当前位置: 首页 > news >正文

FFmpeg - 基本 API大全(视频编解码相关的)

FFmpeg 是一个强大的多媒体处理库,下面我将介绍其基本 API 并结合网络流/本地文件解码示例说明每个 API 的功能和用法。

一、核心 API 分类

1. 格式处理 API (libavformat)

2. 编解码 API (libavcodec)

3. 实用工具 API (libavutil)

4. 图像缩放/像素格式转换 API (libswscale)

二、基本 API 详解及示例

1. 初始化相关 API

c

// 注册所有编解码器和格式 (4.0+已废弃,但许多示例仍保留)
av_register_all();// 初始化网络库 (用于网络流)
avformat_network_init();

2. 打开输入流 API

c

AVFormatContext *pFormatCtx = NULL;// 本地文件打开
const char *url = "input.mp4";
if (avformat_open_input(&pFormatCtx, url, NULL, NULL) != 0) {printf("无法打开输入文件\n");return -1;
}// 网络流打开 (如RTMP)
const char *rtmp_url = "rtmp://live.example.com/app/stream";
AVDictionary *options = NULL;
av_dict_set(&options, "rtsp_transport", "tcp", 0); // 设置RTSP over TCP
av_dict_set(&options, "stimeout", "5000000", 0);  // 设置超时5秒if (avformat_open_input(&pFormatCtx, rtmp_url, NULL, &options) != 0) {printf("无法打开网络流\n");return -1;
}

3. 获取流信息 API

c

if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {printf("无法获取流信息\n");return -1;
}// 打印流信息
av_dump_format(pFormatCtx, 0, url, 0);

4. 查找视频流 API

c

int videoStream = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++) {if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoStream = i;break;}
}
if (videoStream == -1) {printf("未找到视频流\n");return -1;
}

5. 编解码器设置 API

c

// 获取编解码器参数
AVCodecParameters *pCodecParams = pFormatCtx->streams[videoStream]->codecpar;// 查找解码器
const AVCodec *pCodec = avcodec_find_decoder(pCodecParams->codec_id);
if (!pCodec) {printf("不支持的解码器\n");return -1;
}// 创建解码器上下文
AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
if (!pCodecCtx) {printf("无法分配编解码器上下文\n");return -1;
}// 复制参数到上下文
if (avcodec_parameters_to_context(pCodecCtx, pCodecParams) < 0) {printf("无法复制编解码器参数\n");return -1;
}// 打开解码器
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {printf("无法打开解码器\n");return -1;
}

6. 帧和包处理 API

c

// 分配帧
AVFrame *pFrame = av_frame_alloc();
if (!pFrame) {printf("无法分配帧\n");return -1;
}// 初始化包
AVPacket packet;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;

7. 解码循环 API

c

while (av_read_frame(pFormatCtx, &packet) >= 0) {if (packet.stream_index == videoStream) {// 发送数据包到解码器int ret = avcodec_send_packet(pCodecCtx, &packet);if (ret < 0) {printf("发送解码包出错\n");continue;}// 接收解码后的帧while (ret >= 0) {ret = avcodec_receive_frame(pCodecCtx, pFrame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {break;} else if (ret < 0) {printf("解码出错\n");return -1;}// 成功解码一帧,可以处理帧数据printf("解码帧: width=%d, height=%d, format=%d, pts=%lld\n",pFrame->width, pFrame->height, pFrame->format, pFrame->pts);// 这里可以添加帧处理代码...}}av_packet_unref(&packet); // 释放包
}

8. 刷新解码器 API

c

// 发送空包刷新解码器
avcodec_send_packet(pCodecCtx, NULL);// 接收剩余的帧
while (avcodec_receive_frame(pCodecCtx, pFrame) == 0) {printf("刷新解码器获取的帧: pts=%lld\n", pFrame->pts);// 处理帧...
}

9. 资源释放 API

c

av_frame_free(&pFrame);
avcodec_free_context(&pCodecCtx);
avformat_close_input(&pFormatCtx);
avformat_network_deinit(); // 如果之前调用了avformat_network_init()

三、完整网络流解码示例

c

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <stdio.h>int main() {AVFormatContext *pFormatCtx = NULL;AVCodecContext *pCodecCtx = NULL;const AVCodec *pCodec = NULL;AVFrame *pFrame = NULL;AVPacket packet;int videoStream = -1;// 初始化网络库avformat_network_init();// 打开网络流 (这里使用RTMP示例)const char *url = "rtmp://live.example.com/app/stream";AVDictionary *options = NULL;av_dict_set(&options, "rtsp_transport", "tcp", 0);av_dict_set(&options, "stimeout", "5000000", 0);if (avformat_open_input(&pFormatCtx, url, NULL, &options) != 0) {printf("无法打开网络流\n");return -1;}// 获取流信息if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {printf("无法获取流信息\n");return -1;}// 查找视频流for (int i = 0; i < pFormatCtx->nb_streams; i++) {if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoStream = i;break;}}if (videoStream == -1) {printf("未找到视频流\n");return -1;}// 设置解码器AVCodecParameters *pCodecParams = pFormatCtx->streams[videoStream]->codecpar;pCodec = avcodec_find_decoder(pCodecParams->codec_id);if (!pCodec) {printf("不支持的解码器\n");return -1;}pCodecCtx = avcodec_alloc_context3(pCodec);avcodec_parameters_to_context(pCodecCtx, pCodecParams);if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {printf("无法打开解码器\n");return -1;}// 准备帧和包pFrame = av_frame_alloc();av_init_packet(&packet);// 解码循环while (av_read_frame(pFormatCtx, &packet) >= 0) {if (packet.stream_index == videoStream) {if (avcodec_send_packet(pCodecCtx, &packet) < 0) {printf("发送解码包出错\n");continue;}while (avcodec_receive_frame(pCodecCtx, pFrame) == 0) {printf("解码帧: width=%d, height=%d, format=%d, pts=%lld\n",pFrame->width, pFrame->height, pFrame->format, pFrame->pts);// 实际应用中这里可以处理帧数据}}av_packet_unref(&packet);}// 刷新解码器avcodec_send_packet(pCodecCtx, NULL);while (avcodec_receive_frame(pCodecCtx, pFrame) == 0) {printf("刷新解码器获取的帧\n");}// 清理av_frame_free(&pFrame);avcodec_free_context(&pCodecCtx);avformat_close_input(&pFormatCtx);avformat_network_deinit();return 0;
}

四、关键 API 功能总结

API功能描述常用场景
av_register_all()注册所有编解码器和格式旧版本初始化 (4.0+已废弃)
avformat_network_init()初始化网络库处理网络流前调用
avformat_open_input()打开媒体文件或流本地文件/网络流输入
avformat_find_stream_info()获取流信息打开输入后获取详细信息
avcodec_find_decoder()查找解码器根据codec_id查找解码器
avcodec_alloc_context3()创建编解码器上下文解码器/编码器设置
avcodec_parameters_to_context()复制参数到上下文设置解码器参数
avcodec_open2()打开编解码器初始化编解码器
av_read_frame()读取数据包解码循环中获取数据
avcodec_send_packet()发送数据包到解码器现代解码流程
avcodec_receive_frame()接收解码后的帧现代解码流程
av_packet_unref()释放数据包处理完包后释放资源
av_frame_free()释放帧处理完帧后释放资源

五、不同场景下的注意事项

  1. 本地文件解码:

    • 不需要调用avformat_network_init()

    • 通常不需要设置超时等网络参数

  2. 网络流解码:

    • 必须调用avformat_network_init()

    • 建议设置合理的超时参数

    • 对于RTSP流,建议强制使用TCP传输

  3. 实时流处理:

    • 可能需要设置realtime标志

    • 可能需要禁用缓冲av_dict_set(&options, "fflags", "nobuffer", 0)

  4. 错误处理:

    • 所有API调用都应检查返回值

    • 网络流需要更健壮的错误恢复机制

这个指南涵盖了FFmpeg解码的基本API和使用方法,实际应用中可能需要根据具体需求进行调整和扩展。

http://www.dtcms.com/a/326634.html

相关文章:

  • python每日一题练习 两个数组的交集 非常简单
  • GCN: 图卷积网络,概念以及代码实现
  • 【LeetCode刷题集】--排序(三)
  • Protocol Buffers (protobuf) API 接口完全指南
  • maven项目打包成sdk后在别的项目使用
  • 从0开始的中后台管理系统-5(部门管理以及菜单管理页面功能实现)
  • 【科研绘图系列】R语言绘制散点图折线图误差棒组合图
  • 指派问题-匈牙利算法
  • 2025牛客多校第八场 根号-2进制 个人题解
  • HTTPS应用层协议-CA签名与证书
  • Vue 3 快速入门 第六章
  • MaixPy简介
  • Projects
  • 进程管理是什么
  • DeepSeek生成的高精度大数计算器
  • 自制网页并爬取,处理异常值(第十九节课内容总结)
  • .NET/C# webapi框架下给swagger的api文档中显示注释(可下载源码)
  • MP3Tag 软件功能简介
  • (二)vscode搭建espidf环境,配置wsl2
  • 第16届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2025年4月真题
  • 进阶版|企业级 AI Agent 的构建实践
  • 【03】厦门立林科技——立林科技 嵌入式 校招笔试,题目记录及解析
  • 从零开始的ReAct Agent尝试
  • 应用监控工具Skywalking
  • bitbake –s:列出所有可编译的模块
  • 【STL】queue队列容器
  • priority_queue(优先级队列)和仿函数
  • ArkUI中的自定义组件(一)
  • 用于计算的程序是部署在哪里,为什么可以这样?
  • 从 WebView2 迁移至 DotNetBrowser:第一部分