閱讀228 返回首頁    go 技術社區[雲棲]


FFMPEG SDK 開發介紹

FFMPEG SDK 開發介紹

1.簡介:
    ffmpeg是一套可以用來記錄、轉換數字音頻、視頻,並能將其轉化為流的開源計算機程序。
使用ffmpeg能夠完成如下功能:parse,demux,decode,filter(preprocessing),encode,mux,stream和player等.

2.下載和編譯:

    下載地址:  https://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)
        {
            // break ;
        }
        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不解碼)
    // 參考V3代碼: interface IFileDecoder, media/impl/filedecoderimpl.cpp

    {
        // 參考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];
            AVCodecContext *pCodecCtx = pStream->codec;
            // 計算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代碼
        

最後更新:2017-04-03 12:55:10

  上一篇:go C++編程規範指46:如果提供專門的new,應該提供所有標準形式(普通、就地和不拋出)
  下一篇:go 關於android的animation的xml定義中的android:interpolator屬性的含義