FFmpeg处理音视频的常用API及一般流程

FFmpeg是一个开源的音视频处理库,提供了丰富的API用于音视频的编解码、转码、过滤、播放等操作。

一、使用FFmpeg API解码涉及到的函数及一般流程如下:

  1. av_register_all(): 注册所有的编解码器和格式。
cpp 复制代码
av_register_all();
  1. avformat_open_input(): 打开输入文件(流)并获取文件(流)的格式信息。
cpp 复制代码
AVFormatContext *fmt_ctx = NULL;
if (avformat_open_input(&fmt_ctx, input_file, NULL, NULL) < 0) {
    // 打开文件失败
}
  1. avformat_find_stream_info(): 获取流的详细信息。
cpp 复制代码
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
    // 获取流信息失败
}
  1. avcodec_find_decoder(): 查找解码器。
cpp 复制代码
AVCodec *codec = avcodec_find_decoder(stream->codecpar->codec_id);
if (!codec) {
    // 找不到解码器
}
  1. avcodec_open2(): 打开解码器。
cpp 复制代码
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
    // 打开解码器失败
}
  1. av_read_frame(): 读取一帧音视频数据。
cpp 复制代码
AVPacket packet;
while (av_read_frame(fmt_ctx, &packet) >= 0) {
    // 处理音视频数据
    av_packet_unref(&packet);
}
  1. avcodec_send_packet()和avcodec_receive_frame(): 解码音视频数据。
cpp 复制代码
AVFrame *frame = av_frame_alloc();
while (av_read_frame(fmt_ctx, &packet) >= 0) {
    if (packet.stream_index == audio_stream_index) {
        // 解码音频数据
        avcodec_send_packet(codec_ctx, &packet);
        while (avcodec_receive_frame(codec_ctx, frame) >= 0) {
            // 处理解码后的音频帧
        }
    } else if (packet.stream_index == video_stream_index) {
        // 解码视频数据
        avcodec_send_packet(codec_ctx, &packet);
        while (avcodec_receive_frame(codec_ctx, frame) >= 0) {
            // 处理解码后的视频帧
        }
    }
    av_packet_unref(&packet);
}

二、与解码类似,编码的流程一般为:

  1. avformat_alloc_output_context2(): 创建输出格式上下文。
cpp 复制代码
AVFormatContext *out_fmt_ctx = NULL;
if (avformat_alloc_output_context2(&out_fmt_ctx, NULL, NULL, output_file) < 0) {
    // 创建输出格式上下文失败
}
  1. avcodec_find_encoder(): 查找编码器。
cpp 复制代码
AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!encoder) {
    // 找不到编码器
}
  1. avcodec_open2(): 打开编码器。
cpp 复制代码
AVCodecContext *encoder_ctx = avcodec_alloc_context3(encoder);
if (avcodec_open2(encoder_ctx, encoder, NULL) < 0) {
    // 打开编码器失败
}
  1. avformat_write_header(): 写入输出文件的头部信息。
cpp 复制代码
if (avformat_write_header(out_fmt_ctx, NULL) < 0) {
    // 写入头部信息失败
}
  1. avcodec_send_frame()和avcodec_receive_packet(): 编码音视频数据。
cpp 复制代码
AVPacket encoded_packet;
while (av_read_frame(fmt_ctx, &packet) >= 0) {
    if (packet.stream_index == audio_stream_index) {
        // 编码音频数据
        avcodec_send_frame(encoder_ctx, frame);
        while (avcodec_receive_packet(encoder_ctx, &encoded_packet) >= 0) {
            // 处理编码后的音频数据
        }
    } else if (packet.stream_index == video_stream_index) {
        // 编码视频数据
        avcodec_send_frame(encoder_ctx, frame);
        while (avcodec_receive_packet(encoder_ctx, &encoded_packet) >= 0) {
            // 处理编码后的视频数据
        }
    }
    av_packet_unref(&packet);
}
  1. av_write_frame()和av_write_trailer(): 写入编码后的音视频数据。
cpp 复制代码
if (av_write_frame(out_fmt_ctx, &encoded_packet) < 0) {
    // 写入音视频数据失败
}

三、解码和编码结束后都要及时释放内存:

  1. avformat_close_input(): 关闭输入文件。
cpp 复制代码
avformat_close_input(&fmt_ctx);
  1. avcodec_free_context(): 释放编解码器上下文。
cpp 复制代码
avcodec_free_context(&codec_ctx);
  1. av_frame_free(): 释放帧对象。
cpp 复制代码
av_frame_free(&frame);
  1. avformat_free_context(): 释放格式上下文。
cpp 复制代码
avformat_free_context(fmt_ctx);

了解这些常用API及流程对使用FFmpeg开发将大有裨益。

相关推荐
念恒123066 小时前
继承(下) (Inheritance)
c++
H Journey7 小时前
C++之 CMake、CMakeLists.txt、Makefile
开发语言·c++·makefile·cmake
研究点啥好呢11 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
_dindong11 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
沫璃染墨11 小时前
C++ string 从入门到精通:构造、迭代器、容量接口全解析
c语言·开发语言·c++
6Hzlia12 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
计算机安禾12 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio
unicrom_深圳市由你创科技12 小时前
做虚拟示波器这种实时波形显示的上位机,用什么语言?
c++·python·c#
无限进步_12 小时前
【C++】电话号码的字母组合:从有限处理到通用解法
开发语言·c++·ide·windows·git·github·visual studio
C++ 老炮儿的技术栈13 小时前
GCC编译时无法向/tmp 目录写入临时汇编文件,因为设备空间不足,解决
linux·运维·开发语言·汇编·c++·git·qt