data[2]数据-6ren"> data[2]数据-环境 :ubuntu 16.04 64位; ffmpeg 3.3.2 构建 whih cuda cuvid libnpp ... 使用 ffmpeg cmd: ffmpeg -vsync 0 -c:v-6ren">
gpt4 book ai didi

ffmpeg - 为什么ffmpeg使用 "h264_cuvid"解码h264时没有AVFrame->data[2]数据

转载 作者:行者123 更新时间:2023-12-04 23:26:22 25 4
gpt4 key购买 nike

环境 :ubuntu 16.04 64位; ffmpeg 3.3.2 构建 whih cuda cuvid libnpp ...
使用 ffmpeg cmd: ffmpeg -vsync 0 -c:v h264_cuvid -i test.264 -f rawvideo test.yuv工作正常,生成的 yuv 文件没问题。
但是 当我通过我的代码使用“h264_cuvid”解码器解码这个 264 文件时,发生了一些问题,这是我的代码:

#include <stdio.h>

#define __STDC_CONSTANT_MACROS

#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#ifdef __cplusplus
};
#endif
#endif


//test different codec
#define TEST_H264 1
#define TEST_HEVC 0

int main(int argc, char* argv[])
{
AVCodec *pCodec;
AVCodecContext *pCodecCtx= NULL;
AVCodecParserContext *pCodecParserCtx=NULL;

FILE *fp_in;
FILE *fp_out;
AVFrame *pFrame;

const int in_buffer_size=4096;
unsigned char in_buffer[in_buffer_size + FF_INPUT_BUFFER_PADDING_SIZE]= {0};
unsigned char *cur_ptr;
int cur_size;
AVPacket packet;
int ret, got_picture;


#if TEST_HEVC
enum AVCodecID codec_id=AV_CODEC_ID_HEVC;
char filepath_in[]="bigbuckbunny_480x272.hevc";
#elif TEST_H264
AVCodecID codec_id=AV_CODEC_ID_H264;
char filepath_in[]="2_60_265to264.264";
#else
AVCodecID codec_id=AV_CODEC_ID_MPEG2VIDEO;
char filepath_in[]="bigbuckbunny_480x272.m2v";
#endif

char filepath_out[]="mainSend.yuv";
int first_time=1;


//av_log_set_level(AV_LOG_DEBUG);

avcodec_register_all();

// pCodec = avcodec_find_decoder(codec_id);
pCodec = avcodec_find_decoder_by_name("h264_cuvid");
if (!pCodec)
{
printf("Codec not found\n");
return -1;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
if (!pCodecCtx)
{
printf("Could not allocate video codec context\n");
return -1;
}

pCodecParserCtx=av_parser_init(pCodec->id);
if (!pCodecParserCtx)
{
printf("Could not allocate video parser context\n");
return -1;
}

if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Could not open codec\n");
return -1;
}
//Input File
fp_in = fopen(filepath_in, "rb");
if (!fp_in)
{
printf("Could not open input stream\n");
return -1;
}
//Output File
fp_out = fopen(filepath_out, "wb");
if (!fp_out)
{
printf("Could not open output YUV file\n");
return -1;
}

pFrame = av_frame_alloc();
av_init_packet(&packet);

while (1)
{

cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
if (cur_size == 0)
break;
cur_ptr=in_buffer;

while (cur_size>0)
{

int len = av_parser_parse2(
pCodecParserCtx, pCodecCtx,
&packet.data, &packet.size,
cur_ptr, cur_size,
AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);

cur_ptr += len;
cur_size -= len;

if(packet.size==0)
continue;

//Some Info from AVCodecParserContext
printf("[Packet]Size:%6d\t",packet.size);
switch(pCodecParserCtx->pict_type)
{
case AV_PICTURE_TYPE_I:
printf("Type:I\tNumber:%4d\n",pCodecParserCtx->output_picture_number);
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);
AVFrame* myFrame = av_frame_alloc();
ret = avcodec_decode_video2(pCodecCtx, myFrame, &got_picture, &packet);
if (ret < 0)
{
printf("Decode Error.\n");
return ret;
}
if (got_picture)
{
if(first_time)
{
printf("\nCodec Full Name:%s\n",pCodecCtx->codec->long_name);
printf("width:%d\nheight:%d\n\n",pCodecCtx->width,pCodecCtx->height);
first_time=0;
}
//Y, U, V
for(int i=0; i<myFrame->height; i++)
{
fwrite(myFrame->data[0]+myFrame->linesize[0]*i,1,myFrame->width,fp_out);
}
for(int i=0; i<myFrame->height/2; i++)
{
fwrite(myFrame->data[1]+myFrame->linesize[1]*i,1,myFrame->width/2,fp_out);
}
for(int i=0; i<myFrame->height/2; i++)
{
fwrite(myFrame->data[2]+myFrame->linesize[2]*i,1,myFrame->width/2,fp_out);
}
// printf("pframe's width height %d %d\t key frame %d\n",myFrame->width,myFrame->height,myFrame->key_frame);
printf("Succeed to decode 1 frame!\n");
av_frame_free(&myFrame);
}
}

}

fclose(fp_in);
fclose(fp_out);


av_parser_close(pCodecParserCtx);

av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);

return 0;
}

在这个演示代码中,我通过 vcodec_find_decoder_by_name("h264_cuvid"); 调用 h264_cuvid
但是代码在 fwrite(myFrame->data[2]+myFrame->linesize[2]*i,1,myFrame->width/2,fp_out); 处崩溃
所以用codeblocks调试后发现myFrame->data[2] codeblocks watching window里面没有数据

有什么建议吗?谢谢!

最佳答案

“h264”解码器的帧像素格式为 AV_PIX_FMT_YUV420P
但是“h264_cuvid”解码器的帧像素格式是 AV_PIX_FMT_NV12
所以,编辑代码

            for(int i=0; i<myFrame->height; i++)
{
fwrite(myFrame->data[0]+myFrame->linesize[0]*i,1,myFrame->width,fp_out);
}
for(int i=0; i<myFrame->height/2; i++)
{
fwrite(myFrame->data[1]+myFrame->linesize[1]*i,1,myFrame->width,fp_out);
}

工作正常

关于ffmpeg - 为什么ffmpeg使用 "h264_cuvid"解码h264时没有AVFrame->data[2]数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45321032/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com