-
Notifications
You must be signed in to change notification settings - Fork 149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add initial support for matroska / webm #66
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave this a quick test by enabling mkv
in symphonia-play
and I can see it correctly exposing the right number of tracks for the file. This is really fantastic start!
In addition to the issues noted in the review, please also make sure to put yourself as the author in the Cargo.toml
file for the demuxer, and add yourself to the CONTRIBUTORS
file in the project root.
I tested it using |
symphonia-format-mkv/src/lib.rs
Outdated
buffer.push_back((track, reader.read_boxed_slice_exact(frame_size)?)); | ||
} | ||
} | ||
_ => unreachable!(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This catch-all arm shouldn't be needed since the match covers all cases. If we keep it, then any additions to the Lacing
will fall through to this case and cause a panic in practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I missed it when introducing an enum.
Hey @darksv, The progress is looking good! Sadly, I haven't had much luck in getting anything playing on my end, but I think it's close. I've noted in the review comments where it's getting stuck on my end. There are also some bugs that I need to fix as well. Particularly, |
I added vorbis and remaining AAC codecs. Also fixed two off-by-one errors in |
Having very good results with the latest set of changes! Many of the MKVs I have with Vorbis or AAC audio tracks are working pretty flawlessly, even ones with multiple tracks. Lot's of debug logs though 😅 . I'll push a commit into the main branch that fixes the issue with FLAC tracks in the next day or so. |
I've fixed the issue with For the optimal solution, the extra data for FLAC should just contain the Stream Info block. However, the codec private data provided by MKV contains many of the FLAC metadata blocks which are useless for the decoder and may bloat the extra data substantially if there's stuff like album art embedded into the file. Could you make it so that only the Stream Info block is provided in the extra data? The following code should extract the Stream Info block from the MKV codec private data which you can then add to the CodecParameters. use symphonia_utils_xiph::flac::metadata::{MetadataBlockHeader, MetadataBlockType};
fn get_stream_info_from_codec_private(codec_private: &[u8]) -> Result<Box<[u8]>> {
let mut reader = BufReader::new(codec_private);
let marker = reader.read_quad_bytes()?;
if marker != *b"fLaC" {
return unsupported_error("mkv (flac): missing flac stream marker");
}
let header = MetadataBlockHeader::read(&mut reader)?;
loop {
match header.block_type {
MetadataBlockType::StreamInfo => {
break Ok(reader.read_boxed_slice_exact(header.block_len as usize)?);
}
_ => reader.ignore_bytes(u64::from(header.block_len))?,
}
}
} |
I've just pushed the commit with this change. |
I pushed the changes required for FLAC to work. It should be good the next time you rebase. |
Hey @darksv, Let me know when you think this may be ready for an initial merge. I've been a bit busy with life and other bug reports lately so I haven't been able to keep up with these changes. When you think it may be good to go I can do a more thorough review and suggest changes to get it ready for merging. |
@pdeljanov I think it might be ready for a more detailed review. Right now it still has some rough edges, but it seems to work with the files I tested. CRC validation is not implemented yet and I need to improve handling of broken files. I believe it could be done later, after merging this PR. |
Hey @darksv, First off, thank you for your hard work on this. I'd love to publish this in the upcoming version v0.5.0 release. Aside from the review, before I can merge this there are a few issues that need to be resolved:
While you look into those, I'll start working on a thorough review. Thanks again! EDIT: Don't worry about the rustfmt failure. Symphonia's |
I've fixed all the warnings, including clippy lints. Also changed warnings about ignored elements to debug messages.
Thanks for pointing that out. I will work on this soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm probably going to have to do a second round, there's a lot of code here! 😅
Just some general comments:
-
In the current definition of the API, any error returned by
FormatReader
is basically fatal to demuxing (aside fromResetRequired
). Please make sure that if you return an error that it's not possible to continue by skipping/ignoring the damaged element, cluster, or track. Of course, there is balance to be had here. We shouldn't complicate the code to try and handle completely messed up files, but if it's possible to be more tolerant of damaged files we should try. I made comments in a few locations where I think this could be done. -
Since Symphonia is a library, we should not do anything that can panic (e.g.,
assert
,unwrap
, etc.). Anything fatal should return an error. I've added comments where I think this may be a problem. Usingdebug_assert
should be fine, but still should be reserved for truly exceptional circumstances.
Thanks!
symphonia-format-mkv/src/ebml.rs
Outdated
header | ||
} | ||
}; | ||
assert_eq!(header.etype, E::ID, "reading invalid element"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure this would never occur in production.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrote this function so it doesn't read the EBML header implicitly and improved messages inside the assertions.
symphonia-format-mkv/src/ebml.rs
Outdated
// TODO: ignore crc for now | ||
continue; | ||
} | ||
assert_eq!(header.etype, E::ID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure this would never occur in production.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replaced with just a log::warn
symphonia-format-mkv/src/ebml.rs
Outdated
Some((ty, _)) => { | ||
assert_eq!(header.data_pos, self.reader.pos(), "invalid stream position"); | ||
if let (Some(cur), Some(end)) = (self.current, self.end) { | ||
assert!(cur.pos + cur.len <= end, "invalid stream position"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replaced this assertion with a DecodeError
Found a couple more issues:
|
Oh, funny, after your changes, I now get |
Sorry, last week I wasn't able to work on this. I'll try to get back to fixing remaining issues today.
Interesting... I'll look into it. This probably should be fixed by skipping data in the stream until a valid tag is found. |
@pdeljanov I've pushed some changes with handling of clusters with unknown sizes. Let me know if this fixes your issue. |
Hi @darksv, No problem, take your time! I get a panic instead of an error now. Please see the backtrace below:
|
@pdeljanov Please check whether recent changes fix this. |
Nice work @darksv, the file plays now! |
Hi @darksv, I think for the most part all the comments have been addressed. There are two issues though:
Are those going to be easy to fix? I'd like to publish v0.5 early next week. However, if you think it would take longer than that to fix those issues, then we can target v0.5.1 for MKV support instead. I feel the first issue may be a show-stopper for many users so it probably wouldn't make sense to include it in v0.5 as-is. |
…o read the whole file in `MkvReader::try_new`
Thank you @darksv! I, and I'm sure many other people, appreciate the work you've put into implementing this. |
Hi! This PR adds an initial support for matroska and webm containers that is intended to close #63. It is far from complete, but I decided to share what I have so far to get some feedback.