2011-03-10 58 views
14

有誰知道如何在FFmpeg中實現以秒(或毫秒)爲單位的搜尋。我目前使用av_read_frame()有一個循環遍歷視頻幀,我想確定這個幀應該在幾秒鐘內到達的時間。如果它達到某個點,那麼我想在視頻中尋找一個稍後的點。順便說它不是視頻播放器,只是處理幀。我聽說我應該能夠從數據包中獲得dts或pts,但其始終返回0.如何在FFmpeg中尋找C/C++

+0

要知道,在編解碼器是不是有些代碼「我只架,」你可能會得到垃圾前幾尋找之後的幀,直到ffmpeg獲得足夠的信息給你一個完整的幀。自從我嘗試了一段時間,但AFAIK,這仍然是事實。 ffmpeg假設你是一個玩家,並且不關心幾幀出錯,或者你正在直接處理並依次獲取所有幀。如果情況並非如此,那麼您可能遇到諸如MPEG4之類的問題。 – wrosecrans 2011-11-04 03:30:20

+0

@wrosecrans非常感謝那些信息。我遇到了像你所解釋的一些奇怪現象,並且我瞭解到試圖尋找關鍵幀是要走的路。如果你試圖尋找不是關鍵幀的視頻的一部分,那麼你會得到一些奇怪的輸出一秒鐘。 – DRiFTy 2011-11-04 12:29:53

回答

12

注意:這是過時的,它應該仍然有效,但現在有av_seek_frame()正式執行它。

我沒有寫這一點,但這裏是從樣品我

bool seekMs(int tsms) 
{ 
    //printf("**** SEEK TO ms %d. LLT: %d. LT: %d. LLF: %d. LF: %d. LastFrameOk: %d\n",tsms,LastLastFrameTime,LastFrameTime,LastLastFrameNumber,LastFrameNumber,(int)LastFrameOk); 

    // Convert time into frame number 
    DesiredFrameNumber = ffmpeg::av_rescale(tsms,pFormatCtx->streams[videoStream]->time_base.den,pFormatCtx->streams[videoStream]->time_base.num); 
    DesiredFrameNumber/=1000; 

    return seekFrame(DesiredFrameNumber); 
} 

bool seekFrame(ffmpeg::int64_t frame) 
{ 

    //printf("**** seekFrame to %d. LLT: %d. LT: %d. LLF: %d. LF: %d. LastFrameOk: %d\n",(int)frame,LastLastFrameTime,LastFrameTime,LastLastFrameNumber,LastFrameNumber,(int)LastFrameOk); 

    // Seek if: 
    // - we don't know where we are (Ok=false) 
    // - we know where we are but: 
    // - the desired frame is after the last decoded frame (this could be optimized: if the distance is small, calling decodeSeekFrame may be faster than seeking from the last key frame) 
    // - the desired frame is smaller or equal than the previous to the last decoded frame. Equal because if frame==LastLastFrameNumber we don't want the LastFrame, but the one before->we need to seek there 
    if((LastFrameOk==false) || ((LastFrameOk==true) && (frame<=LastLastFrameNumber || frame>LastFrameNumber))) 
    { 
     //printf("\t avformat_seek_file\n"); 
     if(ffmpeg::avformat_seek_file(pFormatCtx,videoStream,0,frame,frame,AVSEEK_FLAG_FRAME)<0) 
     return false; 

     avcodec_flush_buffers(pCodecCtx); 

     DesiredFrameNumber = frame; 
     LastFrameOk=false; 
    } 
    //printf("\t decodeSeekFrame\n"); 

    return decodeSeekFrame(frame); 

    return true; 
} 
+1

太棒了!謝謝回覆!我認爲這看起來應該起作用。一旦我回到我的電腦併發回我的結果,我會試一試。我不知道avformat_seek_file,我正在使用av_seek_frame ......你知道有什麼區別嗎? – DRiFTy 2011-03-10 21:56:10

+0

對不起 - 我只是做了視頻寫作代碼的一部分,我甚至沒有測試過讀者。 – 2011-03-10 22:08:54

+1

馬丁貝克特發佈的方法確實有效,並且允許我在視頻中尋找基於毫秒的特定幀。 – DRiFTy 2011-03-14 16:39:38