前面兩篇博文介紹到了CvCapture_FFMPEG,這個類的聲明與定義都在cap_ffmpeg_impl.hpp這個頭文件裏
在CvCapture_FFMPEG衆多方法中,
bool open( const char* filename );
void close();
bool grabFrame();
bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn);
bool processRawPacket();
以下5個函數是最核心的功能
1、open 打開視頻流
2、close 關閉視頻流
3、grabFrame 程序內部獲取幀
4、retrieveFrame 將幀數據導出
5、processRawPacket 處理原始包
這個5個函數對ffmpeg視頻處理功能進行了封裝,每一個函數都可以看出ffmpeg在視頻流處理過程中的流程邏輯,而這5個函數中更爲核心的是open和grabFrame函數
open()簡化處理流程如下:
bool CvCapture_FFMPEG::open( const char* _filename )
{
...
close();
...
ic = avformat_alloc_context();
...
av_dict_set(&dict, "rtsp_transport", "tcp", 0);
...
int err = avformat_open_input(&ic, _filename, input_format, &dict);
...
err = avformat_find_stream_info(ic, NULL);
...
for(i = 0; i < ic->nb_streams; i++)
{
AVCodecContext *enc = ic->streams[i]->codec;
...
if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0)
{
// backup encoder' width/height
int enc_width = enc->width;
int enc_height = enc->height;
AVCodec *codec;
codec = avcodec_find_decoder(enc->codec_id);
...
avcodec_open2(enc, codec, NULL);
...
video_stream = i;
video_st = ic->streams[i];
...
picture = av_frame_alloc();
...
}
}
...
}
grabFrame()函數簡化處理流程如下:
bool CvCapture_FFMPEG::grabFrame()
{
...
// get the next frame
while (!valid)
{
av_packet_unref (&packet);
...
int ret = av_read_frame(ic, &packet);
if( packet.stream_index != video_stream )
{
av_packet_unref (&packet);
...
continue;
}
...
if (rawMode)
{
valid = processRawPacket();
break;
}
...
// Decode video frame
avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet);
// Did we get a video frame?
...
}
...
}
看完opencv的源碼,你會發現,以前搜索的ffmpeg樣例和opencv的基本上沒什麼差別,ffmpeg獲取視頻流的處理流程基本上一樣,只是版本之間可能會有一些細微的差別