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_ERROR
、AV_LOG_WARNING
、AV_LOG_INFO
和 AV_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;
}
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 库来执行文件操作,包括创建、重命名和删除文件。以下是对代码的逐步分析和解释:
案例
代码功能概述
- 创建并写入文件:创建一个文本文件并写入一些内容。
- 重命名文件:将创建的文件重命名。
- 删除文件:删除重命名后的文件。
- 日志记录:使用 FFmpeg 的日志系统记录操作的结果。
详细步骤
-
包含头文件:
#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 函数。
- 通过预处理器指令
-
主函数:
int main() {
- 定义了
main()
函数,程序的入口点。
- 定义了
-
创建并写入文件:
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
来处理文件输出,并在写入完成后关闭文件。
- 创建一个名为
-
检查文件是否关闭:
if (outfile.is_open()) { av_log(nullptr, AV_LOG_ERROR, "Failed to close file: %s", "./test.txt"); return 1; // 如果文件未关闭,返回错误代码 }
- 检查文件是否成功关闭。如果未关闭,记录错误信息并返回错误代码
1
。
- 检查文件是否成功关闭。如果未关闭,记录错误信息并返回错误代码
-
设置日志级别:
av_log_set_level(AV_LOG_DEBUG);
- 设置 FFmpeg 的日志级别为调试级别,以便输出更详细的日志信息。
-
重命名文件:
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_move
将test.txt
重命名为demo.txt
。如果重命名失败,记录错误信息;如果成功,记录成功信息。
- 使用
-
删除文件:
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
。如果删除失败,记录错误信息;如果成功,记录成功信息。
- 使用
-
注释的日志记录:
// 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 进行基本的文件管理操作。
3. 操作目录重要函数
-
avio_open_dir()
:- 功能:打开一个目录以供进一步读取。
- 返回值:成功时返回指向
AVIODirContext
的指针,失败时返回NULL
。 - 使用:此函数用于初始化目录遍历,获取指向目录中第一个条目的指针。
-
AVIODirContext
:- 类型:这是一个不透明的结构体,用于表示打开的目录和遍历状态。
- 用途:在使用
avio_open_dir()
成功打开目录后,会返回一个AVIODirContext
类型的指针,该指针在后续的目录遍历中使用。
-
avio_read_dir()
:- 功能:读取目录中的下一个条目。
- 参数:传入
AVIODirContext
指针。 - 返回值:成功时返回指向
AVIoDirEntry
的指针,遍历完成或失败时返回NULL
。 - 使用:在每次调用
avio_read_dir()
后,都会移动到目录中的下一个条目。如果已经到达目录末尾或发生错误,则返回NULL
。
-
AVIoDirEntry
:- 类型:这是一个结构体,包含有关目录条目的信息,如文件名、文件类型等。
- 用途:通过
avio_read_dir()
获取的每个条目都是一个AVIoDirEntry
对象,它包含了关于文件或目录的信息。
-
avio_close_dir()
:- 功能:关闭之前用
avio_open_dir()
打开的目录。 - 参数:传入
AVIODirContext
指针。 - 返回值:返回0表示成功,返回负数表示失败。
- 使用:完成目录遍历后,应当调用此函数来释放与
AVIODirContext
关联的资源。
- 功能:关闭之前用
- 案例
这段代码是一个简单的 C++ 程序,使用 FFmpeg 库来执行一些文件和目录操作。以下是对代码的逐步分析和解释:
代码功能概述
- 打开目录:使用 FFmpeg 的
avio_open_dir
函数打开当前目录。 - 读取目录内容:循环读取目录中的文件和子目录,并打印它们的名称和大小。
- 创建和写入文件:创建一个文本文件并写入一些内容。
- 重命名文件:将创建的文件重命名。
- 删除文件:删除重命名后的文件。
详细步骤
-
包含头文件:
- 包含了 FFmpeg 的相关头文件以及 C++ 的输入输出流库。
-
主函数:
- 定义了
main()
函数,程序的入口点。
- 定义了
-
打开目录:
ret = avio_open_dir(&ctx,"./", nullptr);
- 使用
avio_open_dir
打开当前目录("./"
)。如果打开失败,记录错误信息并跳转到_fail
标签。
- 使用
-
读取目录内容:
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
释放内存,防止内存泄漏。
- 使用
-
关闭目录:
_fail: avio_close_dir(&ctx);
- 在
_fail
标签处关闭目录上下文,确保资源被释放。
- 在
-
创建和写入文件:
std::ofstream outfile("./test.txt"); outfile<<"hello world!\n"<<std::endl; outfile<<"this is a test file"<<std::endl; outfile.close();
- 创建一个名为
test.txt
的文本文件,并写入两行内容。 - 关闭文件。
- 创建一个名为
-
检查文件是否关闭:
if (outfile.is_open()) { av_log(nullptr,AV_LOG_ERROR,"Failed to close file: %s","./test.txt"); return 1; }
- 检查文件是否成功关闭。如果未关闭,记录错误并返回错误代码。
-
重命名文件:
ret = avpriv_io_move("./test.txt","./demo.txt");
- 使用
avpriv_io_move
将test.txt
重命名为demo.txt
。如果重命名失败,记录错误信息。
- 使用
-
删除文件:
ret = avpriv_io_delete("./demo.txt");
- 使用
avpriv_io_delete
删除demo.txt
。如果删除失败,记录错误信息。
- 使用
-
日志记录:
- 使用
av_log
函数记录各种操作的结果,包括成功和失败的信息。
- 使用
这段代码展示了如何使用 FFmpeg 的 I/O 函数来打开目录、读取文件信息、创建和写入文件、重命名文件以及删除文件。它结合了 FFmpeg 的功能和 C++ 的标准文件操作,提供了一个简单的示例来演示文件管理的基本操作。