#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; }