int DecodeH265ToYuv420(unsigned char *H264FrameBuffer, int H264FrameNumber, int H264FrameSize, unsigned char *YBuffer, unsigned char *UvBuffer)
{
AVCodec *pCodec = NULL;
AVCodecContext *pCodecCtx= NULL;
AVCodecParserContext *pCodecParserCtx=NULL;
AVFrame *pFrame= NULL;
AVCodecID CodeId = AV_CODEC_ID_H265;
unsigned char *CurPtr = NULL;
int CurSize = 0, ret = 0, GotPicture = 0, FirstTime = 1, LeftSize = H264FrameSize, BufferOffset = 0;
AVPacket packet;
const int InBufferSize = 8192;
unsigned char InBuffer[InBufferSize + 32] = {0};
avcodec_register_all();
pCodec = avcodec_find_decoder(CodeId);
if (!pCodec) {
T_ERR("Codec not found\n");
return -1;
}
T_INFO("****\n");
pCodecCtx = avcodec_alloc_context3(pCodec);
if (!pCodecCtx){
T_ERR("Could not allocate video codec context\n");
return -1;
}
pCodecParserCtx = av_parser_init(CodeId);
if (!pCodecParse)
{
T_ERR("Could not allocate video parser context\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
T_ERR("Could not open codec\n");
return -1;
}
pFrame = av_frame_alloc();
av_init_packet(&packet);
T_INFO("**LeftSize:%d**\n",LeftSize);
while (1) {
if (LeftSize >= InBufferSize) {
CurSize = InBufferSize;
} else if (LeftSize > 0 && LeftSize < InBufferSize) {
CurSize = LeftSize;
} else {
break;
}
memset(InBuffer, 0, sizeof(InBuffer));
memcpy(InBuffer, H264FrameBuffer+BufferOffset, CurSize);
CurPtr = InBuffer;
BufferOffset += CurSize;
LeftSize = LeftSize - CurSize;
T_INFO("**CurSize:%d**\n",CurSize);
while (CurSize > 0) {
int len = av_parser_parse2(
pCodecParserCtx, pCodecCtx,
&packet.data, &packet.size,
CurPtr , CurSize ,
AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
CurPtr += len;
CurSize -= len;
T_INFO("**CurSize:%d*len:%d*\n",CurSize,len);
if ( packet.size == 0 )
{
T_INFO("packet.size:%d\n",packet.size);
continue;
}
//Some Info from AVCodecParserContext
printf("[Packet]Size:%6d\t",packet.size);
switch(pCodecParserCtx->pict_type){
case AV_PICTURE_TYPE_I: printf("Type:I\t");break;
case AV_PICTURE_TYPE_P: printf("Type:P\t");break;
case AV_PICTURE_TYPE_B: printf("Type:B\t");break;
default: printf("Type:Other\t");break;
}
printf("Number:%4d\n",pCodecParserCtx->output_picture_number);
ret = avcodec_decode_video2(pCodecCtx, pFrame, &GotPicture, &packet);
if (ret < 0) {
printf("Decode Error.\n");
return ret;
}
if (GotPicture) {
if (FirstTime) {
printf("Codec Full Name:%s\n",pCodecCtx->codec->long_name);
printf("width:%d\nheight:%d\n\n",pCodecCtx->width,pCodecCtx->height);
FirstTime = 0;
}
//Y, U, V 420 nv12
int y_offset = 0;
for (int i = 0; i<pFrame->height; i++) {
memcpy(YBuffer+y_offset, pFrame->data[0]+pFrame->linesize[0]*i, pFrame->width);
y_offset += pFrame->width;
}
int uv_offset = 0;
for (int i = 0; i<pFrame->height/2; i++) {
for (int j = 0; j < pFrame->width/2; j++) {
UvBuffer[uv_offset] = *(pFrame->data[1]+pFrame->linesize[1]*i + j);
UvBuffer[uv_offset + 1] = *(pFrame->data[2]+pFrame->linesize[2]*i + j);
uv_offset += 2;
}
}
T_INFO("Succeed to decode 1 frame!\n");
}
}
}
av_parser_close(pCodecParserCtx);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
return 0;
}
H264/H265转成yuv420数据
最新推荐文章于 2022-10-08 11:06:44 发布