FFmpeg学习记录(二)—— ffmpeg多媒体文件处理

embedded/2024/11/14 6:33:07/

1.日志系统

常用的日志级别:

  • AV_LOG_ERROR
  • AV_LOG_WARNING
  • AV_LOG_INFO
  • AV_LOG_DEBUG
#include <stdio.h>
#include <libavutil/log.h>int main(int argc, char *argv[])
{av_log_set_level(AV_LOG_DEBUG);av_log(NULL, AV_LOG_DEBUG, "hello world!\n");return 0;
}

2.文件的删除与重命名

文件删除与重命名的API:

  • avpriv_io_delete()
  • avpriv_io_move()
	int ret;// 重命名ret = avpriv_io_move("111.txt", "222.txt");if(ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to rename\n");return -1;}av_log(NULL, AV_LOG_INFO, "Success to renmae\n");// 删除ret = avpriv_io_delete("./test.txt");if(ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to delete\n");return -1;}av_log(NULL, AV_LOG_INFO, "Success to delete\n");

3.目录操作

操作目录重要函数:

  • avio_open_dir()
  • avio_read_dir()
  • avio_close_dir()

操作目录重要结构体:

  • AVIODirContext
  • AVIODirEntry
    avdevice_register_all();int ret;AVIODirContext *ctx = NULL;AVIODirEntry *entry = NULL;av_log_set_level(AV_LOG_INFO);ret = avio_open_dir(&ctx, "./", NULL);if(ret < 0){av_log(NULL, AV_LOG_ERROR, "Can't open dir: %s\n", av_err2str(ret));return -1;}while(1) {avio_read_dir(ctx, &entry);if(ret < 0){av_log(NULL, AV_LOG_ERROR, "Can't read dir: %s\n", av_err2str(ret));goto __fail;}if(!entry) {break;}av_log(NULL, AV_LOG_INFO,"%-9s %12"PRId64"  %s\n", entry->size, entry->name);avio_free_directory_entry(&entry);}__fail:avio_close_dir(&ctx);

4.抽取音频数据

  • 1.处理一些参数
  • 2.打开多媒体文件
  • 3.从多媒体文件中找到音频流
  • 4.打开目的文件的上下文
  • 5.为目的文件,创建一个新的音频流
  • 6.设置输出音频参数
  • 7.写多媒体文件头到目的文件
  • 8…从源多媒体文件中读音频数据到目的文件中
  • 9.写多媒体文件尾到文件中
  • 10.将申请的资源释放掉

步骤比较多,一点一点来实现:

 // 1.处理一些参数if(argc < 3) {av_log(NULL, AV_LOG_INFO, "argument must be 3");exit(-1);}src = argv[1];dst = argv[2];// 2.打开多媒体文件ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);if(ret < 0) {av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));exit(-1);}
// 3.从多媒体文件中找到音频流idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);if(idx < 0) {av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio\n");goto _ERROR;}// 4.打开目的文件的上下文oFmtCtx = avformat_alloc_context();if(!oFmtCtx) {av_log(NULL, AV_LOG_ERROR, "No Memory\n");goto _ERROR;}outFmt = av_guess_format(NULL, dst, NULL);oFmtCtx->oformat = outFmt;// 5.为目的文件,创建一个新的音频流outStream = av_format_new_stream(oFmtCtx, NULL);// 6.设置输出音频参数inStream = pFmtCtx->stream[idx];avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);outStream->codecpar->codec_tag = 0;
    // 7.写多媒体文件头到目的文件ret = avformat_write_header(oFmtCtx, NULL);if(ret < 0) {av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));goto _ERROR;}// 8.聪源多媒体文件中读到音频数据到目的文件中while(av_read_frame(pFmtCtx, &pkt) >= 0) {if(pkt.stream_index == idx) {pkt.pts = av_rescale_q_rnd(pkt.pts, inStream->time_base, outStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);pkt.dts = pkt.dts;pkt.duration = av_rescale_q(pkt.duration, inStream->time_base, outStream->time_base);pkt.stream_index = 0;pkt.pos = -1;av_interleaved_write_frame(oFmtCtx, &pkt);av_packet_unref(&pkt);}}// 9.写多媒体文件尾到文件中av_write_trailer(oFmtCtx);// 10.将申请的资源释放掉
_ERROR:if(pFmtCtx) {avformat_close_input(&pFmtCtx);pFmtCtx = NULL;}if(oFmtCtx->pb) {avio_close(oFmtCtx->pb);}if(oFmtCtx) {avformat_free_context(oFmtCtx);oFmtCtx = NULL;}

6.抽取视频数据

与处理音频流程相同,简单修改即可

 // 3.从多媒体文件中找到视频流idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if(idx < 0) {av_log(pFmtCtx, AV_LOG_ERROR, "Does not include VIDEO\n");goto _ERROR;}... ...// 8.从源多媒体文件中读到视频数据到目的文件中while(av_read_frame(pFmtCtx, &pkt) >= 0) {if(pkt.stream_index == idx) {pkt.pts = av_rescale_q_rnd(pkt.pts, inStream->time_base, outStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);pkt.dts = av_rescale_q_rnd(pkt.dts, inStream->time_base, outStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);// pkt.dts = pkt.dts;pkt.duration = av_rescale_q(pkt.duration, inStream->time_base, outStream->time_base);pkt.stream_index = 0;pkt.pos = -1;av_interleaved_write_frame(oFmtCtx, &pkt);av_packet_unref(&pkt);}}

6.多媒体格式转封装

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

7.视频裁剪

在这里插入图片描述

程序是在上面的程序基础上修改的,这里就把核心修改地方贴出来。

有两个注意点:(对应下面的修改2和修改3)

第一个是音视频时间的问题。

针对音频:从第5秒钟截取,那他就是第5秒。针对视频:因为有IPB 帧,如果刚好第5秒是P帧或者B帧,没有了I帧,那么就不能解码成功,播放的时候就会花屏。

解决:告诉ffmpeg如果不是I帧,就要向前或者向后找最近的I帧

第二个是时间的问题。

由于是裁剪,所以需要计算相对时间。 使用后面的时间减去第一个时间基的时间,这样子才能保证时间的正确性。音频的dts和pts是相同的,而视频可能是不同的,所以这里需要多加一步判断。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/embedded/33233.html

相关文章

编写你的第一个 golang 的应用程序

进行你的第一个golang的程序 当你把程序都安装好以后 环境变量配置 好 vscode 插件下载好以后 1. 创建一个test.go 的文件 //主包&#xff0c;可执行文件所在包 package main//导入包 import "fmt"//主函数&#xff0c;入口函数 func main() { }2.解释 需要导入包 …

数字资产:究竟靠什么形成?

在当今数字化的时代&#xff0c;数字资产成为了一个备受关注的话题。那么&#xff0c;数字资产究竟是靠什么形成的呢&#xff1f;这是一个值得我们深入探讨的问题。 数字资产的形成离不开以下几个关键因素&#xff1a; 1.技术创新&#xff1a;不断发展的科技为数字资产的产生…

绘唐3软件注册邀请码在哪

绘唐3软件注册邀请码在哪 点击在这里哦 安装完成 解压所需配套驱动 将您下载好的驱动解压后会获得如下文件夹 将驱动程序移动至安装目录下的SJ_SoftwareData文件夹内 打开绘唐3安装目录 打开SJ_SoftwareData文件夹将解压后的驱动程序移动至此 ❗❗…

5G图标显示分析

1、问题现象 MTK平台项目中出现一个5G图标显示问题&#xff0c;注册5G时&#xff0c;拨打电话&#xff0c;对比机图标显示回落到4G&#xff0c;测试机一直显示5G。 2、原因分析 2.1、NSA显示规则 根据GSMA协议&#xff0c;NSA架构下5G图标显示有如下4种. 2.2、Android中显示5G…

【openLooKeng集成Hive连接器完整过程】

【openLooKeng集成Hive连接器完整过程】 一、摘要二、正文2.1 环境说明2.2 Hadoop安装2.2.1. 准备工作2.2.2 在协调节点coordinator上进行安装hadoop2.2.3、将Hadoop安装目录分发到从节点worker2.2.4、在协调节点coordinator上启动hadoop集群2.3 MySQL安装2.4 Hive安装及基本操…

git的操作命令有哪些、PyCharm 中常用的 Git 操作命令、-b参数的使用、stash命令在git中的使用、rebase在git中的使用

1 git的操作命令有哪些 2 PyCharm 中常用的 Git 操作命令 3 -b参数的使用 4 stash命令在git中的使用 5 rebase在git中的使用 1 git的操作命令有哪些 1. **初始化一个新的仓库**&#xff1a;git init2. **克隆仓库**&#xff1a;git clone <repository_url>3. **添加文件…

5-用户权限控制(前端)

1.登录成功后&#xff0c;调用状态管理中对应的设置菜单的方法 //调用store中的setMenu函数 this.$store.commit(setMenu,data.data.data)2.将后端返回的菜单数据存入Cookie中 //设置菜单的方法setMenu(state, val) {state.menu valCookie.set("menu", JSON.strin…

华为机考入门python3--(21)牛客21- 简单密码

分类&#xff1a;字符串 知识点&#xff1a; 字符的Unicode码 num ord(my_char) 一个整数转换为一个对应的 ASCII 字符 my_char chr(num) 题目来自【牛客】 import sysdef transform_password(password):result ""for char in password:if a < char…