基於FFmpeg的Dxva2硬解碼及Direct3D顯示(二)


解析視頻源

說明:這篇博文分為“獲取視頻流”和“解析視頻流”兩個部分,使用的是FFmpeg4.1的版本,與網上流傳的低版本的API有一定的區別。

獲取視頻流

  1. 首先需要創建一個AVFormatContext對象,其包含了很多視頻的基本信息;

    m_pFmtCtx = avformat_alloc_context();
    
  2. 打開視頻源,可以通過rtsp協議,也可以直接打開本地視頻文件,或者讀取內存中的數據。

    通過rtsp協議:

     // 以下兩種rtsp格式都是可以的,主碼流:main,子碼流:sub,這里拉取h.264裸碼流
     //const char * rtsp = "rtsp://admin:密碼@相機ip/main/Channels/1";
     const char * rtsp = "rtsp://admin:密碼@相機ip:554/h264/ch1/main/av_stream";
    
    AVDictionary* options = NULL;
    av_dict_set(&options, "stimeout", "20000", 0);		// 連接超時
    av_dict_set(&options, "rtsp_transport", "tcp", 0);	// 設置tcp連接,默認為udp,在網絡環境不好的情況下可能會丟包
    
    // 打開視頻源
    avformat_open_input(&m_pFmtCtx, rtsp, NULL, &options);
    

    打開本地文件:

    const char * fileName = "C://localfile.mp4";
    
    // 打開視頻源
    avformat_open_input(&m_pFmtCtx, fileName, NULL, NULL);
    

    讀取內存中的數據:

    unsigned char * pIOBuffer = (unsigned char *)av_malloc(32768);	// 其它大小也是可行的
    
    // 第一個參數是為AVIOContext申請的內存地址
    // 第二個參數是每次讀取數據的大小,如無要求一般設為4kb
    // 第三個參數是buffer是否可寫
    // 第四個參數是refilling(填寫)buffer數據回調函數
    // 第五個參數是將buffer寫入磁盤的回調函數
    // 第六個參數是移動讀寫指針的位置回調函數
    AVIOContext * pAVIO = avio_alloc_context(pIOBuffer, 32768, 0, NULL, ReadData, NULL, NULL);	// ReadData 為自己實現的回調函數
    
    m_pFmtCtx->pb = pAVIO;
    // 打開視頻源
    avformat_open_input(&m_pFmtCtx, "", NULL, NULL);
    

解析視頻流

  1. 查找視頻流並獲得對應的軟解碼器。

    // 解析數據流信息
    avformat_find_stream_info(m_pFmtCtx, NULL);
    // 查找視頻流
    // AVCodec * m_pDecoder; // 解碼器
    int m_videoIndex = av_find_best_stream(m_pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &m_pDecoder, 0);
    
    // AVStream * m_pVideoStream; // 視頻流
    m_pVideoStream = m_pFmtCtx->streams[m_videoIndex];
    
  2. 初始化解碼器上下文

    // AVCodecContext * m_pDecoderCtx;
    m_pDecoderCtx = avcodec_alloc_context3(m_pDecoder);
    // 初始化
    avcodec_parameters_to_context(m_pDecoderCtx, m_pVideoStream->codecpar);
    // 打開解碼器,亦即初始化 m_pDecoderCtx
    avcodec_open2(m_pDecoderCtx, m_pDecoder, NULL);
    
  3. 初始化解碼器上下文的幀率

    m_pDecoderCtx->framerate = av_guess_frame_rate(m_pFmtCtx, m_pVideoStream, NULL);
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM