opencv with ffmpeg 代碼解析(三)

前面兩篇博文介紹到了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獲取視頻流的處理流程基本上一樣,只是版本之間可能會有一些細微的差別

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章