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

在调测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

时间: 2024-10-23 13:53:26

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

Windows下MySQL日志基本的查看以及导入导出用法教程_Mysql

MYSQL有不同类型的日志文件(各自存储了不同类型的日志),从它们当中可以查询到MYSQL里都做了些什么,对于MYSQL的管理工作,这些日志文件是不可缺少的. 1.错误日志(The error log):记录了数据库启动.运行以及停止过程中错误信息: 2.ISAM操作日志(The isam log):记录了所有对ISAM表的修改,该日志仅仅用于调试ISAM模式: 3.SQL执行日志(The query log):记录了客户端的连接以及所执行的SQL语句: 4.更新日志(The update lo

C++软件添加dump调试打印日志(推荐)_C 语言

C++软件添加dump调试打印日志(推荐) #include <DbgHelp.h> #pragma comment(lib, "dbghelp.lib") LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) { //cout << "Enter TopLevelExceptionFilter Function" << en

如何调试C/C++内联函数及过程

这篇文章描述了一种持续的权衡方法,可以在调试程序和使之运行 更快之间取得正确的平衡.这篇文章同时还描述了如何调试内联函数及过程. 编写一个运行得快的程序并不容易.编译器可以帮助将一个程序转换成运行得更加快,但权衡是转换之后的程序与初始的程序会有所不同.在某些作了积极优化转换(aggressive optimization transform)的情形里,从人类的角度看转换后的程序与初始程序相比较已经几乎没有可读的一致性了. 因此,调试有问题的已优化程序会更加困难.这是一个问题,因为为了获得最大化的

回调函数的问题,在安卓下调试找不到回调函数名??

问题描述 回调函数的问题,在安卓下调试找不到回调函数名?? 设置的回调函数都是无参的,按理说如果回调函数没有进去,我的界面切换效果应该也 出不来,但现在界面切换效果出来了,但是场景2就是显示不了,资源文件看了一下asset 目录里都有,按理说应该找的到啊,如果是内存的问题应该也只是延迟显示把,这不懂,求大神指点

Log4j配置详解及不同的包(package)下的日志写入到不同的日志文件下

以下都是log4j.properties要写入的内容: 一:参数介绍: 1.Log4J配置文件的基本格式如下: [plain] view plaincopy #配置根Logger   log4j.rootLogger  =   [ level ]   ,  appenderName1 ,  appenderName2 ,  -      #配置日志信息输出目的地Appender   log4j.appender.appenderName  =  fully.qualified.name.of.a

.NET Core下的日志(1):记录日志信息

记录各种级别的日志是所有应用不可或缺的功能.关于日志记录的实现,我们有太多第三方框架可供选择,比如Log4Net.NLog.Loggr和Serilog 等,当然我们还可以选择微软原生的诊断机制(相关API定义在命名空间"System.Diagnostics"中)实现对日志的记录..NET Core提供了独立的日志模型使我们可以采用统一的API来完成针对日志记录的编程,我们同时也可以利用其扩展点对这个模型进行定制,比如可以将上述这些成熟的日志框架整合到我们的应用中.本系列文章旨在从设计和

log-LINUX下C语言编程怎么打印日志

问题描述 LINUX下C语言编程怎么打印日志 刚刚工作,以前看过别人写的代码调试完后都可以打印日志来查看日志,自己新参加工作,给服务器发包什么的,开始发总是出问题,带我的人就一直和我说你打印个日志出来,然后看日志.但是我不会,只能printf把变量值输出到屏幕上看,也想写的更专业一点,求大神指点.那个日志是怎么做的,是自己写的函数,还是LINUX自带这种功能或函数,要怎么用.希望可以有一小段代码例子.还有日志的存放位置,写一个项目日志要存在同一个工程里吗 解决方案 用log4c等专业打印log的

如何使用线程局部存储实现多线程下的日志系统

概述 通常来说,在应用程序中需要日志来记录程序运行的状态,以便后期问题的跟踪定位.在日志系统的设计中,通常会有一个总的日志系统来统一协调这些日志的设置如位置.输出级别和内容等.在多线程编程中,当每个线程都需要输出日志时,因为要考虑线程间的同步,日志系统的设计更加复杂. 在单线程应用程序中,通常使用一个日志单例向某个文件输出应用运行过程中的重要日志信息,但是在多线程环境中,这样做显然不好,因为各个线程打印出的日志会错综复杂从而使得日志文件不容易阅读和跟踪.比较好的办法是主线程记录自己的日志,各个子

Linux下的日志维护技巧

1.系统日志 /var/log/messages不仅是服务器的系统日志,很多时候它也包括许多服务的日志,所以它被称为"杂货铺",建议重点关注.大家一般都喜欢用以下命令来看最后10条日志:tail -n10/var/log/messages. 其实还可以将一段日志保存成文件(Xmanager3.0企业版的shell也有日志录像截取功能),或者直接用vim来处理.我以前配置主从复制的bind服务器时,有时会因为权限的原因报错,这时就可以在一台报错的服务器上用命令tail -f/var/lo