actrontec / qtffmpegwrapper

Automatically exported from code.google.com/p/qtffmpegwrapper
Other
0 stars 0 forks source link

Wrong frame number with H.264 #18

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
The current QVideoDecoder code assumes that packet.dts values are equivalent to 
frame numbers (i.e. start from 0 and are incremented by one with each 
successfully read packet). However, this does not hold for all video codecs 
(such as H.264), according to my experience. The effect is that such videos are 
unable to be played back or at least seeked correctly. See 
http://www.auby.no/files/video_tests/h264_720p_mp_3.1_3mbps_aac_shrinkage.mp4 
for a sample behaviour.

The proposed fix is based on the implementation in Blender 
(https://svn.blender.org/svnroot/bf-blender/trunk/blender/source/gameengine/Vide
oTexture/VideoFFmpeg.cpp):

*** In bool QVideoDecoder::decodeSeekFrame(int after) *** 

REPLACE

int f = packet.dts;

WITH

double m_baseFrameRate = av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate);
double timeBase = av_q2d(pFormatCtx->streams[videoStream]->time_base);
int64_t startTs = pFormatCtx->streams[videoStream]->start_time;
if (startTs == AV_NOPTS_VALUE) startTs = 0;
int f = (long)((packet.dts-startTs) * (m_baseFrameRate*timeBase) + 0.5);

*** In bool QVideoDecoder::seekFrame(int64_t frame) ***

REPLACE

//printf("\t avformat_seek_file\n");
if(ffmpeg::avformat_seek_file(pFormatCtx,videoStream,0,frame,frame,AVSEEK_FLAG_F
RAME)<0)

WITH

double m_baseFrameRate = av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate);
double timeBase = av_q2d(pFormatCtx->streams[videoStream]->time_base);
int64_t startTs = pFormatCtx->streams[videoStream]->start_time;
if (startTs == AV_NOPTS_VALUE) startTs = 0;
double preSeek = 1*getFPS(); //ffmpeg bug?: with H.264 avformat_seek_file often 
seeks not in a keyframe, thus the following avcodec_decode_video2 iterations 
may go past desiredDts
int desiredDts = (frame-0.5-preSeek) / (m_baseFrameRate*timeBase) + startTs;
if (desiredDts<startTs) desiredDts = startTs;

//printf("\t avformat_seek_file to %d (pts %d)\n", frame, desiredDts);
if(ffmpeg::avformat_seek_file(pFormatCtx,videoStream,-0x7ffffffffffffff,desiredD
ts,desiredDts,AVSEEK_FLAG_BACKWARD)<0)

Original issue reported on code.google.com by msimonov...@gmail.com on 21 Oct 2013 at 3:28

GoogleCodeExporter commented 9 years ago
Platform information: Win32, ffmpeg zeranoe build from 20-Oct-2013, wrapper 
from May 7 2013 with the fixes from "Issue 17" (note that the reported behavior 
was the same with the original version).

Original comment by msimonov...@gmail.com on 21 Oct 2013 at 3:32