2

I am using Ffmpeg to decode and play video files. I have currently got the video playing and the audio playing at as fast as the CPU can decode and display them. The problem is that I want to play the video and audio in sync using the system clock.

I've searched around for some help but can't find anything substantial other than dranger's tutorial 05 but I don't really understand what he is doing because my program isn't written in the same way as his.

I am using mjpeg files and so the pts seems to be retrieved every single time a frame is decoded, I have multiplied the pts by the time_base as dranger does to get the value in seconds but the resolution seems to be only seconds and so I get the value "6" 25 times and then "7" 25 times as the video runs at 25 frames per second.

Is there not a more accurate value? Or way to get a more accurate value and if so, how would I go about syncing to this value? I am using SDL to display the value so can I just use a SDL_Delay() of the value I get?

Thanks for your time,

Infinitifizz

Infiniti Fizz
  • 1,726
  • 4
  • 24
  • 40
  • Check to verify that you're using the right type, maybe you're doing the `pts * time_base` calculation as int instead of float. – Nathan Whitehead Jul 18 '11 at 20:30
  • Well the PTS value seems to be in int64t not float or double. – Infiniti Fizz Jul 19 '11 at 08:26
  • Looking at dranger's tutorial, he basically uses the pts of the first packet that makes up the frame as the frame's pts or if that doesn't exist, the packet's dts value. This value is then multiplied by the video time_base (as a double) but is still a uint64_t and so I just get output like: 0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4 etc. rather than anything in milliseconds or anything more accurate than seconds. – Infiniti Fizz Jul 19 '11 at 09:01

1 Answers1

2

To convert pts or dts to floating-point seconds, use av_q2d() on proper time_base:

// You got the context from open_input:
AVFormatContext *pFormatCtx;
avformat_open_input(&pFormatCtx, inputfilename, NULL, &format_opts);

// Get a stream from the context
AVStream pStream= pFormatCtx->streams[i];

// Convert packet time (here, dts) to seconds with:  
double seconds= (dts - pStream->start_time) * av_q2d(pStream->time_base);

// Or convert frame number to seconds with the codec context
AVCodecContext *pCodecCtx= pStream->pVideoStream->codec;
double seconds= framenumber * av_q2d(pCodecCtx->time_base);

This returns time-from-when-the-video-starts in seconds.

hexatron
  • 675
  • 6
  • 9
  • What is "frame" and from where you are getting "dts from"? – Ian Medeiros Jun 27 '12 at 21:11
  • 1
    You probably worked out your issues but for future searchers: `framenumber` is obtained from the `pCodecCtx` and `dts` comes from the `AVPacket` that you get after calling the decode function. – Sam Sep 07 '15 at 08:35