ffmpeg音视频开发从入门到精通——ffmpeg 视频数据抽取

文章目录

  • FFmpeg视频处理工具使用总结
    • 环境配置
    • 主函数与参数处理
    • 打开输入文件
    • 获取流信息
    • 分配输出文件上下文
    • 猜测输出文件格式
    • 创建视频流并设置参数
    • 打开输出文件并写入头信息
    • 读取、转换并写入帧数据
    • 写入尾信息并释放资源
    • 运行程序
    • 注意事项
    • 源代码

FFmpeg视频处理工具使用总结

环境配置

在C++程序中使用FFmpeg之前,需要包含相应的头文件,并根据是否使用C++编译器,可能需要添加extern "C"块。


```cpp
#ifdef __cplusplus
extern "C" {
#endif
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/log.h>
#ifdef __cplusplus
}
#endif

主函数与参数处理

程序入口点是main函数,它处理命令行参数并设置日志级别。

int main(int argc, char *argv[]) {// 参数检查if (argc < 3) {av_log(nullptr, AV_LOG_ERROR, "Usage: %s <input file> <output file>\n", argv[0]);exit(-1);}// 输入输出文件路径char *src = argv[1];char *dst = argv[2];// 设置日志级别av_log_set_level(AV_LOG_DEBUG);
}

打开输入文件

使用avformat_open_input打开输入文件,并检查返回值。

int ret = avformat_open_input(&pFormatCtx, src, nullptr, nullptr);
if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "Could not open input file: %s\n", src);exit(-1);
}

获取流信息

调用av_find_best_stream找到最佳的视频流。

ret = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "Failed to retrieve input stream information\n");goto _ERROR;
}

分配输出文件上下文

使用avformat_alloc_context分配输出文件的格式上下文。

oFormatCtx = avformat_alloc_context();
if (oFormatCtx == nullptr) {av_log(nullptr, AV_LOG_ERROR, "Failed to allocate output context\n");goto _ERROR;
}

猜测输出文件格式

使用av_guess_format猜测输出文件的格式。

outFmt = av_guess_format(nullptr, dst, nullptr);
if (outFmt == nullptr) {av_log(nullptr, AV_LOG_ERROR, "Failed to guess output format\n");goto _ERROR;
}
oFormatCtx->oformat = outFmt;

创建视频流并设置参数

为输出文件创建视频流,并复制输入视频流的参数。

outStream = avformat_new_stream(oFormatCtx, nullptr);
avcodec_parameters_copy(outStream->codecpar, pFormatCtx->streams[ret]->codecpar);
outStream->codecpar->codec_tag = 0;

打开输出文件并写入头信息

使用avio_open2打开输出文件,并使用avformat_write_header写入文件头信息。

ret = avio_open2(&oFormatCtx->pb, dst, AVIO_FLAG_WRITE, nullptr, nullptr);
if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "Failed to open output file: %s\n", dst);goto _ERROR;
}
ret = avformat_write_header(oFormatCtx, nullptr);
if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "Failed to write output file header\n");goto _ERROR;
}

读取、转换并写入帧数据

读取输入文件的视频帧,转换时间戳,并使用av_interleaved_write_frame写入输出文件。

while (av_read_frame(pFormatCtx, &pkt) >= 0) {if (pkt.stream_index == ret) {// 转换时间戳等pkt.pts = av_rescale_q_rnd(pkt.pts, inSteam->time_base, outStream->time_base, AV_ROUND_NEAR_INF);pkt.dts = av_rescale_q_rnd(pkt.dts, inSteam->time_base, outStream->time_base, AV_ROUND_NEAR_INF);pkt.duration = av_rescale_q(pkt.duration, inSteam->time_base, outStream->time_base);// 写入帧数据av_interleaved_write_frame(oFormatCtx, &pkt);}av_packet_unref(&pkt);
}

写入尾信息并释放资源

使用av_write_trailer写入文件尾信息,并释放所有资源。

av_write_trailer(oFormatCtx);_ERROR:
// 清理资源
if (oFormatCtx && oFormatCtx->pb) {avio_close(oFormatCtx->pb);oFormatCtx->pb = nullptr;
}
if (oFormatCtx) {avformat_free_context(oFormatCtx);oFormatCtx = nullptr;
}
if (pFormatCtx) {avformat_free_context(pFormatCtx);pFormatCtx = nullptr;
}

运行程序

程序需要传入两个参数:输入文件路径和输出文件路径。例如:

./my_ffmpeg_tool input.mp4 output.mkv

确保替换为您的实际文件名和所需的输出格式。

注意事项

  • 确保FFmpeg开发库已正确安装且可链接。
  • 检查程序输出的错误信息以进行调试。
  • 程序可能需要适当的读取和写入权限。

源代码

  • cmake 源文件
cmake_minimum_required(VERSION 3.27)
project(FFmpeg_exercise)
set(CMAKE_CXX_STANDARD 14)# 定义FFmpeg的安装路径变量
set(FFMPEG_INSTALL_DIR "/usr/local/ffmpeg")# 将FFmpeg的头文件目录添加到包含路径
include_directories(${FFMPEG_INSTALL_DIR}/include)# 定义FFmpeg库的基础名称(根据你的需要调整)
set(FFMPEG_LIBS "avcodec;avformat;avutil") # 用分号分隔库名# 寻找并链接FFmpeg库
foreach(FFMPEG_LIB ${FFMPEG_LIBS})find_library(${FFMPEG_LIB}_LIBRARY NAMES ${FFMPEG_LIB}PATHS ${FFMPEG_INSTALL_DIR}/lib NO_DEFAULT_PATH)list(APPEND FFMPEG_LIBRARIES ${${FFMPEG_LIB}_LIBRARY})
endforeach()add_executable(FFmpeg_exercise# main.cpp# extra_audic.cppextra_video.cpp)
# 链接FFmpeg库
target_link_libraries(FFmpeg_exercise ${FFMPEG_LIBRARIES})
  • cpp
//
// Created by 陈伟峰 on 2024/6/22.
//
#ifdef __cplusplus
extern "C" {
#endif
// 包含FFmpeg的头文件
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/log.h>
#ifdef __cplusplus}
#endif
#include <iostream>int main(int argc,char *argv[]){int ret {-1};int idx {-1};//1.处理一些参数char *src {nullptr};char *dst {nullptr};AVFormatContext *pFormatCtx {nullptr};AVFormatContext *oFormatCtx {nullptr};AVOutputFormat *outFmt {nullptr};AVStream *outStream {nullptr};AVStream *inSteam {nullptr};AVPacket pkt {nullptr};// 日志信息av_log_set_level(AV_LOG_DEBUG);if(argc<3){av_log(nullptr,AV_LOG_ERROR,"Usage:%s <input file> <output file>\n",argv[0]);exit(-1);}src = argv[1];dst = argv[2];// 2.打开多媒体输入文件ret = avformat_open_input(&pFormatCtx,src,nullptr,nullptr);if(ret<0){av_log(nullptr,AV_LOG_ERROR,"Could not open input file:%s\n",src);exit(-1);}// 3.获取多媒体文件信息ret = av_find_best_stream(pFormatCtx,AVMEDIA_TYPE_VIDEO,-1,-1,nullptr,0);if(ret<0){av_log(nullptr,AV_LOG_ERROR,"Failed to retrieve input stream information\n");goto _ERROR;}// 打开目的多媒体文件oFormatCtx = avformat_alloc_context();if(oFormatCtx==nullptr){av_log(nullptr,AV_LOG_ERROR,"Failed to allocate output context\n");goto _ERROR;}outFmt = av_guess_format(nullptr,dst,nullptr);if(outFmt==nullptr){av_log(nullptr,AV_LOG_ERROR,"Failed to guess output format\n");goto _ERROR;}oFormatCtx->oformat = outFmt;// 为目的文件,创建一个新的视频流outStream = avformat_new_stream(oFormatCtx,nullptr);// 设置视频参数inSteam = pFormatCtx->streams[idx];avcodec_parameters_copy(outStream->codecpar,pFormatCtx->streams[ret]->codecpar);outStream->codecpar->codec_tag = 0;// 绑定ret = avio_open2(&oFormatCtx->pb,dst,AVIO_FLAG_WRITE, nullptr, nullptr);if(ret<0){av_log(nullptr,AV_LOG_ERROR,"Failed to open output file:%s\n",dst);goto _ERROR;}// 写入头信息ret = avformat_write_header(oFormatCtx,nullptr);if(ret<0){av_log(nullptr,AV_LOG_ERROR,"Failed to write output file header\n");goto _ERROR;}// 写多媒体文件到目的文件ret = avformat_write_header(oFormatCtx,nullptr);if(ret<0){av_log(nullptr,AV_LOG_ERROR,"Failed to write output file header:%s\n", av_err2str(ret));goto _ERROR;}while(av_read_frame(pFormatCtx,&pkt)>=0) {if (pkt.stream_index == idx) {pkt.pts = av_rescale_q_rnd(pkt.pts, inSteam->time_base, outStream->time_base,(AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.dts = av_rescale_q_rnd(pkt.dts, inSteam->time_base, outStream->time_base,(AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.duration = av_rescale_q(pkt.duration, inSteam->time_base, outStream->time_base);pkt.stream_index = 0;pkt.pos = -1;av_interleaved_write_frame(oFormatCtx, &pkt);}av_packet_unref(&pkt);}// 写入尾信息av_write_trailer(oFormatCtx);_ERROR:if(oFormatCtx->pb){avio_close(oFormatCtx->pb);oFormatCtx->pb = nullptr;}if(oFormatCtx){avformat_free_context(oFormatCtx);oFormatCtx = nullptr;}if(pFormatCtx){avformat_free_context(pFormatCtx);pFormatCtx = nullptr;}return 0;
}
  • 执行
./main demo.mp4 demo2.h264
  • 运行
ffplay demo2.h264

image-20240622143747704

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/356554.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全:Web 安全 面试题.(SQL注入)

网络安全&#xff1a;Web 安全 面试题.&#xff08;SQL注入&#xff09; 网络安全面试是指在招聘过程中,面试官会针对应聘者的网络安全相关知识和技能进行评估和考察。这种面试通常包括以下几个方面&#xff1a; &#xff08;1&#xff09;基础知识:包括网络基础知识、操作系…

Vue69-路由基本使用

一、需求 二、开发步骤 2-1、路由的安装 vue-router3才能在vue2中使用&#xff01;现在默认是vue-router4版本&#xff0c;要在vue3中使用&#xff01;所以&#xff0c;安装的时候要指定版本。 2-2、在main.js中引入和使用路由 2-3、创建router文件夹 一般在vue中用了vue-ro…

外包IT运维解决方案

随着企业信息化进程的不断深入&#xff0c;IT系统的复杂性和重要性日益增加。高效的IT运维服务对于保证业务连续性、提升企业竞争力至关重要。外包IT运维解决方案通过专业的服务和技术支持&#xff0c;帮助企业降低运维成本、提高运维效率和服务质量。 本文结合《外包IT运维解…

会自动清除的文件——tempfile

原文链接&#xff1a;http://www.juzicode.com/python-tutorial-tempfile/ 在某些不需要持久保存文件的场景下&#xff0c;可以用tempfile模块生成临时文件或者文件夹&#xff0c;这些临时文件或者文件夹在使用完之后就会自动删除。 NamedTemporaryFile用来创建临时文件&…

计算机组成原理 | 数据的表示、运算和校验(3)数据处理与存储

移位 舍入和扩展 存储模式和对齐 不按边界对齐&#xff0c;访存次数会增加一次

计算机组成原理笔记-第3章 系统总线

第三章 系统总线 笔记PDF版本已上传至Github个人仓库&#xff1a;CourseNotes&#xff0c;欢迎fork和star&#xff0c;拥抱开源&#xff0c;一起完善。 该笔记是最初是没打算发网上的&#xff0c;所以很多地方都为了自我阅读方便&#xff0c;我理解了的地方就少有解释&#xf…

indexedDB---掌握浏览器内建数据库的基本用法

1.认识indexedDB IndexedDB 是一个浏览器内建的数据库&#xff0c;它可以存放对象格式的数据&#xff0c;类似本地存储localstore&#xff0c;但是相比localStore 10MB的存储量&#xff0c;indexedDB可存储的数据量远超过这个数值&#xff0c;具体是多少呢&#xff1f; 默认情…

MLP多层感知器:AI人工智能神经网络的基石

MLP 是指多层感知器&#xff08;Multilayer Perceptron&#xff09;&#xff0c;是一种基础人工神经网络模型&#xff08;ANN&#xff0c;Artificial Neural Network&#xff09;。MLP 的核心是通过深度学习从大量数据中学习特征和模式&#xff0c;并训练参数。通过参数与激活函…

AMSR/ADEOS-II L1A Raw Observation Counts V003地球表面和大气微波辐射的详细观测数据

AMSR/ADEOS-II L1A Raw Observation Counts V003 简介 AMSR/ADEOS-II L1A Raw Observation Counts V003数据是由日本航空航天研究开发机构&#xff08;JAXA&#xff09;的AMSR (Advanced Microwave Scanning Radiometer)仪器收集的一组原始观测计数数据。这些数据是从ADEOS-I…

第一题(伏羲六十四卦)

题目&#xff1a; 首先伏羲64卦解密 再用base64解密即可

全栈人工智能工程师:现代博学者

任何在团队环境中工作过的人都知道&#xff0c;每个成功的团队都有一个得力助手——无论你的问题性质如何&#xff0c;他都能帮助你。在传统的软件开发团队中&#xff0c;这个人是一个专业的程序员&#xff0c;也是另一种技术的专家&#xff0c;可以是像Snowflake这样的数据库技…

编写水文专业串口通讯软件的开发经历

编写水文专业串口通讯软件的开发经历 一、关于开发 YAC9900 水位雨量 RTU 通讯软件二、软件开发遇到的问题和困难1、开发架构的适应2、开发语言的学习3、.net core 8 架构中串口构建的难点4、YAC9900 水位雨量 RTU 通讯软件开发中的 UI 冻结 三、发现问题解决问题的具体办法1、…

Android Studio无法连接夜神模拟器的解决方案

一、AS检测不到夜神模拟器 1、问题描述 在按照教程【如何安装和使用Android夜神模拟器】进入夜神的bin目录&#xff0c;输入连接命令回车后&#xff0c;终端显示的already connected to 127.0.0.1:62001&#xff0c;但是AS的Running Devices并没有显示夜神模拟器。 2、解决方…

鸿蒙HarmonyOS NEXT角落里的知识:ArkTS高性能编程实践

概述 本文主要提供应用性能敏感场景下的高性能编程的相关建议&#xff0c;助力开发者开发出高性能的应用。高性能编程实践&#xff0c;是在开发过程中逐步总结出来的一些高性能的写法和建议&#xff0c;在业务功能实现过程中&#xff0c;我们要同步思考并理解高性能写法的原理…

【Java】已解决java.nio.channels.ClosedChannelException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.nio.channels.ClosedChannelException异常 在Java的NIO&#xff08;New I/O&#xff09;编程中&#xff0c;java.nio.channels.ClosedChannelException是一个常见的异常…

韩国裸机云站群服务器托管租用方案

随着网络技术的飞速发展&#xff0c;站群服务器在网站运营中扮演着越来越重要的角色。韩国裸机云站群服务器&#xff0c;以其独特的优势&#xff0c;如地理位置优越、价格相对较低、技术实力雄厚等&#xff0c;吸引了众多企业的关注。本文将为您详细介绍韩国裸机云站群服务器的…

PostgreSQL配置SSL连接

1、系统需要有openssl、openssl-devel包 yum -y install openssl openssl-devel 2、查看当前数据库是否使用openssl编译 pg_config|grep CONFIGURE 如果没有重新编译 make clean make && make install 3、服务器端证书配置 服务器端需生成三个文件: root.crt(根证…

[RK-Linux] RK3562 I2C驱动TP芯片GSL3680

TP芯片GSL3680 1、简介 GSL3680是一款电容屏多点触摸控制单芯片,其芯片内部框架图如下所示: GSL3680采用了独特的互电容感应技术,可以在1ms内测量多达192个节点,支持广泛的传感器选择,包括单层或双层ITO,玻璃或薄膜,采用了先进的抗电磁干扰信号处理技术,使其对各种干…

新火种AI|Claude 3.5一夜封王超越GPT-4o!留给OpenAI的时间真的不多了...

AI大模型更新换代的速度&#xff0c;的确快到令人难以想象。 相信很多人现在对“最先进AI大模型”的印象还停留在GPT-4&#xff0c;但事实上&#xff0c;大模型领域的头把交椅早已悄然易主了好几回。就在GPT-4惊艳全球不久之后&#xff0c;其“死对头” Anthropic发布了Claude…

Tomcat基础详解

第一篇&#xff1a;Tomcat基础篇 lecture&#xff1a;邓澎波 一、构建Tomcat源码环境 工欲善其事必先利其器&#xff0c;为了学好Tomcat源码&#xff0c;我们需要先在本地构建一个Tomcat的运行环境。 1.源码环境下载 源码有两种下载方式&#xff1a; 1.1 官网下载 https://…