-
Notifications
You must be signed in to change notification settings - Fork 87
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
Allow to get/set average frame rate #31
Conversation
Hi @rkfg! Thanks for patch. I merge it now, but... could you please provide some sample for this API using? I suggest take a some exists one, rename and show this API using. Thanks! |
Oh, sure! This was my personal pain and took me a whole day to figure out while digging through the ffmpeg (both libav and the cli utility) sources but the damn thing always put 1k fps no matter what I set. And the server at the local TV station was going mad because of 1000 fps. I found that it's a hardcoded mkv timebase and there's no way to change it without changing the source. Still, all other mkvs I had on hand sure showed normal fps like 25 or 30. So I was stuck for days but in the end left it as is because it worked good enough for us. At the time I just put 1/25 timebase to the stream parameters after writing the headers and while it worked it was incorrect and hacky. Like, mkvinfo said I had 0.9 sec of video and 35 sec of audio (the true duration) and mpv showed a lot of dropped frames. But finally I found the line in the ffmpeg utility that set this parameter and to my surprise it helped! That's the story. I'll provide an example, though it mostly applies to mkv only (which we need because of subtitles), MP4 afaik doesn't have a forced timebase. |
Hmm, now that I started to look into it more closely it becomes all confusing. This source says that Try encoding an MKV file with this patch: diff --git a/example/api2-samples/api2-scale-video.cpp b/example/api2-samples/api2-scale-video.cpp
index 0dda886..bf48f30 100644
--- a/example/api2-samples/api2-scale-video.cpp
+++ b/example/api2-samples/api2-scale-video.cpp
@@ -93,7 +93,7 @@ int main(int argc, char **argv)
OutputFormat ofrmt;
FormatContext octx;
- ofrmt.setFormat("flv", out);
+ ofrmt.setFormat("mkv", out);
octx.setFormat(ofrmt);
Codec ocodec = findEncodingCodec(ofrmt);
@@ -129,7 +129,7 @@ int main(int argc, char **argv)
//
// RESCALER
//
- VideoRescaler rescaler; // Rescaler will be inited on demaind
+ VideoRescaler rescaler(encoder.width(), encoder.height(), encoder.pixelFormat());
// I fixed the rescaler, the on demand init doesn't actually work as the rescaler doesn't know the target width/height (and I couldn't figure out why it should in the first place). So, I guess replacing or adding the |
Oh, I really don't know; another check of the encoded file (without setting the
So both fields are there and they must have different meanings and use cases. That's fine but I think about making it easier to use for the user because this discrepancy is really obscure and is not documented well. Maybe it's still fine to have two getters and setters but we need to spice it up with some commentary about what is what. Also: this SO question and this, linked from there. It seems to be tied to the encoder used. Well, shit. |
Just collect useful links here.
|
Regarding OpenCV, that's for getting the frame rate but it doesn't say anything about setting one which is the point of this PR. This line from kodi is interesting: if (m_bMatroska && pStream->avg_frame_rate.den && pStream->avg_frame_rate.num) So this parameter is only used (or important) explicitly for MKV it seems. But I couldn't find a way to access the format context from within the stream, and I'm not sure it's a good idea either in terms of incapsulation. We could add a FormatContext reference to the Stream class so it could check what the outer format is and apply the framerate accordingly but it smells of overengineering to me. As a compromise, we could add About the original request concerning an API example, would it be ok to just modify the existing one so that it rescales video and saves it to an MKV file (instead of FLV)? I made just that and also added comments about setting the framerate and why it's important. |
This is important for containers with predefined timebase like Matroska with fixed 1 ms timebase. Without setting the average FPS manually you'll get 1000 fps (or 1k) as a result. It's usually not the true FPS but rather a best guess by the tools like ffprobe. Still, it looks ugly and can confuse less intelligent tools like TV software. Note that
setFrameRate()
doesn't help in this case hence introducing a new method.