zoukankan      html  css  js  c++  java
  • 基于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);
      
  • 相关阅读:
    RAID、LVM和btrfs文件系统
    RAID、LVM和btrfs文件系统
    python实现二分叉查找
    python实现二分叉查找
    python实现二分叉查找
    python实现二分叉查找
    java集合的简单用法
    java集合的简单用法
    java集合的简单用法
    用 AJAX 读取xml 节点属性值
  • 原文地址:https://www.cnblogs.com/huluwa508/p/10304386.html
Copyright © 2011-2022 走看看