VTrain_BothSides/engine/DecodeEngine/HardDecode.cpp

171 lines
4.7 KiB
C++

#include "HardDecode.h"
using namespace std;
HardDecode::HardDecode()
{
;
}
HardDecode::~HardDecode()
{
;
}
int HardDecode::hardDecoderInit(unsigned int uiWidth, unsigned int uiHeight, unsigned int uiFrameRate, AVCodecParameters *pCodecParameters)
{
uiWidth_ = uiWidth; uiHeight_ = uiHeight;
uiFrameRate_ = uiFrameRate;
this->pCodecParameters_ = pCodecParameters;
av_log_set_level(AV_LOG_ERROR);
// AVCodecID codec_id = AV_CODEC_ID_H264; //解码H264
// pCodec_ = avcodec_find_decoder(codec_id); //获取解码器
pCodec_ = avcodec_find_decoder(this->pCodecParameters_->codec_id);
if (pCodec_ == nullptr) {
LogError << "cannot find decoder !";
return 0;
}
//创建上下文
pCodecCtx_ = avcodec_alloc_context3(pCodec_);
if (!pCodecCtx_){
LogError << "Could not allocate video codec context";
return 0;
}
// 将AVCodecParameters结构体中码流参数拷贝到AVCodecContext结构体中,format, width, height, codec_type等
avcodec_parameters_to_context(pCodecCtx_, this->pCodecParameters_);
if (!pCodecCtx_) {
LogError << "Cannot alloc context.";
return 0;
}
//打开解码器
int iRet = 1;
if ((iRet = avcodec_open2(pCodecCtx_, pCodec_, nullptr)) < 0) {
LogError << "cannot open decoder, Ret:" << iRet;
return 0;
}
//分配packet
pPacket_ = av_packet_alloc();
if (!pPacket_){
LogError << "Could not allocate video packet";
return 0;
}
// av_init_packet(pPacket_);
//分配frame
pSrcFrame_ = av_frame_alloc();
if (!pSrcFrame_) {
LogError << "Could not allocate video src pFrame";
return 0;
}
pDstFrame_ = av_frame_alloc();
if (!pDstFrame_) {
LogError << "Could not allocate video dst pFrame";
return 0;
}
// printf("after align down video_width: %d, video_height: %d\n", uiWidth_, uiHeight_);
int bufferSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P,
pCodecCtx_->width,
pCodecCtx_->height, 1);
outBuffer_ = (unsigned char *) av_malloc(bufferSize);
av_image_fill_arrays(pDstFrame_->data,
pDstFrame_->linesize,
outBuffer_,
AV_PIX_FMT_YUV420P,
pCodecCtx_->width,
pCodecCtx_->height, 1);
pSwsContext_ = sws_getContext(pCodecCtx_->width, pCodecCtx_->height, pCodecCtx_->pix_fmt,
pCodecCtx_->width, pCodecCtx_->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, nullptr, nullptr, nullptr);
return 1;
}
int HardDecode::hardDecoderDeInit()
{
if (pCodecParameters_){
av_free(pCodecParameters_);
pCodecParameters_ = nullptr;
}
if(outBuffer_){
av_free(outBuffer_);
outBuffer_ = nullptr;
}
if(pSrcFrame_){
av_frame_free(&pSrcFrame_);
pSrcFrame_ = nullptr;
}
if(pDstFrame_){
av_frame_free(&pDstFrame_);
pDstFrame_ = nullptr;
}
if(pPacket_){
av_packet_free(&pPacket_);
pPacket_ = nullptr;
}
if(pCodecParserCtx_){
av_parser_close(pCodecParserCtx_);
pCodecParserCtx_ = nullptr;
}
if(pCodecCtx_){
avcodec_close(pCodecCtx_);
av_free(pCodecCtx_);
pCodecCtx_ = nullptr;
}
if(pSwsContext_){
sws_freeContext(pSwsContext_);
pSwsContext_ = nullptr;
}
return 1;
}
int HardDecode::hardDecoder(void* pOutputData,unsigned int* puiOutputDataSize)
{
int ret;
ret = avcodec_send_packet(this->pCodecCtx_, this->pPacket_); //接收packet解码
if (ret < 0) {
LogError << "Error sending a packet for decoding " << ret;
return 0;
}
while (ret >= 0) {
ret = avcodec_receive_frame(this->pCodecCtx_, this->pSrcFrame_); //解码
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){
LogWarn << "During decoding eof";
return 0;
}
else if (ret < 0) {
LogError << "Error during decoding";
return 0;
}
sws_scale(this->pSwsContext_,
(const uint8_t *const *)this->pSrcFrame_->data,
this->pSrcFrame_->linesize,
0,
this->pCodecCtx_->height,
this->pDstFrame_->data,
this->pDstFrame_->linesize);
fflush(stdout);
int iSize = this->pCodecCtx_->width * this->pCodecCtx_->height;
memcpy(pOutputData, this->pDstFrame_->data[0], iSize); //Y
memcpy(pOutputData+iSize, this->pDstFrame_->data[1], iSize/4); //U
memcpy(pOutputData+iSize+iSize/4, this->pDstFrame_->data[2], iSize/4); //V
*puiOutputDataSize = iSize*3/2;
return iSize*3/2;
}
return 0;
}