ffmpeg解码内存中的数据

本文参考自:ffmpeg 从内存中读取数据(原创:雷霄骅)

需求

最近做一个项目需要播放一些简单的音频,而这些音频以二进制的形式存储在数据库中。而且需要保证音频的音频播放的实时性。故研究下如何从内存数据中解码音频。

开发

原帖中给的代码已经十分详细了。不过有几个需要注意的点原帖中并未提及。

  1. 回调函数filliobuffer中的第一个参数
    int fillIiobuffer(void * opaque, uint8_t * buf, int bufsize)
    
    回调函数内存读取的回调函数中第一个参数其实是在avio_alloc_context函数中第四个参数设置的。
    在回调函数中回将指针传回。这里可以用来标记一些自定义信息。如在我的实际项目代码中用它来传递数据。
    int fillIiobuffer(void * opaque, uint8_t * buf, int bufsize)
    {
    	QByteArray* ba = static_cast<QByteArray*>(opaque);
    	if (ba == nullptr || ba->isEmpty())
    	{
    		return 0;
    	}
    	int realSize = 0;
    	if (bufsize > ba->size())
    	{
    		realSize = ba->size();
    		memset(buf,0,bufsize);
    	}
    	else
    	{
    		realSize = bufsize;
    	}
    	if (!memcpy_s(buf, realSize, ba->data(), realSize))
    	{
    		ba->remove(0, realSize);
    		return realSize;
    	}
    	return 0;
    }
    
    由于回调函数写成了一个全局函数,而其他操作封装到了一个类里面。这里需要将用来存储实际未解码内存数据的成员变量以指针的形式传入回调函数中。
    具体是这样写的。
    bool XRealTimePlayer::openAudioBuf(QByteArray ba)
    {
    	m_AudioData = ba;
    	...
    	AVIOContext *avio = avio_alloc_context(m_iobuffer, 32768, 0, &m_AudioData, fillIiobuffer, nullptr, nullptr);
    	m_AVFormatFromBuf->pb = avio;
    	...
    }
    
  2. 内存的释放
    因为实例需要反复使用,这里就需要进行一些内存释放工作。
    经过反复测试发现只有这样做才不会出错,具体为什么,对不对。我也知道,反正目前没有发现内存泄漏。
    	if (m_AVFormatFromBuf)
    	{
    		//av_free(m_iobuffer);						//注意这里
    		avio_context_free(&m_AVFormatFromBuf->pb);
    		avformat_close_input(&m_AVFormatFromBuf);
    		avformat_free_context(m_AVFormatFromBuf);
    	}
    	m_iobuffer = (unsigned char *)av_malloc(32768);
    	m_AVFormatFromBuf = avformat_alloc_context();
    	AVIOContext *avio = avio_alloc_context(m_iobuffer, 32768, 0, &m_AudioData, fillIiobuffer, nullptr, nullptr);
    	m_AVFormatFromBuf->pb = avio;
    
    应该有些人会注意到,我申请的m_ioBuffer并没有释放。而且这个空间还不小。但它就是没有引起内存泄漏,就是这么神奇。
    如果我把它释放了,就是把//av_free(m_iobuffer);这句注释打开的话。在第三次播放的时候必然堆损坏。不知道为什么。
    在源码中对avio_alloc_context函数第一个参数的注释是这样的。
    /*
     * @param buffer Memory block for input/output operations via AVIOContext.
     *        The buffer must be allocated with av_malloc() and friends.
     *        It may be freed and replaced with a new buffer by libavformat.
     *        AVIOContext.buffer holds the buffer currently in use,
     *        which must be later freed with av_free().
     * /
    
    大概意思就是这个参数可能会被一个新的叫libavformat.AVIOContext.buffer的内存空间取代。而且这个libavformat.AVIOContext.buffer需要进行释放。
    因此经过再次测试我们需要释放libavformat.AVIOContext.buffer这个变量。
    所以释放空间的代码需要这么写
    	if (m_AVFormatFromBuf)
    	{
    		//av_free(m_iobuffer);						//注意这里
    		av_free(m_AVFormatFromBuf->pb->buffer);
    		avio_context_free(&m_AVFormatFromBuf->pb);
    		avformat_close_input(&m_AVFormatFromBuf);
    		avformat_free_context(m_AVFormatFromBuf);
    	}
    	m_iobuffer = (unsigned char *)av_malloc(32768);
    	m_AVFormatFromBuf = avformat_alloc_context();
    	AVIOContext *avio = avio_alloc_context(m_iobuffer, 32768, 0, &m_AudioData, fillIiobuffer, nullptr, nullptr);
    	m_AVFormatFromBuf->pb = avio;
    

具体代码见附件

https://download.csdn.net/download/u014410266/12264898

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值