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

ffmpeg音视频开发从入门到精通——ffmpeg日志及目录操作

文章目录

    • FFMPEG
    • 1. 操作日志
      • 1. `AV_LOG_ERROR`
      • 2. `AV_LOG_WARNING`
      • 3. `AV_LOG_INFO`
      • 4. `AV_LOG_DEBUG`
      • 5. 日志级别的使用
    • 2. 文件移动和删除
      • 1. `avpriv_io_delete()`
        • 功能
        • 函数原型
        • 输入参数
        • 返回值
      • 2. `avpriv_io_move()`
        • 功能
        • 函数原型
        • 输入参数
        • 返回值
      • 案例
        • 代码功能概述
        • 详细步骤
    • 3. 操作目录重要函数
        • 代码功能概述
        • 详细步骤

FFMPEG

1. 操作日志

在 FFmpeg 中,日志系统用于记录不同级别的消息,以帮助开发者和用户调试和监控程序的运行状态。FFmpeg 提供了多种日志级别,以下是对 AV_LOG_ERRORAV_LOG_WARNINGAV_LOG_INFOAV_LOG_DEBUG 的介绍:

1. AV_LOG_ERROR

  • 描述:表示错误级别的日志消息。
  • 用途:用于记录严重错误,这些错误通常会导致程序无法继续执行或导致某个功能失败。
  • 示例:文件打开失败、解码器初始化失败等。

2. AV_LOG_WARNING

  • 描述:表示警告级别的日志消息。
  • 用途:用于记录可能会影响程序正常运行的警告,但程序仍然可以继续执行。警告通常表示潜在的问题,建议开发者注意。
  • 示例:输入文件格式不支持、某些参数不推荐使用等。

3. AV_LOG_INFO

  • 描述:表示信息级别的日志消息。
  • 用途:用于记录一般信息,通常用于提供程序的运行状态或进度。信息级别的日志不会影响程序的执行。
  • 示例:成功打开文件、开始编码/解码过程等。

4. AV_LOG_DEBUG

  • 描述:表示调试级别的日志消息。
  • 用途:用于记录详细的调试信息,通常用于开发和调试阶段。调试信息可以帮助开发者理解程序的内部状态和行为。
  • 示例:变量值、函数调用的详细信息等。

5. 日志级别的使用

FFmpeg 的日志系统允许开发者根据需要设置日志级别,以控制输出的详细程度。可以通过 av_log_set_level() 函数设置全局日志级别,只有高于或等于该级别的日志消息才会被输出。

FFmpeg 的日志系统提供了多种日志级别,帮助开发者记录和监控程序的运行状态。通过合理使用这些日志级别,可以有效地调试和维护 FFmpeg 应用程序。

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)
# 链接FFmpeg库
target_link_libraries(FFmpeg_exercise ${FFMPEG_LIBRARIES})

通过预处理器指令#ifdef __cplusplus来检查代码是否在C++环境中编译。
如果是,它将开始一个extern "C"块,这意味着在该块内包含的代码将使用C的链接规则。
这通常用于包含C库的头文件,以确保C++编译器不会对函数名进行名称修饰。

  • main.cpp

#ifdef __cplusplus
extern "C" {
#endif// 包含FFmpeg的头文件#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libavutil/avutil.h>
#ifdef __cplusplus}
#endifint main() {av_log_set_level(AV_LOG_DEBUG);av_log(nullptr,AV_LOG_DEBUG,"Hello World!:%d\n",10);av_log(nullptr,AV_LOG_INFO,"Hello World! test: INFO\n");av_log(nullptr,AV_LOG_ERROR,"Hello World! test: ERROR\n");return 0;
}

image-20240621212832462

2. 文件移动和删除

avpriv_io_delete()avpriv_io_move() 是 FFmpeg 中用于文件操作的私有函数。它们通常用于处理文件的删除和移动操作。以下是对这两个函数的介绍,包括它们的用法和参数。

1. avpriv_io_delete()

功能
  • 删除指定的文件。
函数原型
int avpriv_io_delete(const char *filename);
输入参数
  • *const char filename:
    • 要删除的文件的路径。
返回值
  • 返回 0 表示成功,返回负数表示失败(例如,文件不存在或没有权限)。

2. avpriv_io_move()

功能
  • 移动(重命名)指定的文件。
函数原型
int avpriv_io_move(const char *src_filename, const char *dst_filename);
输入参数
  • *const char src_filename:

    • 源文件的路径,即要移动的文件。
  • *const char dst_filename:

    • 目标文件的路径,即文件移动后要保存的位置。
返回值
  • 返回 0 表示成功,返回负数表示失败(例如,源文件不存在、目标路径无效或没有权限)。

  • avpriv_io_delete() 用于删除指定的文件,返回值指示操作是否成功。

  • avpriv_io_move() 用于移动或重命名文件,同样返回值指示操作是否成功。

  • 这两个函数在处理文件时提供了基本的文件管理功能,适用于需要对文件进行删除或移动操作的场景。

  • 案例


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)
# 链接FFmpeg库
target_link_libraries(FFmpeg_exercise ${FFMPEG_LIBRARIES})

这段代码是一个简单的 C++ 程序,使用 FFmpeg 库来执行文件操作,包括创建、重命名和删除文件。以下是对代码的逐步分析和解释:

案例

代码功能概述
  1. 创建并写入文件:创建一个文本文件并写入一些内容。
  2. 重命名文件:将创建的文件重命名。
  3. 删除文件:删除重命名后的文件。
  4. 日志记录:使用 FFmpeg 的日志系统记录操作的结果。
详细步骤
  1. 包含头文件

    #ifdef __cplusplus
    extern "C" {
    #endif#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libavutil/avutil.h>
    #ifdef __cplusplus
    }
    #endif
    
    • 通过预处理器指令 #ifdef __cplusplus 检查代码是否在 C++ 环境中编译。如果是,它将开始一个 extern "C" 块,以确保在该块内包含的 C 语言头文件不会被 C++ 编译器进行名称修饰。这是为了确保可以正确链接 FFmpeg 的 C 函数。
  2. 主函数

    int main() {
    
    • 定义了 main() 函数,程序的入口点。
  3. 创建并写入文件

    std::ofstream outfile("./test.txt");
    outfile << "hello world!\n" << std::endl;
    outfile << "this is a test file" << std::endl;
    outfile.close();
    
    • 创建一个名为 test.txt 的文本文件,并写入两行内容。
    • 使用 std::ofstream 来处理文件输出,并在写入完成后关闭文件。
  4. 检查文件是否关闭

    if (outfile.is_open()) {av_log(nullptr, AV_LOG_ERROR, "Failed to close file: %s", "./test.txt");return 1; // 如果文件未关闭,返回错误代码
    }
    
    • 检查文件是否成功关闭。如果未关闭,记录错误信息并返回错误代码 1
  5. 设置日志级别

    av_log_set_level(AV_LOG_DEBUG);
    
    • 设置 FFmpeg 的日志级别为调试级别,以便输出更详细的日志信息。
  6. 重命名文件

    int ret {0};
    ret = avpriv_io_move("./test.txt", "./demo.txt");
    if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "Failed to rename text.txt\n");
    }
    av_log(nullptr, AV_LOG_INFO, "SUCCESSED TO RENAME FILE TEXT.TXT\n");
    
    • 使用 avpriv_io_movetest.txt 重命名为 demo.txt。如果重命名失败,记录错误信息;如果成功,记录成功信息。
  7. 删除文件

    ret = avpriv_io_delete("./demo.txt");
    if (ret < 0) {av_log(nullptr, AV_LOG_ERROR, "Failed to delete demo.txt\n");
    }
    av_log(nullptr, AV_LOG_INFO, "SUCCESSED TO delete FILE TEXT.TXT\n");
    
    • 使用 avpriv_io_delete 删除 demo.txt。如果删除失败,记录错误信息;如果成功,记录成功信息。
  8. 注释的日志记录

    // av_log(nullptr, AV_LOG_DEBUG, "Hello World!:%d\n", 10);
    // av_log(nullptr, AV_LOG_INFO, "Hello World! test: INFO\n");
    // av_log(nullptr, AV_LOG_ERROR, "Hello World! test: ERROR\n");
    
    • 这些行是注释掉的日志记录示例,展示了如何使用 av_log 函数记录不同级别的日志信息。

这段代码展示了使用 FFmpeg 的 I/O 函数来创建、重命名和删除文件,同时结合 C++ 的标准文件操作。它还使用 FFmpeg 的日志系统记录操作的结果,包括成功和失败的信息。整体上,这段代码是一个简单的示例,演示了如何在 C++ 中使用 FFmpeg 进行基本的文件管理操作。

image-20240621222021634

3. 操作目录重要函数

  1. avio_open_dir():

    • 功能:打开一个目录以供进一步读取。
    • 返回值:成功时返回指向AVIODirContext的指针,失败时返回NULL
    • 使用:此函数用于初始化目录遍历,获取指向目录中第一个条目的指针。
  2. AVIODirContext:

    • 类型:这是一个不透明的结构体,用于表示打开的目录和遍历状态。
    • 用途:在使用avio_open_dir()成功打开目录后,会返回一个AVIODirContext类型的指针,该指针在后续的目录遍历中使用。
  3. avio_read_dir():

    • 功能:读取目录中的下一个条目。
    • 参数:传入AVIODirContext指针。
    • 返回值:成功时返回指向AVIoDirEntry的指针,遍历完成或失败时返回NULL
    • 使用:在每次调用avio_read_dir()后,都会移动到目录中的下一个条目。如果已经到达目录末尾或发生错误,则返回NULL
  4. AVIoDirEntry:

    • 类型:这是一个结构体,包含有关目录条目的信息,如文件名、文件类型等。
    • 用途:通过avio_read_dir()获取的每个条目都是一个AVIoDirEntry对象,它包含了关于文件或目录的信息。
  5. avio_close_dir():

    • 功能:关闭之前用avio_open_dir()打开的目录。
    • 参数:传入AVIODirContext指针。
    • 返回值:返回0表示成功,返回负数表示失败。
    • 使用:完成目录遍历后,应当调用此函数来释放与AVIODirContext关联的资源。
  • 案例
    这段代码是一个简单的 C++ 程序,使用 FFmpeg 库来执行一些文件和目录操作。以下是对代码的逐步分析和解释:
代码功能概述
  1. 打开目录:使用 FFmpeg 的 avio_open_dir 函数打开当前目录。
  2. 读取目录内容:循环读取目录中的文件和子目录,并打印它们的名称和大小。
  3. 创建和写入文件:创建一个文本文件并写入一些内容。
  4. 重命名文件:将创建的文件重命名。
  5. 删除文件:删除重命名后的文件。
详细步骤
  1. 包含头文件

    • 包含了 FFmpeg 的相关头文件以及 C++ 的输入输出流库。
  2. 主函数

    • 定义了 main() 函数,程序的入口点。
  3. 打开目录

    ret = avio_open_dir(&ctx,"./", nullptr);
    
    • 使用 avio_open_dir 打开当前目录("./")。如果打开失败,记录错误信息并跳转到 _fail 标签。
  4. 读取目录内容

    while(true){ret = avio_read_dir(ctx,&entry);...if(!entry){break;}av_log(nullptr,AV_LOG_INFO,"%lld PRID64%s\n",entry->size,entry->name);avio_free_directory_entry(&entry);
    }
    
    • 使用 avio_read_dir 循环读取目录中的每个条目(文件或子目录)。
    • 如果读取成功,打印条目的大小和名称。
    • 使用 avio_free_directory_entry 释放内存,防止内存泄漏。
  5. 关闭目录

    _fail:
    avio_close_dir(&ctx);
    
    • _fail 标签处关闭目录上下文,确保资源被释放。
  6. 创建和写入文件

    std::ofstream outfile("./test.txt");
    outfile<<"hello world!\n"<<std::endl;
    outfile<<"this is a test file"<<std::endl;
    outfile.close();
    
    • 创建一个名为 test.txt 的文本文件,并写入两行内容。
    • 关闭文件。
  7. 检查文件是否关闭

    if (outfile.is_open()) {av_log(nullptr,AV_LOG_ERROR,"Failed to close file: %s","./test.txt");return 1;
    }
    
    • 检查文件是否成功关闭。如果未关闭,记录错误并返回错误代码。
  8. 重命名文件

    ret = avpriv_io_move("./test.txt","./demo.txt");
    
    • 使用 avpriv_io_movetest.txt 重命名为 demo.txt。如果重命名失败,记录错误信息。
  9. 删除文件

    ret = avpriv_io_delete("./demo.txt");
    
    • 使用 avpriv_io_delete 删除 demo.txt。如果删除失败,记录错误信息。
  10. 日志记录

    • 使用 av_log 函数记录各种操作的结果,包括成功和失败的信息。

这段代码展示了如何使用 FFmpeg 的 I/O 函数来打开目录、读取文件信息、创建和写入文件、重命名文件以及删除文件。它结合了 FFmpeg 的功能和 C++ 的标准文件操作,提供了一个简单的示例来演示文件管理的基本操作。
image-20240622093515869

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 第143天:内网安全-权限维持自启动映像劫持粘滞键辅助屏保后门WinLogon
  • 探寻 IP 代理地址繁多之因
  • 【WPF】WPF学习之【二】布局学习
  • Spring Boot 部署(jar包)
  • 手机TF卡格式化后数据恢复:方法、挑战与预防措施
  • KRTS网络模块:UDP通信
  • MQ-7一氧化碳传感器详解(STM32)
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • PostgreSQL的repmgr工具介绍
  • java基础-线程实现
  • 自己实现一个分布式锁
  • 【自然语言处理】调用NLTK数据失败‘wordnet‘和‘punkt‘不存在[Errno 11004]问题解决
  • BIO、NIO、AIO 有什么区别?
  • 机器学习模型中的因果关系:引入单调约束
  • 【SQL】常见语句合集
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 10个确保微服务与容器安全的最佳实践
  • 4个实用的微服务测试策略
  • ComponentOne 2017 V2版本正式发布
  • docker python 配置
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • Hibernate【inverse和cascade属性】知识要点
  • JAVA_NIO系列——Channel和Buffer详解
  • JS 面试题总结
  • js对象的深浅拷贝
  • Leetcode 27 Remove Element
  • LeetCode18.四数之和 JavaScript
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • PAT A1120
  • Rancher-k8s加速安装文档
  • REST架构的思考
  • Vue.js源码(2):初探List Rendering
  • 从setTimeout-setInterval看JS线程
  • 大主子表关联的性能优化方法
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 缓存与缓冲
  • 前端攻城师
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 智能网联汽车信息安全
  • 阿里云ACE认证之理解CDN技术
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (06)Hive——正则表达式
  • (7)STL算法之交换赋值
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • ***检测工具之RKHunter AIDE
  • *算法训练(leetcode)第四十七天 | 并查集理论基础、107. 寻找存在的路径
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost