Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ H265编解码器从hvc1更改为hev1_C++_Ffmpeg_Libavcodec - Fatal编程技术网

C++ H265编解码器从hvc1更改为hev1

C++ H265编解码器从hvc1更改为hev1,c++,ffmpeg,libavcodec,C++,Ffmpeg,Libavcodec,我尝试用hevc视频复制mp4文件。 源文件有hvc1编解码器 Stream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668) 复制编解码器后,获取hev1的值 Stream #0:0(und): Video: hevc (Main) (hev1 / 0x31766568) 我怎样才能得到hvc1? 我发现ffmpeg可以通过“-tag:v hvc1”来实现 () 以及如何在C++代码中设置标签() 但这并不起作用 我的代码: AVOutpu

我尝试用hevc视频复制mp4文件。 源文件有hvc1编解码器

Stream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668)
复制编解码器后,获取hev1的值

Stream #0:0(und): Video: hevc (Main) (hev1 / 0x31766568)
我怎样才能得到hvc1? 我发现ffmpeg可以通过“-tag:v hvc1”来实现 () 以及如何在C++代码中设置标签() 但这并不起作用

我的代码:

AVOutputFormat *ofmt = NULL;
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
AVPacket pkt;
const char *in_filename, *out_filename;
int ret, i;
int stream_index = 0;
int *stream_mapping = NULL;
int stream_mapping_size = 0;

if (argc < 3) {
    printf("usage: %s input output\n"
        "API example program to remux a media file with libavformat and libavcodec.\n"
        "The output format is guessed according to the file extension.\n"
        "\n", argv[0]);
    return 1;
}

in_filename = argv[1];
out_filename = argv[2];

av_register_all();

if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
    fprintf(stderr, "Could not open input file '%s'", in_filename);
    goto end;
}

if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
    fprintf(stderr, "Failed to retrieve input stream information");
    goto end;
}

av_dump_format(ifmt_ctx, 0, in_filename, 0);

avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
if (!ofmt_ctx) {
    fprintf(stderr, "Could not create output context\n");
    ret = AVERROR_UNKNOWN;
    goto end;
}

stream_mapping_size = ifmt_ctx->nb_streams;
stream_mapping = (int*)av_mallocz_array(stream_mapping_size, sizeof(*stream_mapping));
if (!stream_mapping) {
    ret = AVERROR(ENOMEM);
    goto end;
}

ofmt = ofmt_ctx->oformat;

for (i = 0; i < (int)ifmt_ctx->nb_streams; i++) {
    AVStream *out_stream;
    AVStream *in_stream = ifmt_ctx->streams[i];
    AVCodecParameters *in_codecpar = in_stream->codecpar;
    AVCodec *decoder = avcodec_find_decoder(in_stream->codecpar->codec_id);
    AVCodec *encoder = avcodec_find_encoder(in_stream->codecpar->codec_id);

    if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
        in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
        in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
        stream_mapping[i] = -1;
        continue;
    }

    stream_mapping[i] = stream_index++;

    out_stream = avformat_new_stream(ofmt_ctx, NULL);
    if (!out_stream) {
        fprintf(stderr, "Failed allocating output stream\n");
        ret = AVERROR_UNKNOWN;
        goto end;
    }

    ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
    if (ret < 0) {
        fprintf(stderr, "Failed to copy codec parameters\n");
        goto end;
    }

    unsigned int tag = 0;
    // for ffmpeg new api 3.x
    AVCodecParameters *parameters = out_stream->codecpar;
    if (av_codec_get_tag2(ofmt_ctx->oformat->codec_tag, encoder->id, &tag) == 0) {
        av_log(NULL, AV_LOG_ERROR, "could not find codec tag for codec id %d, default to 0.\n", encoder->id);
    }
    parameters->codec_tag = tag;
    out_stream->codec = avcodec_alloc_context3(encoder);
    // more setting for stream->codec
    avcodec_parameters_to_context(out_stream->codec, parameters);
}
av_dump_format(ofmt_ctx, 0, out_filename, 1);

if (!(ofmt->flags & AVFMT_NOFILE)) {
    ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
    if (ret < 0) {
        fprintf(stderr, "Could not open output file '%s'", out_filename);
        goto end;
    }
}

ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
    fprintf(stderr, "Error occurred when opening output file\n");
    goto end;
}

while (1) {
    AVStream *in_stream, *out_stream;

    ret = av_read_frame(ifmt_ctx, &pkt);
    if (ret < 0)
        break;

    in_stream = ifmt_ctx->streams[pkt.stream_index];
    if (pkt.stream_index >= stream_mapping_size ||
        stream_mapping[pkt.stream_index] < 0) {
        av_packet_unref(&pkt);
        continue;
    }

    pkt.stream_index = stream_mapping[pkt.stream_index];
    out_stream = ofmt_ctx->streams[pkt.stream_index];
    log_packet(ifmt_ctx, &pkt, "in");

    /* copy packet */
    pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
    pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
    pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
    pkt.pos = -1;
    log_packet(ofmt_ctx, &pkt, "out");

    ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
    if (ret < 0) {
        fprintf(stderr, "Error muxing packet\n");
        break;
    }
    av_packet_unref(&pkt);
}

av_write_trailer(ofmt_ctx);
AVOutputFormat*ofmt=NULL;
AVFormatContext*ifmt\u ctx=NULL,*ofmt\u ctx=NULL;
AVPacket-pkt;
常量字符*输入\文件名,*输出\文件名;
int ret,i;
int stream_index=0;
int*stream_映射=NULL;
int stream_mapping_size=0;
如果(argc<3){
printf(“用法:%s输入输出\n”
“使用libavformat和libavcodec重新复制媒体文件的API示例程序。\n”
“根据文件扩展名猜测输出格式。\n”
“\n”,argv[0]);
返回1;
}
in_filename=argv[1];
out_filename=argv[2];
av_寄存器_all();
if((ret=avformat\u open\u input(&ifmt\u ctx,in\u filename,0,0))<0){
fprintf(stderr,“无法在文件名中打开输入文件“%s”);
转到终点;
}
如果((ret=avformat\u find\u stream\u info(ifmt\u ctx,0))<0){
fprintf(stderr,“检索输入流信息失败”);
转到终点;
}
av_dump_格式(ifmt_ctx,0,in_文件名,0);
avformat\u alloc\u output\u context2(&ofmt\u ctx,NULL,NULL,out\u文件名);
如果(!ofmt_ctx){
fprintf(stderr,“无法创建输出上下文\n”);
ret=平均误差(未知);
转到终点;
}
流映射大小=ifmt\u ctx->nb\u流;
stream_mapping=(int*)av_mallocz_数组(stream_mapping_大小,sizeof(*stream_mapping));
if(!流_映射){
ret=平均值(ENOMEM);
转到终点;
}
ofmt=ofmt_ctx->oformat;
对于(i=0;i<(int)ifmt_ctx->nb_streams;i++){
AVStream*输出流;
AVStream*in_stream=ifmt_ctx->streams[i];
AVCodecParameters*in_codecpar=in_stream->codecpar;
AVCodec*decoder=AVCodec\u find\u解码器(在\u流->编解码器->编解码器id中);
AVCodec*encoder=AVCodec\u find\u encoder(在\u stream->codepar->codec\u id中);
如果(在编解码器中->编解码器类型!=AVMEDIA\u类型\u音频&&
在\u codepar->codec\u type!=AVMEDIA\u type\u视频中&&
在\u codepar->codec\u type!=AVMEDIA\u type\u字幕){
流映射[i]=-1;
继续;
}
流_映射[i]=流_索引++;
out\u stream=avformat\u new\u stream(ofmt\u ctx,NULL);
如果(!流出){
fprintf(stderr,“分配输出流失败\n”);
ret=平均误差(未知);
转到终点;
}
ret=avcodec\u参数\u复制(输出流->编解码器,输入编解码器);
如果(ret<0){
fprintf(stderr,“复制编解码器参数失败\n”);
转到终点;
}
无符号整数标记=0;
//对于ffmpeg新api 3.x
AVCodecParameters*parameters=out\u stream->codecpar;
如果(av_codec_get_tag2(ofmt_ctx->oformat->codec_tag,encoder->id和tag)==0){
av_日志(空,av_日志错误,“找不到编解码器id%d的编解码器标记,默认为0。\n”,编码器->id);
}
参数->编解码器\标签=标签;
out\u stream->codec=avcodec\u alloc\u context3(编码器);
//流->编解码器的更多设置
avcodec_参数_到_上下文(出流->编解码器,参数);
}
av_转储_格式(ofmt_ctx,0,out_文件名,1);
if(!(ofmt->flags&AVFMT_NOFILE)){
ret=avio_open(&ofmt_ctx->pb,out_文件名,avio_标志_写入);
如果(ret<0){
fprintf(stderr,“无法打开输出文件“%s”,out\u文件名);
转到终点;
}
}
ret=avformat\U write\U头(ofmt\U ctx,NULL);
如果(ret<0){
fprintf(stderr,“打开输出文件时出错\n”);
转到终点;
}
而(1){
AVStream*输入流,*输出流;
ret=av_读取_帧(ifmt_ctx和pkt);
如果(ret<0)
打破
in_stream=ifmt_ctx->streams[pkt.stream_index];
如果(pkt.stream\u index>=流映射\u大小||
流映射[pkt.stream\u索引]<0){
av_数据包_unref(&pkt);
继续;
}
pkt.stream_index=stream_映射[pkt.stream_index];
out_stream=ofmt_ctx->streams[pkt.stream_index];
日志数据包(ifmt\U ctx和pkt,“in”);
/*复制包*/
pkt.pts=av_rescale_q_rnd(pkt.pts,in_stream->time_base,out_stream->time_base,(AVRounding)(av_ROUND_近INF|av_ROUND_PASS_MINMAX));
pkt.dts=av_rescale_q_rnd(pkt.dts,in_stream->time_base,out_stream->time_base,(AVRounding)(av_ROUND_NEAR_INF|av_ROUND_PASS_MINMAX));
pkt.duration=av_rescale_q(pkt.duration,in_stream->time_base,out_stream->time_base);
pkt.pos=-1;
日志数据包(ofmt\U ctx和pkt,“退出”);
ret=av交织写入帧(ofmt、ctx和pkt);
如果(ret<0){
fprintf(stderr,“错误多路复用数据包\n”);
打破
}
av_数据包_unref(&pkt);
}
av_写入_预告片(ofmt_ctx);
完:

avformat\u close\u输入(&ifmt\u ctx);
/*关闭输出*/
if(ofmt\u ctx&&!(ofmt->flags&AVFMT\u NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_上下文(ofmt_ctx);
av_freep(和流_映射);
if(ret<0&&ret!=AVERROR\u EOF){
fprintf(stderr,“发生错误:%s\n”,av_errTOstr(ret.c_str());
返回1;
}
更改后:

    out_stream = avformat_new_stream(ofmt_ctx, NULL);
    ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);

    AVCodecParameters *parameters = out_stream->codecpar;
    unsigned int tag = 0;
    av_codec_get_tag2(ofmt_ctx->oformat->codec_tag, encoder->id, &tag) == 0);
    parameters->codec_tag = tag;

    out_stream->codec = avcodec_alloc_context3(encoder);
    avcodec_parameters_to_context(out_stream->codec, parameters);

    if (in_codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        parameters->codec_tag = MKTAG('h', 'v', 'c', '1');
    }
}

av_dump_format(ofmt_ctx, 0, out_filename, 1);
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);

ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
    fprintf(stderr, "Error write header: %s\n", av_errTOstr(ret). c_str());
    goto end;
}
out\u stream=avformat\u new\u stream(ofmt\u ctx,NULL);
ret=avcodec\u参数\u复制(输出流->编解码器,输入编解码器);
AVCodecParameters*parameters=out\u stream->codecpar;
无符号整数标记=0;
av_codec_get_tag2(ofmt_ctx->oformat->codec_tag,encoder->id和tag)==0);
参数->编解码器\标签=标签;
out\u stream->codec=avcodec\u alloc\u context3(编码器);
avcodec_参数_到_上下文(出流->编解码器,参数);
如果(在编解码器中->编解码器类型==AVMEDIA\u类型\u视频){
参数->编解码器标签=MKTAG('h','v','c','1');
}
}
av_转储_格式(ofmt_ctx,0,out_文件名,1);
ret=avio_open(&ofmt_ctx->pb,out_文件名,avio_标志_写入);
ret=avformat\U write\U头(ofmt\U ctx,NULL);
如果(ret<0){
fprintf(stderr,“错误写入头:%s\n”,av_errTOstr(ret.c_str());
转到终点;
}

Replace
parameters->codec\u tag=tag带有
参数->编解码器标签=0x31637668。您也可以使用
MKTAG
    out_stream = avformat_new_stream(ofmt_ctx, NULL);
    ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);

    AVCodecParameters *parameters = out_stream->codecpar;
    unsigned int tag = 0;
    av_codec_get_tag2(ofmt_ctx->oformat->codec_tag, encoder->id, &tag) == 0);
    parameters->codec_tag = tag;

    out_stream->codec = avcodec_alloc_context3(encoder);
    avcodec_parameters_to_context(out_stream->codec, parameters);

    if (in_codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        parameters->codec_tag = MKTAG('h', 'v', 'c', '1');
    }
}

av_dump_format(ofmt_ctx, 0, out_filename, 1);
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);

ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
    fprintf(stderr, "Error write header: %s\n", av_errTOstr(ret). c_str());
    goto end;
}