在VS2019环境下静态编辑ffmpeg遇到的问题

在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,新编译的库即可正常链接。

你可能感兴趣的:(FFmpeg)