您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
14. 加入生产者消费者模式控制音视频缓冲~1
发布时间:2021-06-10 11:40:18编辑:雪饮阅读()
说到这个缓冲啊,其实需要定义一个最大队列缓冲限制,这样避免耗尽太多内存。
#define XPLAY_IDECODE_H
#include "XParameter.h"
#include "IObserver.h"
#include <list>
//解码接口,支持硬解码
class IDecode:public IObserver
{
public:
//打开解码器
virtual bool Open(XParameter para) = 0;
//future模型发送数据到线程解码
virtual bool SendPacket(XData pkt) = 0;
//从线程中获取解码结果 再次调用会复用上次空间,线程不安全
virtual XData RecvFrame() = 0;
//由主体notify的数据阻塞
virtual void Update(XData pkt);
bool isAudio = false;
//最大的队列缓冲
int maxList = 100;
protected:
virtual void Main();
//读取缓冲
std::list<XData> packs;
std::mutex packsMutex;
};
#endif //XPLAY_IDECODE_H
上篇中只获取了AVMEDIA_TYPE_VIDEO类型的样本字节数,其实对于类型不是AVMEDIA_TYPE_VIDEO的也要获取下样本字节数:cpp/FFDecode.cpp:
最后照旧运行在魅族16T中
#include "XLog.h"
//由主体notify的数据
void IDecode::Update(XData pkt)
{
if(pkt.isAudio != isAudio)
{
return;
}
while (!isExit)
{
packsMutex.lock();
//阻塞
if(packs.size() < maxList)
{
//生产者
packs.push_back(pkt);
packsMutex.unlock();
break;
}
packsMutex.unlock();
XSleep(1);
}
}
void IDecode::Main()
{
while(!isExit)
{
packsMutex.lock();
if(packs.empty())
{
packsMutex.unlock();
XSleep(1);
continue;
}
//取出packet 消费者
XData pack = packs.front();
packs.pop_front();
//发送数据到解码线程,一个数据包,可能解码多个结果
if(this->SendPacket(pack))
{
while(!isExit)
{
//获取解码数据
XData frame = RecvFrame();
if(!frame.data) break;
//XLOGE("RecvFrame %d",frame.size);
//发送数据给观察者
this->Notify(frame);
}
}
pack.Drop();
packsMutex.unlock();
}
}
{
#include <libavcodec/avcodec.h>
}
#include "FFDecode.h"
#include "XLog.h"
bool FFDecode::Open(XParameter para)
{
if(!para.para) return false;
AVCodecParameters *p = para.para;
//1 查找解码器
AVCodec *cd = avcodec_find_decoder(p->codec_id);
if(!cd)
{
XLOGE("avcodec_find_decoder %d failed!",p->codec_id);
return false;
}
XLOGI("avcodec_find_decoder success!");
//2 创建解码上下文,并复制参数
codec = avcodec_alloc_context3(cd);
avcodec_parameters_to_context(codec,p);
codec->thread_count = 8;
//3 打开解码器
int re = avcodec_open2(codec,0,0);
if(re != 0)
{
char buf[1024] = {0};
av_strerror(re,buf,sizeof(buf)-1);
XLOGE("%s",buf);
return false;
}
if(codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
this->isAudio = false;
}
else
{
this->isAudio = true;
}
XLOGI("avcodec_open2 success!");
return true;
}
bool FFDecode::SendPacket(XData pkt)
{
if(pkt.size<=0 || !pkt.data)return false;
if(!codec)
{
return false;
}
int re = avcodec_send_packet(codec,(AVPacket*)pkt.data);
if(re != 0)
{
return false;
}
return true;
}
//从线程中获取解码结果
XData FFDecode::RecvFrame()
{
if(!codec)
{
return XData();
}
if(!frame)
{
frame = av_frame_alloc();
}
int re = avcodec_receive_frame(codec,frame);
if(re != 0)
{
return XData();
}
XData d;
d.data = (unsigned char *)frame;
if(codec->codec_type == AVMEDIA_TYPE_VIDEO)
d.size = (frame->linesize[0] + frame->linesize[1] + frame->linesize[2])*frame->height;
else
//样本字节数 * 单通道样本数 * 通道数
d.size = av_get_bytes_per_sample((AVSampleFormat)frame->format)*frame->nb_samples*2;
return d;
}
关键字词:音视频缓冲
相关文章
-
无相关信息