天天看點

FFMPEG SDK 開發介紹

ffmpeg

sdk 開發介紹

1.簡介:

    ffmpeg是一套可以用來記錄、轉換數字音頻、視訊,并能将其轉化為流的開源計算機程式。

使用ffmpeg能夠完成如下功能:parse,demux,decode,filter(preprocessing),encode,mux,stream和player等.

2.下載下傳和編譯:

    下載下傳位址:  http://ffmpeg.org/download.html

    編譯:

       1)windows平台static library/shared library, 編譯工具:mingw-gcc或者在linux平台下交叉編譯(推薦)

       2)linux平台static library/shared library, 編譯工具:gcc

    子產品:

        libavcodec    - 編碼解碼器

        libavdevice   - 輸入輸出裝置的支援

        libavfilter   - 視音頻濾鏡支援

        libavformat   - 視音頻等格式的解析

        libavutil     - 工具庫

        libpostproc   - 後期效果處理

        libswscale    - 圖像顔色、尺寸轉換

3.sdk介紹和開發(基于ffmpeg 0.8 sdk)

    ffmpeg每部分功能都采用plugin的方式,使用統一的接口調用,這樣就能夠非常友善的使用和擴充。

    plugin分為幾種:muxer,demuxer,protocol,hwaccel,encoder,decoder,parser,bitstream,filter,...

    是以在使用sdk的時候第一步就是注冊plugin

    avcodec_register_all()  : 注冊 hwaccel,encoder,decoder,parser,bitstream

    av_register_all()       : 注冊 muxer,demuxer,protocol

    avfilter_register_all() : 注冊 濾鏡filter

    下面根據不同的應用場景,給出主要的代碼示例(僅是代碼片斷,不一定能編譯通過):

    1)如何擷取媒體檔案的資訊(parser):

    // 參考v3代碼: interface ifiledecoder, media/impl/filedecoderimpl.cpp

    {

        av_register_all();

        avformatcontext * pformatctx = null;

        int err = 0;

        const char *filename = "c:\\test.mp4";

        err = av_open_input_file(&pformatctx, filename, null, 0, null);

        if(err != 0)

        {

            // break ;

        }

        err = av_find_stream_info(pformatctx);

        if(err < 0)

        for(uint32_t i = 0; i < pformatctx->nb_streams; i ++)

            // stream 結構資料

            avstream *pstream = pformatctx->streams[i];

            // 幀率資訊

            avrational framerate = pstream->r_frame_rate;

            // 時間機關比率

            avrational timebase = pstream->time_base;

            // stream duration

            int64_t duration = pstream->duration;

            // 擷取codec資料結構

            avcodeccontext *pcodecctx = pstream->codec;

            avmediatype codectype = pcodecctx->codec_type;

            codecid codecid = pcodecctx->codec_id;

            if(codectype == avmedia_type_video)

            {

                // 擷取video基本資訊

                int width = pcodecctx->width;

                int height = pcodecctx->height;

                pixelformat pixelformat = pcodecctx->pix_fmt;

            }

            else if(codectype == avmedia_type_audio)

                // 擷取audio基本資訊

                int channels = pcodecctx->channels;

                int sample_rate = pcodecctx->sample_rate;

                avsampleformat samplefmt = pcodecctx->sample_fmt;

        // 釋放

        if(pformatctx != null)

            av_close_input_file(pformatctx);

            pformatctx = null;

        }    

    }

    2)讀取sample資料(read raw sample不解碼)

        // 參考parser代碼

        // av_register_all();

        // avformatcontext * pformatctx = null;

        // err = av_open_input_file(&pformatctx, filename, null, 0, null);

        avpacket packet;

        av_init_packet(&packet);

        int ret = av_read_frame(pformatctx, &packet);

        if(ret >= 0)

            int streamindex = packet.stream_index;

            avstream *pstream = pformatctx->streams[streamindex];

            // 計算timestamp

            // 轉換時間到1/1000000秒

            avrational time_base;

            time_base.num = 1;

            time_base.den = 1000000;

            // 25.0     1/25,   29.97    1001/30000

            // 擷取 dts/pts

            const int64_t dts = av_rescale_q(packet.dts, pstream->time_base, time_base);

            const int64_t pts = av_rescale_q(packet.pts, pstream->time_base, time_base);

            uint8_t *data = packet.data;

            int size = packet.size;

            bool iskey = ((packet.flags & av_pkt_flag_key) == av_pkt_flag_key);    

        av_free_packet(&packet);        

    3)解碼sample(video es=>yuv/rgb,  audio es=>pcm)

    // 參考v3代碼: interface ivideodecoder/iaudiodecoder, media/impl/videodecoderimpl.cpp/audiodecoderimpl.cpp

        // 參考parser,read raw sample代碼