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

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

}
#endif

int 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


http://www.kler.cn/a/290965.html

相关文章:

  • iterm2 focus时灰色蒙层出现的解决办法
  • 深度学习的DataLoader是什么数据类型,为什么不可用来索引
  • MySql:基本查询
  • SAP RESTful架构和OData协议
  • 基于蓝牙通信的手机遥控智能灯(论文+源码)
  • Windows安全中心(病毒和威胁防护)的注册
  • Java开发笔记--通用消息组件设计(移动短信、华为短信、163邮件)
  • chapter03 流程语句 知识点Note
  • JS基础-ClassList -移动端插件的引入-touch事件-sessionStorage 和 localStorage
  • STM32—I2C的基本时序,MU6050的ID读取
  • 云计算和传统IT相比,有哪些优势?
  • map和set的区别和底层实现是什么?map取值的 find,[],at方法的区别
  • GitLab 是什么?GitLab使用常见问题解答
  • 论文浅尝 | TaxoLLaMA: 用基于WordNet的模型来解决多个词汇语义任务(ACL2024)
  • 微信小程序npm扩展能力探究
  • Linux性能监控神器:深入nmon详解与使用
  • 经验笔记:Maven 与 Gradle —— Java 构建工具对比
  • 每日一练4:牛牛的快递(含链接)
  • @DateTimeFormat和@JsonFormat的区别和使用场景
  • 前端工程化之【模块化规范】
  • 黑马JavaWeb开发笔记15——用JAVA进行Web开发时候的请求、响应流程,B\S架构、C\S架构(概述)
  • log4j漏洞原理以及复现
  • 【JUC】12-CAS
  • Nordic Collegiate Programming ContestNCPC 2021
  • Linux基础 -- 获取CPU负载信息
  • 在react 中还有另外一种three.js 渲染方式