基于 FFmpeg 实现 H.264 转 MP4 视频转码

引言

FFmpeg 是强大的开源音视频处理库,能实现多种音视频操作。本文将分享如何用 FFmpeg 把 H.264 视频文件转码为 MP4 格式。

代码整体思路

代码把转码功能封装在 TranceVideo 类中,通过一系列步骤完成 H.264 到 MP4 的转码,包括初始化、打开输入文件、获取视频流信息、确定输出格式、创建输出文件、转码并写入帧数据,最后清理资源。

详细步骤

1. 初始化

在类的构造函数里,进行基础的初始化操作:

cpp

// 注册 FFmpeg 所有组件
av_register_all(); 
// 分配输入和输出格式上下文
inFormatContext = avformat_alloc_context(); 
outFormatContext = avformat_alloc_context(); 
// 分配 AVPacket 用于存储编码后的数据
pkt = (AVPacket*)malloc(sizeof(AVPacket)); 
// 初始化视频流索引为 -1
videoIndex = -1; 

先注册 FFmpeg 组件,接着分配输入输出格式上下文和 AVPacket 内存,同时初始化视频流索引。

2. 打开输入文件

cpp

// 打开 H.264 文件
avformat_open_input(&inFormatContext, filepath, nullptr, nullptr); 
// 获取视频流信息
avformat_find_stream_info(inFormatContext, nullptr); 
// 查找视频流索引
for (int i = 0; i < inFormatContext->nb_streams; ++i) {
    if (inFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
        videoIndex = i;
        break;
    }
}

使用 avformat_open_input 打开文件,avformat_find_stream_info 获取流信息,再遍历流找到视频流索引。

3. 准备输出文件

cpp

// 猜测输出文件格式
outputFormat = av_guess_format(nullptr, output_filepath, nullptr); 
// 设置输出格式
outFormatContext->oformat = outputFormat; 
// 打开输出文件的 I/O 流
avio_open(&outFormatContext->pb, output_filepath, AVIO_FLAG_WRITE); 
// 创建新的视频流
AVStream *newStream = avformat_new_stream(outFormatContext, nullptr); 
// 复制原视频流的编解码器参数
avcodec_parameters_copy(newStream->codecpar, inFormatContext->streams[videoIndex]->codecpar); 
// 写入输出文件头信息
avformat_write_header(outFormatContext, nullptr); 

先猜测输出格式,设置到输出格式上下文,打开输出文件 I/O 流,创建新视频流,复制编解码器参数,最后写入文件头信息。

4. 转码处理

cpp

while (av_read_frame(inFormatContext, pkt) == 0) {
    if (pkt->stream_index == videoIndex) {
        // 处理时间戳和时长
        if (pkt->pts == AV_NOPTS_VALUE) {
            // 计算 pts、dts 和 duration
        } else if (pkt->pts < pkt->dts) {
            continue;
        }
        // 时间基转换
        pkt->dts = av_rescale_q_rnd(pkt->dts, in_time_base, out_time_base, ...);
        pkt->pts = av_rescale_q_rnd(pkt->pts, in_time_base, out_time_base, ...);
        pkt->duration = av_rescale_q(pkt->duration, in_time_base, out_time_base);
        pkt->pos = -1;
        pkt->flags |= AV_PKT_FLAG_KEY;
        pkt->stream_index = 0;
        // 写入一帧数据到输出文件
        av_interleaved_write_frame(outFormatContext, pkt);
    }
    // 重置 AVPacket
    av_packet_unref(pkt);
}

循环读取输入文件帧数据,处理视频帧的时间戳和时长,进行时间基转换,最后写入输出文件。

5. 清理资源

cpp

// 写入输出文件尾信息
av_write_trailer(outFormatContext); 
// 关闭输出文件 I/O 流
avio_close(outFormatContext->pb); 
// 释放输出格式上下文
av_free(outFormatContext); 
// 关闭输入文件上下文
avformat_close_input(&inFormatContext); 
// 释放输入格式上下文
av_free(inFormatContext); 

写入文件尾信息,关闭输入输出文件上下文并释放资源。

总结

通过上述步骤,实现了 H.264 到 MP4 的转码。使用 FFmpeg 时,要注意资源分配与释放,以及时间戳和时长的转换,同时完善错误处理,避免程序崩溃。此代码可作为日后复习和应用的参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值