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

FFMPEG api使用

一、播放音视频

1.1 整体架构

1.2 具体代码

1. 创建一个媒体句柄AVFormatContext,这个句柄里面存储了 流信息、视频信息 或 音频信息

AVFormatContext *fmt_ctx = NULL;// 1. 分配上下文
fmt_ctx = avformat_alloc_context();
if (!fmt_ctx) {// 处理内存分配失败
}// 2. 打开文件并填充上下文
if (avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL) != 0) {// 处理打开失败
}// 3. 使用上下文进行操作(如查找流信息等)// 4. 关闭文件并释放资源
avformat_close_input(&fmt_ctx);

avformat_alloc_context 和 avformat_free_context 配对使用

avformat_open_input 和 avformat_close_input 配对使用

注意可以不使用avformat_alloc_context()分配内存后再使用avformat_open_input()打开文件。只要传入的fmt_ctx==NULL,就会自动创建

使用avformat_close_input关闭解复用器器后,就不用使用avformat_free_context释放AVFormatContext

2. 查看AVFormatContext里面有哪些媒体流

// 获取流的信息
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {fprintf(stderr, "无法获取流信息\n");avformat_close_input(&fmt_ctx);return -1;
}// 获取了信息才能使用下面方法找流
for (int i = 0; i < fmt_ctx->nb_streams; i++) {if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {target_stream_index = i;printf("找到视频流,索引:%d\n", target_stream_index);break;}
}

使用avformat_find_stream_info()可以获取视频文件信息

3. 从AVFormatContext里面获取一个包AVPacket

AVPacket * packet = av_packet_alloc();while ((ret = av_read_frame(fmt_ctx, packet)) == 0) {// 判断当前包是否属于目标流if (packet->stream_index == target_stream_index) {// 处理目标流的数据包(例如解码、打印信息等)printf("处理视频流数据,PTS: %lld\n", packet->pts);}// 无论是否处理,都需要释放数据包的引用av_packet_unref(packet);
}

avformat_seek_file()定位到音视频文件的位置

4. 常见解码

视频:H.264 -> YUV

音频:AAC -> PCM

通过下面的函数将AVPacket转成AVFrame

// 获取解码参数
AVCodecParameters * codec_par = fmt_ctx->streams[video_stream_idx]->codecpar;
// 根据解码器ID获取解码器
AVCodec * dec = avcodec_find_decoder(codec_par->codec_id);
// 根据解码器创建上下文结构体
AVCodecContext * dec_ctx = avcodec_alloc_context3(dec);int decode_video_packet(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt) {int ret;// 发送数据包到解码器if (avcodec_send_packet(dec_ctx, pkt) < 0) {fprintf(stderr, "发送视频数据包失败\n");return -1;}// 接收解码后的帧ret = avcodec_receive_frame(dec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return 0;if (ret < 0) {fprintf(stderr, "视频解码失败\n");return -1;}// 简单处理:打印视频帧信息printf("视频帧 - 宽: %d, 高: %d, PTS: %lld\n", frame->width, frame->height, frame->pts);av_frame_unref(frame);return 0;
}
AVCodecParameters *codec_par = fmt_ctx->streams[audio_stream_idx]->codecpar;
AVCodec * dec = avcodec_find_decoder(codec_par->codec_id);
AVCodecContext * dec_ctx = avcodec_alloc_context3(dec);int decode_audio_packet(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt) {int ret;// 发送数据包到解码器if (avcodec_send_packet(dec_ctx, pkt) < 0) {fprintf(stderr, "发送音频数据包失败\n");return -1;}// 接收解码后的帧ret = avcodec_receive_frame(dec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return 0;if (ret < 0) {fprintf(stderr, "音频解码失败\n");return -1;}// 简单处理:打印音频帧信息printf("音频帧 - 采样率: %d, 声道数: %d, 样本数: %d\n",dec_ctx->sample_rate, dec_ctx->channels, frame->nb_samples);av_frame_unref(frame);return 0;
}

二、FFMPEG整体架构

上层应用(最顶部)

ffplay:一个简单的媒体播放器,基于 FFmpeg 库实现音视频的播放功能,可用于测试和简单的播放场景。

ffprobe:用于查看媒体文件的信息,比如流的类型、编码格式、时长、比特率等元数据,帮助开发者或用户了解媒体文件的详细结构。

ffmpeg:FFmpeg 最核心的命令行工具,集音视频的录制、转换、编码、解码等多种功能于一体,可对媒体文件进行各种复杂的处理操作。

核心库(中间层)

libavutil:提供了一些通用的工具函数,如内存管理、数学运算、数据结构等,是其他 FFmpeg 库的基础支撑库。

libavformat:负责媒体文件的格式处理,包括封装和解封装操作。比如读取 MP4、MKV 等格式的文件,解析出其中的音视频流;或者将编码后的音视频流封装成特定格式的文件。

libavcodec:音视频编解码的核心库,包含了各种音视频编解码器的实现(如 H.264、AAC 等编解码器),用于将压缩的音视频数据解码为原始数据,或者将原始数据编码为压缩格式。

libswscale:主要用于视频像素格式的转换和图像缩放。例如将 YUV 格式的视频帧转换为 RGB 格式,或者对视频图像进行缩放操作,以适配不同的显示需求。

libswresample:专注于音频重采样和格式转换。可以调整音频的采样率、声道数、采样格式等,使音频在不同的设备或场景下能够正常播放。

libavfilter:提供了各种音视频滤镜功能,用于对音视频进行特效处理。比如给视频添加模糊、锐化效果,对音频进行降噪、均衡等处理。

libpostproc:用于对视频进行后期处理,比如去块效应等,提升视频的视觉质量。

编解码器(底层)

fdk - aac:是一种 AAC 音频编解码器,用于 AAC 格式音频的编码和解码,能提供高质量的 AAC 音频编码。

voaac_enc:也是 AAC 音频编码器,用于将原始音频数据编码为 AAC 格式。

x264:非常知名的 H.264 视频编码器,可将原始视频数据高效地编码为 H.264 格式的视频流,在视频压缩领域应用广泛。

三、AVPacket

1.1 AVPacket引用计数

AVPacket *pkt1 = av_packet_alloc();
AVPacket *pkt2 = av_packet_alloc();
// 假设pkt1已经填充好数据
av_packet_ref(pkt2, pkt1);

av_packet_ref(pkt2, pkt1) 后,pkt1 和 pkt2 共享 pkt1 原来指向的数据内存。引用计数+1,当引用技术减少为0的时候就释放内存

有下面的一些函数:

av_init_packet(AVPacket *pkt) 初始化一个已经分配好内存的 AVPacket 结构体。它主要是将 AVPacket 结构体中的成员变量设置为默认的初始状态,如将 pts、dts 设为 AV_NOPTS_VALUE ,将 data 设为 NULL,将数据大小 size 设为 0 等。但它不会为 AVPacket 结构体分配内存,只是对传入的 AVPacket 结构体进行状态初始化。

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

相关文章:

  • 从disable_cost到disabled_nodes,最小代价预估质的飞跃
  • nestjs日志(nest-winston)
  • pyecharts可视化图表-tree:从入门到精通
  • Linux 系统调优与CPU-IO-网络内核参数调优
  • Task04: CAMEL框架中的多智能体系统(课程第三章剩余章节)
  • 大模型安全概述、LlamaFirewall
  • ESP8266:Arduino学习
  • 前端性能优化:从指标监控到全链路落地(2024最新实战指南)
  • 短视频矩阵管理软件推荐——小麦矩阵系统深度解析
  • 关于两视图相机几何关系
  • DevExpress WPF中文教程:如何将WPF数据网格绑定到本地集合?
  • 软件定义汽车(SDV)调试——如何做到 适配软件定义汽车(SDV)?(下)
  • vue新能源汽车销售平台的设计与实现(代码+数据库+LW)
  • 【Vue2✨】 Vue2 入门之旅(二):模板语法
  • Python异步编程:从理论到实战的完整指南
  • Qt---项目架构解读
  • BiLSTM-Attention分类预测+SHAP分析+特征依赖图!深度学习可解释分析,Matlab代码实现
  • 【GaussDB】深度解析:创建存储过程卡死且无法Kill会话的疑难排查
  • codeforces(1045)(div2)D. Sliding Tree
  • 装饰器模式(C++python)
  • 第十四章 Leaflet-Ant-Path 实现西气东输管线动态流向可视化
  • 源代码接入 1688 接口的详细指南
  • 【生产事故处理--kafka日志策略保留】
  • antv x6实现封装拖拽流程图配置(适用于工单流程、审批流程应用场景)
  • 使用Stone 3D快速制作第一人称视角在线小游戏
  • STM32八大模式
  • Yapi接口文档导出测试用例至Excel中
  • ProfiNet 转 Ethernet/IP西门子 S7-400 及罗克韦尔 PLC 于原油蒸馏的集成应用
  • 插入排序讲解
  • D‘RespNeT无人机图像分割数据集与YOLOv8-DRN模型,实时识别入口与障碍,助力灾后救援