FFmpeg encoded videos play too fast

I looked at the results of Google / SO / Zeranoe and tried to integrate everything that I found into the fact that my program generates the video correctly, but I still cannot get it to work correctly.

I needed a good video to use as a link, so I ran:

ffmpeg -t 5 -f dshow -i "video=Logitech HD Pro WebcamC910" CLI.mpg 

Generated a five-second video that can be played in the VLC, and shows the duration and plays correctly. You can get the video here: https://drive.google.com/file/d/0B1VGi1Ts7D7TR3c4VUlyM2dIcFk/edit?usp=sharing

Then I created a five second video with my own code. I tried to figure out what, in my opinion, is necessary for the recording. The code can be found here: https://drive.google.com/file/d/0B1VGi1Ts7D7TMnFxSE1HX2FKbEU/edit?usp=sharing

It also generated video with similar video quality, but VLC does not show the duration of the video, and the video seems to play too fast. I mean, what I see on the screen seems to be moving too fast. You can find the video created here: https://drive.google.com/file/d/0B1VGi1Ts7D7TSzFGUFZEMHJwQ0U/edit?usp=sharing

Even when you click on the links to the video, you can see that Google is having problems with mine, but there is no problem with the one generated by the CLI FFmpeg. Sorry that I posted everything outside the site, but I did not want to spam my code in the message, and I wanted to provide as much information as possible.

I have seen several posts about this, but I cannot find a final solution.

EDIT: So I implemented your suggestions, and I'm sure your answer fixed the synchronization problem, but now I get 20 not strictly monotonous errors until the first successful call to encode_video. This happens if I use

 gFrame->pts = gFrameIndex; 

or

 gFrame->pts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->codec->time_base); 

before

 ret = avcodec_encode_video2(gCodecContext, &pkt, gFrame, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding frame\n"); return false; } 

This seems to match the video artifacts at the beginning of the video file during playback. gFrameIndex starts at 1.

I believe that my webcam automatically focuses at the beginning of recording, is it possible that this is due?

I uploaded the generated .h264 file to https://drive.google.com/file/d/0B1VGi1Ts7D7TRjRzbzZZemRaRTA/edit?usp=sharing and my latest code is https://drive.google.com/file/d/0B1VGi1Ts7D7TymtYmTymTymTymTymTymTymTymTymTymTymTymTyMTyzTlmY usp = sharing .

I really appreciate the help. Unfortunately, I cannot use the FFmpeg CLI directly in my software, so I need to use the library. I will need to continue shipping along with him if you cannot offer a better alternative.

+2
source share
1 answer

Usually, before calling avcodec_encode_video2() you set the timestamp of the frame, for example:

 gFrame->pts = gFrameIndex; 

gFrameIndex incremented by 1 each encoded frame, which should be correct in your case, because your time_base is 1/30, and each frame represents 1 / 30th of a second.

Then be careful:

  if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(gCodecContext->coded_frame->pts, gCodecContext->time_base, gStream->time_base); if (pkt.dts != AV_NOPTS_VALUE) pkt.dts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->time_base); 

Are you having problems because you use libx264 for encoding? I noticed that in this case you need to rescale the timestamps before and after calling avcodec_encode_video2() , for example:

 gFrame->pts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->codec->time_base); [...] avcodec_encode_video2() [...] pkt.pts = av_rescale_q(pkt.pts, gStream->codec->time_base, gStream->time_base); pkt.dts = av_rescale_q(pkt.dts, gStream->codec->time_base, gStream->time_base); 

This is because the ffmpeg interface with libx264 not very high quality.

Is your webcam discarded? If so, you will need to provide frames with real timestamps. Create a function that returns the elapsed time since the capture began in milliseconds (integer). Then set time_base to {1,1000} and set gFrame->pts to the return value of your function. But be careful: you do not have a timestamp that is equal to <= previous timestamp. Therefore, you will need to drop frames if you get several at once (or write another mechanism to solve this situation). BTW, all this is done for you in the CLI ffmpeg program, so few people try to use the ffmpeg library ...

+1
source

Source: https://habr.com/ru/post/1209001/


All Articles