天天看點

ffmpeg 快速定位幀-資料整理

原文:https://bbs.csdn.net/topics/391854674

如果直接使用AVSEEK_FLAG_ANY參數,會産生一個問題:針對不同的解碼,有的會花屏,有的會解不出圖像資料。

做視訊分析研究,用matlab很容易得到視訊總幀數,并取得指定的某一幀,用ffmpeg如何實作?

網上找的代碼能實作從頭播放到結尾的功能,如下

//一幀一幀讀取視訊

int

frameFinished=0;

av_seek_frame(pAVFormatContext,videoStreamIndex,0*1000,AVSEEK_FLAG_BACKWARD);

while

(av_read_frame(pAVFormatContext, &pAVPacket) >= 0){

if

(pAVPacket.stream_index==videoStreamIndex){

avcodec_decode_video2(pAVCodecContext, pAVFrame, &frameFinished, &pAVPacket);

if

(frameFinished){

mutex.lock();

sws_scale(pSwsContext,(

const

uint8_t* 

const

*)pAVFrame->data,pAVFrame->linesize,0,videoHeight,pAVPicture.data,pAVPicture.linesize);

//OpenCV顯示一幀圖像信号

Mat rgb_mat=Mat(videoHeight,videoWidth,CV_8UC3,pAVPicture.data[0]);

Mat bgr_mat;

cvtColor(out_mat,bgr_mat,CV_RGB2BGR);

imshow(

"Show"

,bgr_mat);

mutex.unlock();

}

}

av_free_packet(&pAVPacket);

//釋放資源,否則記憶體會一直上升

sleep(100);

}

其中av_seek_frame的第三個參數(n*1000)為定位到第n秒開始。

實際操作發現如下問題:

1.av_seek_frame不準。 用暴風影音播放器嚴格對照每一秒,參數n=19,20,21,實際都定位到了19秒上,接着就直接22秒了,20,21秒無法定位。

2.循環三遍才真正捕獲到圖像。第一遍pAVPacket.stream_index==videoStreamIndex(第5行)為假,第二遍frameFinished(第7行)為0。

視訊中有關鍵幀概念,視訊是分塊壓縮存儲,每一塊有一個關鍵幀,其他幀隻記錄與關鍵幀不同的地方以節省存儲空間。

對于第一個問題,AVSEEK_FLAG_BACKWARD是從指定的時間點向前尋找最近的關鍵幀,是以很可能19,20,21秒在一個分塊内,它們的關鍵幀是同一幀。

不過目标依舊沒有實作,繼續研究。

最近也在研究,先用av_seek_frame跳到最近的關鍵幀(I幀)

然後循環讀幀,直到你需要的位置。

如果直接使用AVSEEK_FLAG_ANY參數,會産生一個問題:針對不同的解碼,有的會花屏,有的會解不出圖像資料。

繼續閱讀