如何在Qt4中使用libavcodec?

3

如何在Qt4中使用libavcodec访问单个视频帧?

通过编译这个示例并验证视频流可以被libavcodec解码后,我将源代码移植到我的C++程序中。现在,av_open_input_file()无法打开我的视频文件(返回错误码:-2)。

当前的调用如下:

...
// Register all formats and codecs
avcodec_register_all();

// Open video file
QString videoFileName("/absolute/path/to/video.avi"); // from somewhere else in the application
const char* fileName = videoFileName.toStdString().c_str();
int err = 0;
if((err = av_open_input_file(&pFormatCtx, fileName, NULL, 0, NULL)) != 0)
{
    doErrorHandling(err, fileName); // err = -2
}

当我在调试器中查看const char* fileName时,它看起来是正确的。我是否在混合C和C++代码方面犯了一些基本错误(首次尝试时,我只是将示例代码转储到类的构造函数中)?

注意:为了让应用程序编译,我像这样包含头文件:

extern "C"
{
#define __STDC_CONSTANT_MACROS // for UINT64_C
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}

我还尝试将视频文件的路径硬编码到应用程序中,但没有成功:

av_open_input_file(&pFormatCtx, "/home/bjoernz/video.avi", NULL, 0, NULL);

我成功使用 g++ 编译并运行了这个示例 (avcodec_sample.0.5.0.c)。


避免使用这样的语句:const char* fileName = videoFileName.toStdString().c_str(); 因为你的指针指向了临时对象的内部数据,这可能会导致奇怪的错误,因为在分号之后,该指针所指向的内存将被释放。你应该将整个videoFileName.toStdString().c_str()作为参数传递。此外,.toStdString可能会丢失编码,应改用.toLocal8Bit()(它返回QByteArray,但QByteArray有重载的(const char *)转换)。 - Kamil Klimek
谢谢,我正希望得到这样的建议。我通过调用 videoFileName.toLocal8Bit().constData() 来获取文件名。为了方便调试,我先将其赋值给一个变量。 - bjoernz
你不能把它赋值给变量,因为它仍然是临时对象。请记住QByteArray自动转换为const char *,所以你只需要这样做:QByteArray fileName = videoFileName.toLocal8Bit(); 然后将其作为参数传递给av_open_input_file(&pFormatCtx, fileName, ...)函数。 - Kamil Klimek
2个回答

2

错误代码-2表示没有这个文件或目录。我相信你尝试打开的文件不在你运行应用程序时的“当前工作目录”中。


我承认 QString videoFileName("video.avi") 是有误导性的。通常 videoFileName 包含所需文件的绝对路径(我将在问题中澄清这一点)。 - bjoernz

2

好尴尬:

当我将示例的源代码转移到我自己的C++应用程序中时,出现了连接器错误,告诉我av_register_all();不可用...后来我把它重命名为avcodec_register_all(),稍后解决了连接器问题,就忘了这件事...

解决方案: 将avcodec_register_all()更改为av_register_all()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接