FFmpeg关于转封装-MP4转flv代码实现

#include "libavutil/avutil.h"
#include "libavformat/avformat.h"


/*
    转封装流程
*/
int main(int argc, char const *argv[])
{
    av_log_set_level(AV_LOG_DEBUG);
    if (argc < 3)
    {
        av_log(NULL, AV_LOG_ERROR, "Usage: %s <infileName> <outfileName>\n", argv[0]);
        return -1;
    }
    const char *infileName = argv[1];
    const char *outfileName = argv[2];

    AVFormatContext *inFmtCtx = NULL;

    //1.打开输入媒体文件
    int ret = avformat_open_input(&inFmtCtx, infileName, NULL, NULL);
    if (ret != 0)
    {
        av_log(NULL, AV_LOG_ERROR, "open input format failed: %s\n", av_err2str(ret));
        return -1;
    }

    //2.获取输入流信息
    ret = avformat_find_stream_info(inFmtCtx, NULL);
    if (ret != 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find input stream failed: %s\n", av_err2str(ret));
        goto fail;
    }

    AVFormatContext *outFmtCtx = NULL;
    //3.创建输出流上下文
    ret = avformat_alloc_output_context2(&outFmtCtx, NULL, NULL, outfileName);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "alloc output format failed: %s\n", av_err2str(ret));
        goto fail;
    }

    int streamCount = inFmtCtx->nb_streams;
    int *handleStreamIndexArray = av_mallocz_array(streamCount, sizeof(int));
    if (handleStreamIndexArray == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, "malloc handle stream index failed\n");
        goto fail;
    }

    int streamIndex = 0;
    for (int i = 0; i < streamCount; i++)
    {
        AVStream *inStream = inFmtCtx->streams[i];
        if (inStream->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
            inStream->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
            inStream->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
        {
            handleStreamIndexArray[i] = -1;
            continue;
        }
        handleStreamIndexArray[i] = streamIndex++;
        AVStream *outStream = NULL;
        //4.创建输出码流的AVStream
        outStream = avformat_new_stream(outFmtCtx, NULL);
        if (outStream == NULL)
        {
            ret = -1;
            av_log(NULL, AV_LOG_ERROR, "new output stream failed\n");
            goto fail;
        }
        //5.拷贝编码参数
        avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
        outStream->codecpar->codec_tag = 0;
    }
   
    if (!(outFmtCtx->oformat->flags & AVFMT_NOFILE))
    {
        ret = avio_open(&outFmtCtx->pb, outfileName, AVIO_FLAG_WRITE);
        if (ret < 0)
        {
            av_log(NULL, AV_LOG_ERROR, "open %s file failed\n", outfileName);
            goto fail;
        }
    }

    //6.写入视频文件头
    ret = avformat_write_header(outFmtCtx, NULL);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "write header failed: %s\n", av_err2str(ret));
        goto fail;
    }

    AVPacket packet;
    av_init_packet(&packet);

    //7.读取输入视频流
    while (av_read_frame(inFmtCtx, &packet) == 0)
    {
        if (packet.stream_index >= streamCount || handleStreamIndexArray[packet.stream_index] == -1)
        {
            av_packet_unref(&packet);
            continue;
        }

        AVStream *inStream = inFmtCtx->streams[packet.stream_index];
        AVStream *outStream = outFmtCtx->streams[packet.stream_index];

        packet.stream_index = handleStreamIndexArray[packet.stream_index];
        //8.计算pts、dts、duration
        packet.pts = av_rescale_q(packet.pts, inStream->time_base, outStream->time_base);
        packet.dts = av_rescale_q(packet.dts, inStream->time_base, outStream->time_base);
        packet.duration = av_rescale_q(packet.duration, inStream->time_base, outStream->time_base);
        packet.pos = -1;

        //9.写入视频流数据
        ret = av_interleaved_write_frame(outFmtCtx, &packet);
        if (ret < 0)
        {
            av_log(NULL, AV_LOG_ERROR, "av_interleaved_write_frame failed\n");
            return -1;
        }
        av_packet_unref(&packet);
    }
   
    //10.写入视频文件末尾
    ret = av_write_trailer(outFmtCtx);
    if (ret != 0)
    {
        av_log(NULL, AV_LOG_ERROR, "av_write_trailer failed\n");
        return -1;
    }


fail:
    if (inFmtCtx)
    {
        avformat_close_input(&inFmtCtx);
    }
    if (outFmtCtx && !(outFmtCtx->oformat->flags & AVFMT_NOFILE))
    {
        avio_closep(&outFmtCtx->pb);
    }
    if (outFmtCtx)
    {
        avformat_free_context(outFmtCtx);
    }
    if (handleStreamIndexArray)
    {
        av_freep(&handleStreamIndexArray);
    }
    return ret;
}

 

猜你喜欢

转载自blog.csdn.net/u011616934/article/details/124081664