-
Notifications
You must be signed in to change notification settings - Fork 26
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
Refactor OggStreamReader
and provide precise seek
#94
base: master
Are you sure you want to change the base?
Refactor OggStreamReader
and provide precise seek
#94
Conversation
I'm opening a draft PR since it's quite a large change. As soon as I'm done with other tasks I'll switch. But earlier comments and critics are welcome! |
Some things I forgot to write:
|
@TonalidadeHidrica thanks I'll take a look tomorrow. |
@est31 Thanks a lot, but there's no rush! |
You can make a trait containing the common methods of OggStreamReader and SeekableOggStreamReader, impl it for OggStreamReader, and then forward the calls into |
Is this still being worked on? |
The implementations are working correctly in my product so I'm currently waiting for a review. Also, I'm busy recently so if I receive a review, I will not be able to respond instantly. |
@@ -29,12 +29,12 @@ required-features = ["ogg"] | |||
[dependencies] | |||
byteorder = "1.0" | |||
tinyvec = { version = "1.0", features = ["alloc"] } | |||
ogg = { version = "0.8", optional = true } | |||
ogg = { version = "0.8", optional = true, path = "../ogg/" } |
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.
Wow what happened here
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.
So it seems like you have a local edition of the ogg
crate, which I can't find anywhere and thus can't build. :( Mind at least pushing the fork somewhere?
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 patching ogg
crate at RustAudio/ogg#18 and RustAudio/ogg#22 as well, and since this PR depends on those PRs, this temporary measure is taken to handle this. We can remove it after they are merged.
Alright then it's just up the RustAudio to review this then... which seems to be taking a while, this was last commented on by a org member 3 months ago. Do you already have a branch of |
@JackRedstonia |
based and forked |
Just to clarify, the |
@JackRedstonia Oops, sorry. You're right. |
Sorry I'm a bit busy atm. I think first the ogg PRs need to be reviewed, then this PR. |
On getting the stream length, from my understanding, the steps needed are:
Is this correct? |
@JackRedstonia one also has to take the first packet's absolute granule pos into account, but other than that, yes it's accurate. |
wait no, one doesn't have to take the length of the last packet into account, but the length of the first packet. Absolute granule positions always refer to the last sample offset of the last packet finished on the page. |
I don't actually remember the code I wrote few months ago, but now I'm wondering that |
What is the correct way to use SeekableOggStreamReader? I am currently testing the code in this branch. If I call |
@hf29h8sh321 I'm very sorry to leave it undocumented. Since I'm quite busy and sleepy I cannot currently give you a precise example now, but perhaps seeing this file might help you. Sorry for the inconvenienve. |
I copied that file into my project, and I cannot get any audio data after seeking. Calls to |
Hmm, at least it works for almost all of my ogg files, so there should be some difference... |
@hf29h8sh321 Did you check out this messy gist of mine? (I'm not confident it would work right now...) |
I have narrowed down the issue. I ran the code in the gist, which works with my own files. However, I then modified the code and removed this line: It seems like seeking into the middle of the stream without reading it without seeking first causes the error. |
I think if you remove first 2000 bytes or so of the audio file. it should work properly. Thats where all the "garbage" data is stored. |
@hsi3322 Can you elaborate on what you mean by "garbage data"? |
1a9ca88
to
f655fa2
Compare
Thanks for keeping this PR alive! This is the single biggest issue of the lewton crate at the moment, I think. |
You're welcome! The seeking is in fact crucial part of my project, and the feature has actually been thoroughly tested through my actually using. I'll resolve the conflict when I have time, and of course review is always welcome, in that case I'll respond to it as soon as I can. |
@est31 @TonalidadeHidrica Any updates on merging this PR? |
Current
OggStreamReader
has several issues:get_last_absgp
provides insufficient information in some case (closes get_last_absgp returns None for the first stream #84) and may not work for chained streams (closes get_last_absgp may not work properly for chained streams #87)We cannot obtain the length of stream(Utility function to get a vorbis stream's length #95): this is still unimplementedSeek
(Unnecessary Seek for decoders - prevents internet radio rodio#333) (Well, I know you may disagree about this)So I implemented a sample-level seek.
Changes in API
OggStreamReader
does no longer requireio::Seek
. Therefore it does not provideseek_absgp_pg
.SeekableOggStreamReader
is provided. This struct comes withseek_absgp
, where users can seek the reader in sample-level.OggStreamReader
andSeekableOggStreamReader
is dedicated to only a single stream. If you want to parse chained stream, you have to create a new one.next_stream(self) -> Option<OggStreamReader>
that consumes the reader, checks if the next packet exists, and returns if exists.ident_hdr
,comment_hdr
, andsetup_hdr
is no longer public. Now they can be accessed only immutably through the corresponding getter functions.Issues & Future Task
One major issue is that the page absgp in real-world ogg/vorbis file often contains errors. Specifically, each of the ogg files I have has 3-20 errors, classified to the following two types:
absgp
for the former page is wrong. In specific, all of the ogg files I have use "long" blocks of length 2048 and "short" blocks of length 512, and the absgp for the former page sometimes differs by 448. This type of error was found in almost all the ogg files I have.If the absgp provided in the pages has an error, then the seek result may be wrong, especially for the first type of error mentioned above. I'm now wondering that I've mistook some spec of the Vorbis stream, or this is the bug of many Vorbis encoders (all I have of which is based on libvorbis by the way).
Yeah, it's only 448 frames in ~44100 fps data, so the diff is 0.01 seconds, so we may not have to care about that though.
Speaking about the incompatibility with the spec, I also realized that most of the ogg files does not follow the spec that " the second finished audio packet must flush the page on which it appears and the third packet begin a fresh page". I implemented the dropping-leading-samples features based on this fact, but it does not actually run for most of the files. Anyway I followed the another requirement in the spec that "Failure to do so should, at worst, cause a decoder implementation to return incorrect positioning information for seeking operations at the very beginning of the stream". At any rate, most of the ogg files starts with absgp 0, which means that we don't have to drop the initial frames at all.
Here are the other tasks and concerns:
async
feature yet.And here are the issues I'll handle at last: