-
Notifications
You must be signed in to change notification settings - Fork 5
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 seeking #14
Add seeking #14
Conversation
c_src/xav/reader.c
Outdated
|
||
avcodec_flush_buffers(reader->c); | ||
|
||
if (av_seek_frame(reader->fmt_ctx, reader->stream_idx, frmseekPos, AVSEEK_FLAG_BACKWARD) < 0) { |
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.
In my test video, there is a keyframe every second with a framerate of 25 fps. But when i seek, i can only get to frames which are a multiple of 250 frames...couldn't figure out where the issue is. Maybe we have to explicitly calculate P frames?
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.
That was indeed the issue! av_seek_frame
does only seek to an I frame and you have to send packets to the decoder until you reach the desired timestamp. After some checking i confirmed that my test file had a keyframe every 10 seconds instead of every 1 seconds
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.
Nice, I am impressed!
c_src/xav/reader.c
Outdated
int64_t frmseekPos = av_rescale_q( | ||
(int64_t)(time_in_seconds * AV_TIME_BASE), | ||
AV_TIME_BASE_Q, | ||
reader->fmt_ctx->streams[reader->stream_idx]->time_base | ||
); |
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 think that what we need to do here is to convert time_in_seconds to frame number. Given that time_base is 1/fps we should do time_in_seconds * time_base.den / time_base.num so :
int64_t frmseekPos = av_rescale_q( | |
(int64_t)(time_in_seconds * AV_TIME_BASE), | |
AV_TIME_BASE_Q, | |
reader->fmt_ctx->streams[reader->stream_idx]->time_base | |
); | |
av_rescale(time_in_seconds, time_base.den, time_base.num); |
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.
not exactly..av_seek_frame
expects the seeking position in the same timebase as the selected stream not the frame number. I did some further research and it seems, that this is the correct way to calculate the seeking position and preserving the float accuracy. For example the file in test/fixtures/sample_h264.mp4
has a timebase of 1/15360 and AV_TIME_BASE
is 1000000
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.
Ohh okay 🤦♂️ Could you please add a comment or link some resource that explains what we do here? I mean, what's the difference between AV_TIME_BASE and AVStream.time_base and why we need to use both in this calculation?
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.
Absolutely!
9ff14a7
to
89d7375
Compare
89d7375
to
59e850b
Compare
Perfect, thanks a lot! If we could just add a comment explaining what happens in timestamp calculation, we are ready to merge! |
45115dd
to
79b93de
Compare
Merged, thank you! |
Hey, I saw this in you TODO issue #1 and could need it myself.
I've never written any C code, so I probably made some mistakes, but I hope this will help with some improvements.
I added a function to seek to a time in seconds, which will seek the
reader
.Additionally, I've added the frame rate to the
Reader
struct, so the user can use this information for further calculations