Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Files created with a direct stream copy using FFmpeg's libavformat API play back too fast at 3600 fps

I am working on a libavformat API wrapper that converts MP4 files with H.264 and AAC to MPEG-TS segments suitable for streaming. I am just doing a simple stream copy without re-encoding, but the files I produce play the video back at 3600 fps instead of 24 fps.

Here are some outputs from ffprobe https://gist.github.com/chrisballinger/6733678, the broken file is below:

r_frame_rate=1/1
avg_frame_rate=0/0
time_base=1/90000
start_pts=0
start_time=0.000000
duration_ts=2999
duration=0.033322

The same input file manually sent through ffmpeg has proper timestamp information:

r_frame_rate=24/1
avg_frame_rate=0/0
time_base=1/90000
start_pts=126000
start_time=1.400000
duration_ts=449850
duration=4.998333

I believe the problem lies somewhere in my setup of libavformat here: https://github.com/OpenWatch/FFmpegWrapper/blob/master/FFmpegWrapper/FFmpegWrapper.m#L349 where I repurposed a bunch of code from ffmpeg.c that was required for the direct stream copy.

Since 3600 seems like a "magic number" (60*60), it could be as simple as me not setting the time scale properly, but I can't figure out where my code diverges from ffmpeg/avconv itself.

Similar question here, but I don't think they got as far as I did: Muxing a H.264 Annex B & AAC stream using libavformat with vcopy/acopy

like image 783
Chris Ballinger Avatar asked Oct 21 '22 00:10

Chris Ballinger


2 Answers

Actually your pts and dts are messed up.

The MP4 file has pts and dts according to MP4 timebase and you are passing the same pts and dts to the ts muxer which works with 90000Hz clock. for example if your fps is 30 frames per second then in ts it will mean that show a video frame on every 3000 ticks.

you should use av_rescal_q to change the pts from mp4 to ts timbase .

like image 162
Harit Vishwakarma Avatar answered Oct 27 '22 10:10

Harit Vishwakarma


It took a while, but this is the answer: https://stackoverflow.com/a/16903982/805882

packet.pts = av_rescale_q(packet->pts, inStream->time_base, outStream->time_base);
packet.dts = av_rescale_q(packet->dts, inStream->time_base, outStream->time_base);
like image 41
Chris Ballinger Avatar answered Oct 27 '22 11:10

Chris Ballinger