如何用FFmpeg读取内存的PS/TS流,分离出视频和音频

    之前做一个项目遇到一个问题:从网络中收到PS/TS流,需要从中分离出视频和音频,但是FFmpeg只支持标准的几种输入流协议(RTP/HTTP/RTSP/MMS),而我们的协议它不支持,所以就不能够用它来直接做接收。那能否由自己来接收数据然后让FFmpeg读取内存中的数据呢?答案当然是可以的,这就需要用到FFmpeg的探测流格式的功能,主要是用到了两个API: avio_alloc_context, av_probe_input_buffer。前者向FFmpeg传递用户自定义的Read,write, Seek的回调函数,即文件IO操作由用户去管理。下面是函数的原型:

AVIOContext *avio_alloc_context(  
                  unsigned char *buffer,  
                  int buffer_size,  
                  int write_flag,  
                  void *opaque,  
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),//指定从内存中读取的方法,将buf_size字节大小的数据保存到buf  
                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),//对应的这是写内存的函数  
                  int64_t (*seek)(void *opaque, int64_t offset, int whence)); 

     后者则用于探测输入数据的格式,比如采用什么容器封装,这个是内部自动判断的,它会先缓冲一段数据,解析成功后,函数会返回0,如果返回值为负数则表示无法识别格式。

    下面我会实现一个例子,从内存中读取数据,传递给FFmpeg,然后后面的操作就跟读文件一样了。

    第一步,我们要做的工作是:打开一个文件-》创建输入流的上下文-》调用avio_alloc_context函数并传递read_packet函数的地址-》自动探测格式-》打开输入流。代码如下:

AVIOContext* pb = NULL;  
AVInputFormat* piFmt = NULL;  

BOOL bRet = m_file.Open(m_filePath.c_str(), CFile::modeRead);
if(!bRet)
{
   TRACE("OpenFile %s Failed\n", m_filePath.c_str());
   return -3;
}

 uint8_t  * input_buf = (uint8_t*)av_mallocz(sizeof(uint8_t)* BUF_SIZE);  
 pb = avio_alloc_context(input_buf, BUF_SIZE, 0, this, read_data, NULL, NULL);

  //探测从内存中获取到的媒体流的格式  
 if (av_probe_input_buffer(pb, &piFmt, "", NULL, 0, 0) < 0)
 {  
     TRACE("probe format failed\n");  
     return -4;   
 }  
 else
 {  
     TRACE("format:%s[%s]\n", piFmt->name, piFmt->long_name);  
 } 
 m_inpu
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值