在ffmpeg编译阶段没有报错,但在程序中链接生成的静态库,却报出以下错误
1>libavutil.a(log.o) : error LNK2019: unresolved external symbol ___iob_func referenced in function _av_log_default_callback
1>libavutil.a(snprintf.o) : error LNK2019: unresolved external symbol _vacopy referenced in function _avpriv_vsnprintf
1>libavutil.a(bprint.o) : error LNK2001: unresolved external symbol _vacopy
对于第一个错误,期原因是:在av_log_default_callback函数中使用了stderr,作为错误信息的输对象;但自VS2015后,VC系统对stderr等句柄作了重新定义:
#define stdin (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))
而在vs2015之前的定义是:
#define stdin (&__iob_func()[0])
#define stdout (&__iob_func()[1])
#define stderr (&__iob_func()[2])
ffmpeg中貌似还是沿用vs2015之前的方案,因此只要用"__acrt_iob_func(2)"替换掉log.c文件中的所有"stderr",这个问题就不会出现。
这个问题网络上也有其它的解决方法,但我试过之后貌似都不起作用。
第二和第三错误是同一个问题,找到VS中对vacopy函数的定义,在调用该函数的地方给它一个定义,就能蒙混过关。
文件snprintf.c
// snprintf.c 文件
// 新增加的自定义函数
void vacopy(va_list *pap, va_list ap)
{
*pap = ap;
}
int avpriv_vsnprintf(char *s, size_t n, const char *fmt,
va_list ap)
{
int ret;
va_list ap_copy;
if (n == 0)
return _vscprintf(fmt, ap);
else if (n > INT_MAX)
return AVERROR(EOVERFLOW);
/* we use n - 1 here because if the buffer is not big enough, the MS
* runtime libraries don't add a terminating zero at the end. MSDN
* recommends to provide _snprintf/_vsnprintf() a buffer size that
* is one less than the actual buffer, and zero it before calling
* _snprintf/_vsnprintf() to workaround this problem.
* See http://msdn.microsoft.com/en-us/library/1kt27hek(v=vs.80).aspx */
memset(s, 0, n);
vacopy(ap_copy, ap);
ret = _vsnprintf(s, n - 1, fmt, ap_copy);
va_end(ap_copy);
if (ret == -1)
ret = _vscprintf(fmt, ap);
return ret;
}
文件bprintf.c
// bprint.c 文件
// 新增加的自定义函数,为避免和前面的加的函数冲突,改名为_vacopy
void _vacopy(va_list *pap, va_list ap)
{
*pap = ap;
}
void av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg)
{
unsigned room;
char *dst;
int extra_len;
va_list vl;
while (1) {
room = av_bprint_room(buf);
dst = room ? buf->str + buf->len : NULL;
_vacopy(vl, vl_arg); // 这里作了修改
extra_len = vsnprintf(dst, room, fmt, vl);
va_end(vl);
if (extra_len <= 0)
return;
if (extra_len < room)
break;
if (av_bprint_alloc(buf, extra_len))
break;
}
av_bprint_grow(buf, extra_len);
}
修改完成后,保存文件,重新静态编译ffmpeg,新编译的库即可正常链接。