FFmpeg 的错误码是错误诊断和推测的工具,是一个 int 型的负数值,以 AVERROR_
开头,定义在
libavutil/error.h
中。
例如,如果打印错误码:
AVERROR_EOF
是-541478725
。AVERROR_HTTP_NOT_FOUND
是-875574520
.AVERROR_INVALIDDATA
是-1094995529
FFmpeg 的错误码是 POSIX 错误码的负值。
/* error handling */
#if EDOM > 0
#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions.
#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value.
#else
/* Some platforms have E* and errno already negated. */
#define AVERROR(e) (e)
#define AVUNERROR(e) (e)
#endif
位于libavutil/error.h
中。将错误码转换成文字描述信息。
函数原型:
int av_strerror(int errnum, char *errbuf, size_t errbuf_size);
函数参数:errnum
是错误码,errbuf
是错误信息,errbuf_size
是错误信息的长度。
函数返回值:成功返回 0;失败返回负值。
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
{
int ret = 0, i;
const struct error_entry *entry = NULL;
for (i = 0; i < FF_ARRAY_ELEMS(error_entries); i++) {
if (errnum == error_entries[i].num) {
entry = &error_entries[i];
break;
}
}
if (entry) {
av_strlcpy(errbuf, entry->str, errbuf_size);
} else {
#if HAVE_STRERROR_R
ret = AVERROR(strerror_r(AVUNERROR(errnum), errbuf, errbuf_size));
#else
ret = -1;
#endif
if (ret < 0)
snprintf(errbuf, errbuf_size, "Error number %d occurred", errnum);
}
return ret;
}
FF_ARRAY_ELEMS
宏用于求数组中元素个数。函数通过依次比较 errnum 和 error_entries 中每个 error_entry 的 num 字段,如果匹配,则获取错误信息, error_entry结构如下。
struct error_entry {
int num;
const char *tag;
const char *str;
};
error_entries 在 error.c 中,定义为一个静态全局变量。ERROR_TAG
宏通过拼接AVERROR_
和 tag 名,构成错误码的宏,比如上面的AVERROR_HTTP_NOT_FOUND
。
#define ERROR_TAG(tag) AVERROR_##tag, #tag
#define EERROR_TAG(tag) AVERROR(tag), #tag
#define AVERROR_INPUT_AND_OUTPUT_CHANGED (AVERROR_INPUT_CHANGED | AVERROR_OUTPUT_CHANGED)
static const struct error_entry error_entries[] = {
{ ERROR_TAG(BSF_NOT_FOUND), "Bitstream filter not found" },
{ ERROR_TAG(BUG), "Internal bug, should not have happened" },
{ ERROR_TAG(BUG2), "Internal bug, should not have happened" },
...
};
av_err2str
也可以获得错误字符串,本身是一个宏,通过调用av_make_error_string
,再调用 av_strerror
函数,函数参数是错误码,函数返回值是 err_buf
/**
* Fill the provided buffer with a string containing an error string
* corresponding to the AVERROR code errnum.
*
* @param errbuf a buffer
* @param errbuf_size size in bytes of errbuf
* @param errnum error code to describe
* @return the buffer in input, filled with the error description
* @see av_strerror()
*/
static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum)
{
av_strerror(errnum, errbuf, errbuf_size);
return errbuf;
}
/**
* Convenience macro, the return value should be used only directly in
* function arguments but never stand-alone.
*/
#define av_err2str(errnum) \
av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum)
在 libavutil/common.h
中,FFmpeg 的错误码通过以下宏生成:
#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d))
#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24))
宏 MKTAG 将 4 个 char 字符通过位移,组成一个 int型的正整数(4字节,32位),FFERRTAG宏再对其结果取负数。MKTAG对字符d做(unsigned)
转换,由于ASCII码占用一个字节里的后7位,最前面的一位统一规定为 0,这样只要宏 MKTAG 的最后一个参数是 ASCII 码,就能保证转换后的数字是一个整数。如果需要大端排列,使用MKBETAG。
FFmpeg 错误码列表如:error.h
将十进制的错误码转换为十六进制,然后对照 ASCII 码看下错误码(如果使用Mac电脑,可以直接用计算器):
例如,-875574520
十六进制表示为-0x343034F8
。0x34 对应 ASCII 码中 52 ,也就是4
,0x30 对应 48 ,也就是0
。【34 30 34】合在一起就是 404。
再比如,-1094995529
,十六进制表示为 -0x41444E49
,在 ACSII 中,0x41 对应 'A'、0x44 对应 'D'、0x4E 对应 'N , 0x49 对应 'I'。是 AVERROR_INVALIDDATA 定义的 FFERRTAG('I','N','D','A')
。