ffmpeg 开发第一例

站在巨人的肩膀上最简单的基于FFMPEG的封装格式转换器(无编解码)_mp4remuxer_雷霄骅的博客-CSDN博客

在作者的示例上,修正了在ffmpeg6.0.1上运行,有些方法过时了.没有其它的修改.

cpp 复制代码
const char *in_filename = "/Users/archko/Movie/健身气功八段锦-clip.mp4";
    const char *out_filename = "/Users/archko/Movie/code.mp4";
    const AVOutputFormat *ofmt = NULL;
    //输入对应一个AVFormatContext,输出对应一个AVFormatContext
    //(Input AVFormatContext and Output AVFormatContext)
    AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
    AVPacket pkt;
    int ret, i;

    // 输入(Input)
    ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0);
    if (ret < 0) {
        printf("Could not open input file.");
        return 0;
    }
    ret = avformat_find_stream_info(ifmt_ctx, 0);
    if (ret < 0) {
        printf("Failed to retrieve input stream information");
        return 0;
    }
    av_dump_format(ifmt_ctx, 0, in_filename, 0);
    //输出(Output)
    avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
    if (!ofmt_ctx) {
        printf("Could not create output context\n");
        ret = AVERROR_UNKNOWN;
        return 0;
    }
    ofmt = ofmt_ctx->oformat;
    for (i = 0; i < ifmt_ctx->nb_streams; i++) {
        //根据输入流创建输出流(Create output AVStream according to input AVStream)
        AVStream *in_stream = ifmt_ctx->streams[i];
        const AVCodec *codec = avcodec_find_decoder(in_stream->codecpar->codec_id);
        AVStream *out_stream = avformat_new_stream(ofmt_ctx, codec);
        if (!out_stream) {
            printf("Failed allocating output stream\n");
            ret = AVERROR_UNKNOWN;
            return 0;
        }
        //复制AVCodecContext的设置(Copy the settings of AVCodecContext)
        AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
        ret = avcodec_parameters_to_context(codec_ctx, in_stream->codecpar);
        if (ret < 0) {
            printf("Failed to copy context from input to output stream codec context\n");
            return 0;
        }

        ret = avcodec_parameters_from_context(out_stream->codecpar, codec_ctx);
        if (ret < 0) {
            printf("Failed to copy codec context to out_stream codecpar context\n");
            return 0;
        }

        out_stream->codecpar->codec_tag = 0;
        //leixiaohua1020 在这是有这段操作的,6.0不需要这样,然后正常复制视频
        //if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
        //    out_stream->codecpar->codec_tag |= AV_CODEC_FLAG_GLOBAL_HEADER;
        //}
    }
    //输出一下格式------------------
    av_dump_format(ofmt_ctx, 0, out_filename, 1);
    //打开输出文件(Open output file)
    if (!(ofmt->flags & AVFMT_NOFILE)) {
        ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
        if (ret < 0) {
            printf("Could not open output file '%s'", out_filename);
            return 0;
        }
    }
    //写文件头(Write file header)
    ret = avformat_write_header(ofmt_ctx, NULL);
    if (ret < 0) {
        printf("Error occurred when opening output file\n");
        return 0;
    }
    int frame_index = 0;
    while (1) {
        AVStream *in_stream, *out_stream;
        //获取一个AVPacket(Get an AVPacket)
        ret = av_read_frame(ifmt_ctx, &pkt);
        if (ret < 0)
            break;
        in_stream = ifmt_ctx->streams[pkt.stream_index];
        out_stream = ofmt_ctx->streams[pkt.stream_index];
        /* copy packet */
        //转换PTS/DTS(Convert PTS/DTS)
        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;
        //写入(Write)
        ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
        if (ret < 0) {
            printf("Error muxing packet\n");
            break;
        }
        //printf("Write %8d frames to output file\n", frame_index);
        av_packet_unref(&pkt);
        frame_index++;
    }
    //写文件尾(Write file trailer)
    av_write_trailer(ofmt_ctx);
    end:
    avformat_close_input(&ifmt_ctx);
    /* close output */
    if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) {
        avio_close(ofmt_ctx->pb);
    }
    avformat_free_context(ofmt_ctx);
    if (ret < 0 && ret != AVERROR_EOF) {
        printf("Error occurred.\n");
        return -1;
    }
    printf("Copy success.\n");
    return 0;

xcode的开发实在不习惯,用的是clion,cmake,vscode.下一篇,clion创建项目,导入ffmpeg依赖

相关推荐
winfredzhang2 小时前
实战:从零构建一个支持屏幕录制与片段合并的视频管理系统 (Node.js + FFmpeg)
ffmpeg·node.js·音视频·录屏
winfredzhang3 小时前
自动化视频制作:深入解析 FFmpeg 图片转视频脚本
ffmpeg·自动化·音视频·命令行·bat·图片2视频
胖_大海_1 天前
【FFmpeg+Surface 底层渲染,实现超低延迟100ms】
ffmpeg
冷冷的菜哥1 天前
springboot调用ffmpeg实现对视频的截图,截取与水印
java·spring boot·ffmpeg·音视频·水印·截图·截取
进击的CJR2 天前
redis哨兵实现主从自动切换
mysql·ffmpeg·dba
huahualaly2 天前
重建oracle测试库步骤
数据库·oracle·ffmpeg
aqi002 天前
FFmpeg开发笔记(九十九)基于Kotlin的国产开源播放器DKVideoPlayer
android·ffmpeg·kotlin·音视频·直播·流媒体
lizongyao2 天前
FFMPEG命令行典型案例
ffmpeg
冷冷的菜哥2 天前
ASP.NET Core调用ffmpeg对视频进行截图,截取,增加水印
开发语言·后端·ffmpeg·asp.net·音视频·asp.net core
冷冷的菜哥2 天前
go(golang)调用ffmpeg对视频进行截图、截取、增加水印
后端·golang·ffmpeg·go·音视频·水印截取截图