利用FFmpeg转码生成MP4文件

14 篇文章 1 订阅
14 篇文章 0 订阅

项目中,需要把一路音频流及一路视频流分别转码,生成指定格式(MP4)文件。在使用ffmpeg转码生成mp4文件的过程中,碰到了不少的问题,主要如下:
1. 生成的mp4文件无法正常播放
2. 生成的mp4,用ffmpeg分析,发现码率、帧率等参数不对(编码后的pkt结构体无pts,手动赋值错误,如果是mp4文件,不考虑B帧的情况下,pts是按512往上累加,如果是ts文件,则是按3600累加)
3. 生成的mp4文件,没有声音(编码后的pkt结构体无pts,手动赋值错误,如果是AAC文件,pts按1024累加)

在利用ffmpeg转码的时候,首先要初始化一些结构体,在生成一个MP4文件的时候,也需要创建并初始化一些结构体,具体为:

int open_out_put(const char* filename)
{
    int ret, i;
    int video_index = 0;
    int audio_index = 1;
    AVStream *out_stream;
    //编码参数的上下文
    AVCodecContext *enc_ctx;
    AVCodec *encoder;
    //这个参数最为重要,AVFormatContxt*,它为全局变量,该函数主要目的就是初始化它
    ofmt_ctx = NULL;
    //为ofmt_ctx申请空间
    avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
    if(ofmt_ctx == NULL)
    {
        av_log(NULL,AV_LOG_ERROR,"Could not create output context\n");
        return AVERROR_UNKNOWN;
    }
    //申请好空间之后,现在开始需要为它添加音频流及视频流了
    int nb_streams = 2;
    for(i = 0; i < nb_streams; i++)
    {
        //在ofmt_ctx结构体中添加一路媒体流,这路流的实际参数通过out_stream来设置
        out_stream = avformat_new_stream(ofmt_ctx, NULL);
        if(!out_stream)//添加流失败了
        {
            av_log(NULL,AV_LOG_ERROR,"Failed allocating output stream\n");
            return AVERROR_UNKNOWN;
        }
        //获取这路流的编码参数结构体的指针,然后初始化它
        enc_ctx = out_stream->codec;
        if(i == video_index)
        {
            //添加了第一路流,认为它是视频流
            encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
            if(!encoder)
            {
                av_log(NULL,AV_LOG_ERROR,"Video encoder not found\n");
                return AVERROR_UNKNOWN;
            }
            enc_ctx->bit_rate = 2000000;//2M码率
            enc_ctx->width = 1920;
            enc_tx->height = 1080;
            enc_ctx->time_base = (AVRational)(1,25);//说明帧率为25fps
            enc_ctx->gop_size = 50;
            enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
            enc_ctx->thread_count = 2;//编码器的线程数,正常情况下可以使编码速度变快
            av_opt_set(enc_ctx->priv_data,"preset","untrafast",0);
        }
        else if(i == audio_index)
        {
            //添加了第二路流,认为它是音频流
            encoder = avcodec_find_encoder(AV_CODEC_ID_AAC);
            if(!encoder)
            {
                av_log(NULL,AV_LOG_ERROR,"Audio encoder not found\n");
                return AVERROR_UNKNOWN;
            }
            enc_ctx->sample_rate = 44100;
            enc_ctx->channels = 2;
            enc_ctx->channel_layout = av_get_default_channel_layout(enc_ctx->channels);
            enc_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;//根据实际的编码格式来设置,AAC为该值
            enc_ctx->time_base = (AVRational){1,44100};
            enc_ctx->bit_rate = 128000;
        }

        //初始完各个流的编码参数之后,该设置其它媒体文件相关的参数了

        //ofmt_ctx->oformat结构体的值,根据filename的后缀名不同而有所不同,记住,这个判断在放在avcodec_open2之前,否则就算判断了,也不会生效,最终生成的mp4文件,无法正常播放
        if(ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
            enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

        ret = avcodec_open2(enc_ctx, encoder, NULL);
    }
    av_dump_format(ofmt_ctx, 0, filename, 1);

    if(!(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
    {
        ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
        if(ret < 0)
        {
            av_log(NULL,AV_LOG_ERROR,"Could not open output file\n");
            return ret;
        }
    }

    AVDictionary *opt = NULL;
    //设置媒体文件的视频帧率信息
    av_dict_set_int(&opt, "video_track_timescale",25, 0);
    ret = avformat_write_header(ofmt_ctx, &opt);
    if(ret < 0)
    {
        av_log(NULL,AV_LOG_ERROR,"Write file header failed\n");
        return ret;
    }

    return 1;
}

初始化好了之后,就开始编码了,编码成功后,调用函数

av_interleaved_write_frame(ofmt_ctx, &pkt);

把编码成功后的数据写入媒体文件中。
当编码结束后,再调用函数

av_write_trailer(fmt_ctx);

如果没调用此函数写入文件尾部,生成的mp4文件无法正常播放。
最后记得释放fmt_ctx结构体的内存空间。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
海思FFmpeg是一种用于音视频处理的开源工具库,可以用来生成MP4文件MP4是一种常见的音视频容器格式,可以存储包含音频、视频和字幕等多种媒体内容。 海思FFmpeg作为一个强大的多媒体处理工具,可以在各种平台上使用,并且支持多种音频和视频编码格式。生成MP4文件的过程主要包括几个步骤:输入文件的解码、音视频处理、音视频再编码和封装。 首先,需要使用FFmpeg将输入的音视频文件进行解码。通过解码,可以将原始的音视频数据提取出来,方便后续的处理。 接下来,可以对音视频进行各种处理操作,如裁剪、旋转、调整音量等。海思FFmpeg提供了丰富的音视频处理功能,可以根据需要进行配置和调整。 处理完音视频后,还需要进行音视频的再编码。再编码是将处理过的音频和视频数据重新进行编码,以适配MP4格式的要求。在重新编码的过程中,可以选择适当的音视频编码器和参数,以获得更好的图像和音频质量。 最后,将重新编码的音视频数据进行封装,生成最终的MP4文件。封装是将音频、视频和其他相关信息按照特定的格式进行组合,形成一个完整的MP4文件。 总的来说,海思 FFmpeg可以通过解码、处理、再编码和封装等步骤,生成符合MP4格式要求的视频文件。其丰富的功能和易于使用的特点,使得海思FFmpeg成为生成MP4文件的理想选择。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值