首页 > 其他分享 >FFmpeg:视频转封装(FLV转成MP4,不需要转码)(参考remuxing.c)

FFmpeg:视频转封装(FLV转成MP4,不需要转码)(参考remuxing.c)

时间:2023-01-14 19:57:13浏览次数:39  
标签:FFmpeg stream 转码 ctx ret FLV avformat ofmt pkt

如果不是特别熟悉C/C++,又要使用FFmpeg.API处理一些简单的音视频业务,那么可以使用org.bytedeco:ffmpeg-platform,下面记录一下使用ffmpeg-platform视频转封装的方法。

1. 基本流程

  1. 打开输入流
  2. 创建输出AVFormatContext
  3. 读流、写流

2. 完整代码

流程比较简单,这里直接给出完成代码

public class Remuxing {

    public static void main(String[] args) throws IOException {
        remuxing("test1.flv", "t1.mp4");
    }

    public static void remuxing(String input, String output) throws IOException {
        AVFormatContext ifmt_ctx = null;
        AVFormatContext ofmt_ctx = null;
        AVOutputFormat ofmt = null;
        AVPacket pkt = null;

        try {
            ifmt_ctx = avformat.avformat_alloc_context();
            int ret = avformat.avformat_open_input(ifmt_ctx, input, null, null);
            if (ret < 0) {
                throw new IOException(ret + ":avformat_open_input error");
            }

            ret = avformat.avformat_find_stream_info(ifmt_ctx, (AVDictionary) null);
            if (ret < 0) {
                throw new IOException(ret + ":avformat_find_stream_info error");
            }

            ofmt_ctx = new AVFormatContext(null);
            ret = avformat.avformat_alloc_output_context2(ofmt_ctx, null, null, output);
            if (ret < 0) {
                throw new IOException(ret + ":avformat_alloc_output_context2 error");
            }

            int stream_mapping_size = ifmt_ctx.nb_streams();
            int[] stream_mapping = new int[stream_mapping_size];
            int stream_index = 0;

            for (int i = 0; i < ifmt_ctx.nb_streams(); i++) {

                AVStream in_stream = ifmt_ctx.streams(i);
                AVCodecParameters in_codecpar = in_stream.codecpar();
                if (in_codecpar.codec_type() != avutil.AVMEDIA_TYPE_AUDIO
                        && in_codecpar.codec_type() != avutil.AVMEDIA_TYPE_VIDEO
                        && in_codecpar.codec_type() != avutil.AVMEDIA_TYPE_SUBTITLE) {
                    stream_mapping[i] = -1;
                    continue;
                }
                stream_mapping[i] = stream_index++;

                AVStream out_stream = avformat.avformat_new_stream(ofmt_ctx, null);
                if (out_stream == null) {
                    throw new IOException("avformat_new_stream error");
                }

                ret = avcodec.avcodec_parameters_copy(out_stream.codecpar(), in_codecpar);
                if (ret < 0) {
                    throw new IOException(ret + ":avcodec_parameters_copy error");
                }

                out_stream.codecpar().codec_tag(0);
            }

            ofmt = ofmt_ctx.oformat();
            if ((ofmt.flags() & avformat.AVFMT_NOFILE) == 0) {
                AVIOContext pb = new AVIOContext(null);
                ret = avformat.avio_open(pb, output, avformat.AVIO_FLAG_WRITE);
                if (ret < 0) {
                    throw new IOException(ret + ":avio_open error");
                }
                ofmt_ctx.pb(pb);
            }

            ret = avformat.avformat_write_header(ofmt_ctx, (AVDictionary) null);
            if (ret < 0) {
                throw new IOException(ret + ":avformat_write_header error");
            }

            AVStream in_stream, out_stream;
            pkt = avcodec.av_packet_alloc();
            while (true) {
                ret = avformat.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) {
                    avcodec.av_packet_unref(pkt);
                    continue;
                }

                pkt.stream_index(stream_mapping[pkt.stream_index()]);
                out_stream = ofmt_ctx.streams(pkt.stream_index());

                pkt.pts(avutil.av_rescale_q_rnd(pkt.pts(), in_stream.time_base(), out_stream.time_base(),
                        avutil.AV_ROUND_NEAR_INF | avutil.AV_ROUND_PASS_MINMAX));
                pkt.dts(avutil.av_rescale_q_rnd(pkt.dts(), in_stream.time_base(), out_stream.time_base(),
                        avutil.AV_ROUND_NEAR_INF | avutil.AV_ROUND_PASS_MINMAX));
                pkt.duration(avutil.av_rescale_q(pkt.duration(), in_stream.time_base(), out_stream.time_base()));
                pkt.pos(-1);

                ret = avformat.av_interleaved_write_frame(ofmt_ctx, pkt);
                if (ret < 0) {
                    throw new IOException(ret + ":av_interleaved_write_frame error");
                }
            }

            ret = avformat.av_write_trailer(ofmt_ctx);
            if (ret < 0) {
                throw new IOException(ret + ":av_write_trailer error");
            }

        } finally {
            if (Objects.nonNull(pkt)) {
                avcodec.av_packet_free(pkt);
            }
            if (Objects.nonNull(ifmt_ctx)) {
                avformat.avformat_close_input(ifmt_ctx);
            }
            if (Objects.nonNull(ofmt_ctx)) {
                if (Objects.nonNull(ofmt)) {
                    if ((ofmt.flags() & avformat.AVFMT_NOFILE) == 0) {
                        avformat.avio_closep(ofmt_ctx.pb());
                    }
                }
                avformat.avformat_free_context(ofmt_ctx);
            }
        }
    }
}

注意:视频DTS有问题的话,av_interleaved_write_frame可能会有问题。

标签:FFmpeg,stream,转码,ctx,ret,FLV,avformat,ofmt,pkt
From: https://www.cnblogs.com/michong2022/p/17052419.html

相关文章

  • FFmpeg:视频帧格式转化(sws_scale)(参考scaling_video.c)
    如果不是特别熟悉C/C++,又要使用FFmpeg.API处理一些简单的音视频业务,那么可以使用org.bytedeco:ffmpeg-platform,下面记录一下使用ffmpeg-platform视频帧格式转化的方法。1.......
  • FFmpeg:视频解码(FFmpeg 5.x 新API)(参考decode_video.c)
    如果不是特别熟悉C/C++,又要使用FFmpeg.API处理一些简单的音视频业务,那么可以使用org.bytedeco:ffmpeg-platform,下面记录一下使用ffmpeg-platform视频解码的方法。1.代码......
  • FFmpeg:音视频封装(含格式转化、重采样)(参考muxing.c)
    如果不是特别熟悉C/C++,又要使用FFmpeg.API处理一些简单的音视频业务,那么可以使用org.bytedeco:ffmpeg-platform,下面记录一下使用ffmpeg-platform获取封装音视频数据(含格式......
  • 使用ffmpeg合并多个ts文件
    使用ffmpeg合并多个ts文件需求来源在海康的行车记录仪上录制的视频为每分钟一个ts文件,在手机上最多也就可以设置为3分钟,并且在APP只能一下导出5个文件,所以我就将内存卡拔......
  • uniapp裁剪视频使用ffmpeg
    <template><view><button@click="cutVideo">CutVideo</button></view></template><script>importffmpegfrom'ffmpeg.js'exportdefault{method......
  • ffmpeg第8篇:使用ffprobe采集文件信息
    1、前言ffprobe是ffmpeg的其中一个模块,主要用于查看文件信息,咱们知道一个MP4文件其实不仅仅包含了音视频数据,还有如元数据等其它信息,但是实际上咱们关心的往往是音视频......
  • FFmpeg-最最强大的视频工具
    FFmpeg-最最强大的视频工具FFmpeg是一个自由软件,它可以用于处理音频和视频数据。它包含了许多命令行工具,可以进行各种不同的媒体处理任务,如音频编解码、视频编解码、转码、......
  • 转码之路
    大一浑浑噩噩学的农学大二学C语言想着转网络安全最后没有狠下心来大三学python结果考过了计算机二级就又开始懒狗大四没看计算机后来毕业了一年申请......
  • Vue中使用flv.js播放flv格式视频流
    Vue中使用flv.js播放flv格式视频流1.安装依赖npminstallflv.js--save--legacy-peer-deps2.具体代码Html部分<template> <div><videoautoplaycontrol......
  • ffmpeg安装图片转视频
     乌班图:ffmpeg图片转视频一键安装命令:aptinstallffmpeg Centos1.在宝塔终端输入:wgethttp://download.bt.cn/install/ext/ffmpeg.sh&&shffmpeg.sh2.......