您的位置:首页 > 娱乐 > 明星 > 解码器类的实现【4】

解码器类的实现【4】

2024/12/23 15:11:12 来源:https://blog.csdn.net/weixin_45690131/article/details/139776271  浏览:    关键词:解码器类的实现【4】

.h文件

#pragma once
#include <mutex>
#include <iostream>extern "C"
{
#include "libavcodec/avcodec.h"//解码}
#pragma comment(lib,"avcodec.lib")//解码class XDecode
{
public:XDecode();virtual ~XDecode();//打开解码器,不管成功与否都要释放codecPar的空间,virtual bool Open(AVCodecParameters* codecPar, bool isNeedClaerParam = false);//清空codec读取缓存virtual void Clear();//清理codec上下文的内存空间virtual void Close();//将包发送到解码线程,不管成功与否都要释放pkt的空间,(对象空间和数据空间)virtual bool Send(AVPacket* pkt);//解码后数据,一次send可能需要多次recevie,获取缓冲中的数据需要send null再次多次获取//每次复制一份要由调用者释放 av_frame_free() virtual AVFrame* Receive();public:bool isAudio = false;protected:AVCodecContext* codec = NULL;std::mutex mux;};

.cpp文件

#include "XDecode.h"using namespace std;XDecode::XDecode()
{}
XDecode::~XDecode()
{}//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-////打开解码器
bool XDecode::Open(AVCodecParameters* codecpar, bool isNeedClaerParam)
{if (!codecpar) return false;//没有参数传进来,没有拿到解封装后的流媒体参数,无法找到解码器this->Close();/************************音频、视频 解码器的打开******************///找到解码器idAVCodec* vcodec = avcodec_find_decoder(codecpar->codec_id);if (!vcodec){//释放参数空间,之前解封装类传出了分配了内存的codecpar,并且对音频和视频参数分开传了if (isNeedClaerParam)//给一个参数确定是否需要清理{avcodec_parameters_free(&codecpar);}cout << "can't find the codec id : " << codecpar->codec_id << endl;return false;}cout << "avcodec_find_decoder(codec_id) : " << codecpar->codec_id << endl;mux.lock();//上锁//创建解码器上下文,只有出错才直接释放空间 avcodec_free_context(&codec);codec = avcodec_alloc_context3(vcodec);//配置解码器上下文参数,可以通过参数传递avcodec_parameters_to_context(codec, codecpar);//释放参数空间,但没有释放上下文空间if (isNeedClaerParam)//给一个参数确定是否需要清理{avcodec_parameters_free(&codecpar);}//8线程解码codec->thread_count = 4;//打开解码器上下文int re = avcodec_open2(codec, 0, 0);if (re != 0)//0为成功打开文件{//释放上下文的空间avcodec_free_context(&codec);mux.unlock();//释放空间之后解锁char buf[1024] = { 0 };av_strerror(re, buf, sizeof(buf) - 1);//打印错误原因cout << " avcodec_open2 " << "--failed! : " << buf << endl;return false;}cout << "avcodec_open2 " << "--success! " << endl;/******************************************/mux.unlock();return true;
}//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-////清空读取缓存
void XDecode::Clear()
{mux.lock();//清理解码缓冲上下文if (codec){avcodec_flush_buffers(codec);//清理缓存?}mux.unlock();
}
void XDecode::Close()
{mux.lock();//关闭codec上下文if (codec){avcodec_close(codec);//清空codec里面的数据avcodec_free_context(&codec);//将codec指针置为空}mux.unlock();
}//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-////将包发送到解码线程,不管成功与否都要释放pkt的空间,(对象空间和数据空间)
bool XDecode::Send(AVPacket* pkt)
{//容错处理if (!pkt || pkt->size <= 0 || !pkt->data)return false;mux.lock();if (!codec){mux.unlock();return false;//解码器没找到,不用释放包pkt的内存,下次再用}int re = avcodec_send_packet(codec, pkt);//把pkt的数据发送到解码线程mux.unlock();//上锁为了控制全局变量codec,可以再释放pkt空间之前解锁av_packet_free(&pkt);//释放pkt的空间,无论成功没成功都释放if (re != 0)return false;return true;
}//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-//AVFrame* XDecode::Receive()
{mux.lock();if (!codec){mux.unlock();return NULL;//解码器没找到}AVFrame* frame = av_frame_alloc();int re = avcodec_receive_frame(codec, frame);mux.unlock(); //上锁为了控制全局变量codec,codec已经使用了if (re != 0){av_frame_free(&frame);//返回前释放空间return NULL;}cout <<"解码后的frame->linesize[0]: " << frame->linesize[0] << std::endl;return frame;//返回解码后的一帧数据
}//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-//

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com