原文: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);
}
2.循环三遍才真正捕获到图像。第一遍pAVPacket.stream_index==videoStreamIndex(第5行)为假,第二遍frameFinished(第7行)为0。
视频中有关键帧概念,视频是分块压缩存储,每一块有一个关键帧,其他帧只记录与关键帧不同的地方以节省存储空间。
对于第一个问题,AVSEEK_FLAG_BACKWARD是从指定的时间点向前寻找最近的关键帧,所以很可能19,20,21秒在一个分块内,它们的关键帧是同一帧。
不过目标依旧没有实现,继续研究。
最近也在研究,先用av_seek_frame跳到最近的关键帧(I帧)
然后循环读帧,直到你需要的位置。
如果直接使用AVSEEK_FLAG_ANY参数,会产生一个问题:针对不同的解码,有的会花屏,有的会解不出图像数据。