美文网首页
FFmpeg转封装(remuxing)

FFmpeg转封装(remuxing)

作者: 自由侠 | 来源:发表于2022-07-05 13:12 被阅读0次

    // 环境: Qt5.7.1 64位

    //  只需要把LOG的宏定义和Qt的头文件改了,就可以直接编译

    #include <QDebug>

    #include <QString>

    #include <stdio.h>

    #include <stdlib.h>

    #include <qbytearray.h>

    extern "C" {

    #include <libavformat/avformat.h>

    #include <libavcodec/avcodec.h>

    #include <libavutil/imgutils.h>

    #include <libavutil/opt.h>

    #include <libavutil/timestamp.h>

    }

    #define STR(str)    QString::fromLocal8Bit((char*)str)

    #define LOG        qDebug()

    int main()

    {

        char* ifname= "D:/fmt.mp4";

        char* ofname= "D:/dst.mkv";

        int ret=-1;

        AVFormatContext* ic=0, *oc=0;

        ret=avformat_open_input(&ic, ifname, 0, 0);

        avformat_find_stream_info(ic, 0);

        if(ret<0)

            exit(1);

        av_dump_format(ic, 0, "input", 0);

        ret=avformat_alloc_output_context2(&oc, 0, 0,ofname);

        if(ret<0)

            exit(1);

    //    创建一个和ic流数量相同大小的数组,保存ic的st的判断值

    //    若流有效则写入创建的oc流索引,否则设为无效值(-1)

        int nb_st=0;

        int st_mp_sz= ic->nb_streams;

        int* st_info= (int*)av_mallocz_array(ic->nb_streams, sizeof(int));

        AVStream* ist=0, *ost=0;

        for(int i=0; i<ic->nb_streams; ++i)

        {

            ist= ic->streams[i];

            if(ist->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&

                ist->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&

                ist->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE){

                LOG << "not media type stream:" << i;

                st_info[i]= -1;

                continue;

            }

            st_info[i]= nb_st++;

            ost= avformat_new_stream(oc, 0);    //  no need to encode, so codec is NULL

            avcodec_parameters_copy(ost->codecpar, ist->codecpar);

            ost->codecpar->codec_tag= 0;        //  The info of codec is Empty

        }

        av_dump_format(oc, 0, "output", 1);

        if(!(oc->oformat->flags & AVFMT_NOFILE)){        //  若不是自动打开文件的模式,则需要此手动操作

            avio_open2(&oc->pb, ofname, AVIO_FLAG_WRITE, 0, 0);

        }

        AVPacket* pkt= av_packet_alloc();

        avformat_write_header(oc, 0);

        while(av_read_frame(ic, pkt)>=0)

        {

            ist= ic->streams[pkt->stream_index];

            if(pkt->stream_index >=st_mp_sz || st_info[pkt->stream_index]<0){

                LOG << "this pkt is not media type, idx:" << pkt->stream_index;

                av_packet_unref(pkt);

                continue;

            }

            //  再封装pkt

            pkt->stream_index= st_info[pkt->stream_index];

            ost= oc->streams[pkt->stream_index];

            pkt->pts= av_rescale_q_rnd(pkt->pts,ist->time_base,ost->time_base,AVRounding(AV_ROUND_INF|AV_ROUND_PASS_MINMAX));

            pkt->dts= av_rescale_q_rnd(pkt->dts,ist->time_base,ost->time_base, AVRounding(AV_ROUND_INF|AV_ROUND_PASS_MINMAX));

            pkt->duration= av_rescale_q(pkt->duration, ist->time_base, ost->time_base);

            pkt->pos= -1;

          av_interleaved_write_frame(oc, pkt);

          av_packet_unref(pkt);

          LOG << "sucess write pkt, pts:" << pkt->pts;

        }

        av_write_trailer(oc);

        end:

        avformat_close_input(&ic);

        if(oc && !(oc->oformat->flags & AVFMT_NOFILE))

            avio_closep(&oc->pb);

        avformat_free_context(oc);

        av_packet_free(&pkt);

        av_freep(&st_info);

        return 0;

    }

    需要注意的是, 转封装时可能需要转换pts.

    转自: https://blog.csdn.net/weixin_42881084/article/details/82534567

    相关文章

      网友评论

          本文标题:FFmpeg转封装(remuxing)

          本文链接:https://www.haomeiwen.com/subject/wmdsbrtx.html