VLC调试:增加messages.c日志函数,在无vlc_object_t下打印日志

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 在调测VLC源码时经常需要借助日志打印其中核心变量、临时变量的值,方便学习和定位问题,但是遇到像src\input\clock.c中的函数,因缺少vlc_object_t *obj对象,无法打印日志。
在调测VLC源码时经常需要借助日志打印其中核心变量、临时变量的值,方便学习和定位问题,但是遇到像src\input\clock.c中的函数,因缺少vlc_object_t *obj对象,无法打印日志。一般可以通过增加函数参数,从调用方传入,本文提供更简单的方法,可以将以下源码加入到工程里即可使用。
本文基于vlc-2.2.1.32-2013工程修改,源码目录https://github.com/sunqueen/vlc-2.2.1.32-2013。

修改源码:

1、在include\vlc_messages.h函数中增加代码

// add by yagerfgcs:增加msg_Output打印方式
VLC_API void vlc_Debug(vlc_object_t *, int,
                       const char *, const char *, ...) VLC_FORMAT( 4, 5 );
VLC_API void vlc_vaDebug(vlc_object_t *, int,
                         const char *, const char *, va_list);

#define msg_Output(p_this,...) \
    vlc_Debug(VLC_OBJECT(p_this), VLC_MSG_DBG,  MODULE_STRING, __VA_ARGS__ )
// end

2、在src\misc\messages.c中增加代码
a、定义静态变量,存放vlc_object_t对象

// add by yagerfgcs
static libvlc_priv_t *s_priv = NULL;
// end 

b、在vlc_LogSet被调用时,更新s_priv值

void vlc_LogSet (libvlc_int_t *vlc, vlc_log_cb cb, void *opaque)
{
    libvlc_priv_t *priv = libvlc_priv (vlc);

    if (cb == NULL)
    {
#ifdef __ANDROID__
        cb = AndroidPrintMsg;
#else
#if defined (HAVE_ISATTY) && !defined (_WIN32)
        if (isatty (STDERR_FILENO) && var_InheritBool (vlc, "color"))
            cb = PrintColorMsg;
        else
#endif
            cb = PrintMsg;
#endif // __ANDROID__
        opaque = (void *)(intptr_t)priv->log.verbose;
    }

    vlc_rwlock_wrlock (&priv->log.lock);
    priv->log.cb = cb;
    priv->log.opaque = opaque;
    vlc_rwlock_unlock (&priv->log.lock);

    // add by yagerfgcs for:增加在无vlc_object_t对象的情况下也能调用msg_Output打印debug调试日志
    s_priv = priv;
    // end

    /* Announce who we are */
    msg_Dbg (vlc, "VLC media player - %s", VERSION_MESSAGE);
    msg_Dbg (vlc, "%s", COPYRIGHT_MESSAGE);
    msg_Dbg (vlc, "revision %s", psz_vlc_changeset);
    msg_Dbg (vlc, "configured with %s", CONFIGURE_LINE);
}

c、在vlc_LogDeinit中清理s_priv

void vlc_LogDeinit (libvlc_int_t *vlc)
{
    libvlc_priv_t *priv = libvlc_priv (vlc);

    vlc_rwlock_destroy (&priv->log.lock);

    // add by yagerfgcs
    s_priv = NULL;
    // end
}

d、在messages.c文件末尾粘贴以下代码

// add by yagerfgcs:增加在无vlc_object_t对象的情况下也能调用msg_Output打印debug调试日志
void vlc_Debug(vlc_object_t *obj, int type, const char *module,
    const char *format, ...)
{
    va_list args;

    va_start(args, format);
    vlc_vaDebug(obj, type, module, format, args);
    va_end(args);
}

#ifdef _WIN32
static void Win32DebugOutputMsgnoObj(int, const vlc_log_t *,
    const char *, va_list);
#endif

/**
* Emit a log message. This function is the variable argument list equivalent
* to vlc_Log().
*/
void vlc_vaDebug(vlc_object_t *obj, int type, const char *module,
    const char *format, va_list args)
{
    /*if (obj != NULL && obj->i_flags & OBJECT_FLAGS_QUIET)
        return;*/

    /* Get basename from the module filename */
    char *p = strrchr(module, '/');
    if (p != NULL)
        module = p;
    p = strchr(module, '.');

    size_t modlen = (p != NULL) ? (p - module) : 1;
    //    char modulebuf[modlen + 1];
    char *modulebuf = (char *)malloc(modlen + 1);           // sunqueen modify
    if (p != NULL)
    {
        memcpy(modulebuf, module, modlen);
        modulebuf[modlen] = '\0';
        module = modulebuf;
    }

    /* Fill message information fields */
    vlc_log_t msg;

    msg.i_object_id = (uintptr_t)obj;
    msg.psz_object_type = "generic";
    msg.psz_module = module;
    msg.psz_header = NULL;

    for (vlc_object_t *o = obj; o != NULL; o = o->p_parent)
        if (o->psz_header != NULL)
        {
            msg.psz_header = o->psz_header;
            break;
        }

    /* Pass message to the callback */
    // libvlc_priv_t *priv = obj ? libvlc_priv(obj->p_libvlc) : NULL;

#ifdef _WIN32
    va_list ap;

    va_copy(ap, args);
    Win32DebugOutputMsgnoObj(type, &msg, format, ap);
    va_end(ap);
#endif

    if (s_priv) 
    {
        vlc_rwlock_rdlock(&s_priv->log.lock);
        s_priv->log.cb(s_priv->log.opaque, type, &msg, format, args);
        vlc_rwlock_unlock(&s_priv->log.lock);
    }
    free(modulebuf);
}

#ifdef _WIN32
static void Win32DebugOutputMsgnoObj(int type, const vlc_log_t *p_item,
    const char *format, va_list dol)
{
    VLC_UNUSED(p_item);

    va_list dol2;
    va_copy(dol2, dol);
    int msg_len = vsnprintf(NULL, 0, format, dol2);
    va_end(dol2);

    if (msg_len <= 0)
        return;

    char *msg = malloc(msg_len + 1 + 1);
    if (!msg)
        return;

    msg_len = vsnprintf(msg, msg_len + 1, format, dol);
    if (msg_len > 0){
        if (msg[msg_len - 1] != '\n'){
            msg[msg_len] = '\n';
            msg[msg_len + 1] = '\0';
        }
        char* psz_msg = NULL;
        if (asprintf(&psz_msg, "%s %s%s: %s", p_item->psz_module,
            p_item->psz_object_type, msg_type[type], msg) > 0) {
            wchar_t* wmsg = ToWide(psz_msg);
            OutputDebugStringW(wmsg);
            free(wmsg);
            free(psz_msg);
        }
    }
    free(msg);
}
#endif
// end by yagerfgcs

3、在需要打印日志的地方调用msg_Output方法即可,以下两种方式都可以。

vlc_object_t *debug = NULL;
msg_Output(debug, "AvgInit average_t{i_value[%llu] i_residue[%d] i_count[%d] i_divider[%d]} i_divider[%d]", p_avg->i_value, p_avg->i_residue, p_avg->i_count, p_avg->i_divider, i_divider);
msg_Output(NULL, "ClockData i_ts_buffering[%llu] i_ts_delay[%llu]", i_ts_buffering, i_ts_delay);

效果:

日志效果

备注:如果是VS2010版本的老VLC源码,可以参考http://blog.csdn.net/c_m_deng/article/details/8209310

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
9天前
|
人工智能 JSON 安全
无需复杂正则:SLS 新脱敏函数让隐私保护更简单高效
SLS 推出 mask 脱敏函数,支持 keyword 和 buildin 模式,简化敏感数据识别与处理,提升脱敏效率与性能,适用于结构化及非结构化日志。
|
2月前
|
JavaScript 前端开发 开发者
讲述Vue框架中用于对象响应式变化的Object.defineProperty函数。
综上所述,Vue.js通过 `Object.defineProperty()`提供了强大的响应式能力,使得状态管理变得简洁高效。这种能力是Vue.js受到广大开发者青睐的重要原因之一。尽管Vue 3.x使用Proxy替代了该方法,但对于Vue 2.x及其之前版本,`Object.defineProperty()`是理解Vue.js内部工作机制不可或缺的一部分。
125 27
|
6月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——使用Logger在项目中打印日志
本文介绍了如何在项目中使用Logger打印日志。通过SLF4J和Logback,可设置不同日志级别(如DEBUG、INFO、WARN、ERROR)并支持占位符输出动态信息。示例代码展示了日志在控制器中的应用,说明了日志配置对问题排查的重要性。附课程源码下载链接供实践参考。
739 0
|
6月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
9月前
|
存储 Prometheus 监控
Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行
本文深入探讨了在Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行。
398 5
|
10月前
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
282 8
|
11月前
|
PyTorch 算法框架/工具
Pytorch学习笔记(七):F.softmax()和F.log_softmax函数详解
本文介绍了PyTorch中的F.softmax()和F.log_softmax()函数的语法、参数和使用示例,解释了它们在进行归一化处理时的作用和区别。
1084 1
Pytorch学习笔记(七):F.softmax()和F.log_softmax函数详解
|
11月前
|
Java 程序员 应用服务中间件
「测试线排查的一些经验-中篇」&& 调试日志实战
「测试线排查的一些经验-中篇」&& 调试日志实战
137 1
「测试线排查的一些经验-中篇」&& 调试日志实战
|
存储 PHP 数据安全/隐私保护
spl_object_hash() 函数
spl_object_hash() 函数
|
存储 关系型数据库 MySQL

热门文章

最新文章