原文: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參數,會産生一個問題:針對不同的解碼,有的會花屏,有的會解不出圖像資料。