VLC 模块构造宏的展开(access_output_http为例)

VLC模块宏定义解析
本文详细解析了VLC播放器中模块宏定义vlc_module_begin()和vlc_module_end()的具体展开过程,展示了如何通过宏定义设置模块描述、能力、快捷方式、配置项及回调函数,为理解VLC源代码提供了深入的视角。

宏的定义:

vlc_module_begin ()
    set_description( N_("HTTP stream output") )
    set_capability( "sout access", 0 )
    set_shortname( "HTTP" )
    add_shortcut( "http", "https", "mmsh" )
    set_category( CAT_SOUT )
    set_subcategory( SUBCAT_SOUT_ACO )
    add_string( SOUT_CFG_PREFIX "user", "",
                USER_TEXT, USER_LONGTEXT, true )
    add_password( SOUT_CFG_PREFIX "pwd", "",
                  PASS_TEXT, PASS_LONGTEXT, true )
    add_string( SOUT_CFG_PREFIX "mime", "",
                MIME_TEXT, MIME_LONGTEXT, true )
    add_bool( SOUT_CFG_PREFIX "metacube", false,
              METACUBE_TEXT, METACUBE_LONGTEXT, true )
    set_callbacks( Open, Close )
vlc_module_end ()

宏展开后:展开方式,VS中属性-〉C/C++/预处理器:预处理到文件 选择 是 编译后在相应的工程文件目录下有*.i文件,从中可取出以下宏的展开部分。例子里是VLC2.2.6

plugins/access_output/access_output_http.c
__declspec(dllexport) int __cdecl vlc_entry__2_2_0b (vs_cb vs, void *op) {
    module_t *module;     module_cf_t *cf = ((void *)0);
    if (vs (op, ((void *)0), VLC_MODULE_CREATE, &module)) goto error;
    if (vs (op, module, VLC_MODULE_NAME, ("access_output_http"))) goto error;
    if (vs (op, module, VLC_MODULE_DESCRIPTION, (("HTTP stream output")))) goto error;
    if (vs (op, module, VLC_MODULE_CAPABILITY, ("sout access")) || vs (op, module, VLC_MODULE_SCORE, (int)(0))) goto error;
    if (vs (op, module, VLC_MODULE_SHORTNAME, ("HTTP"))) goto error;
    const char *shortcuts[] = { "http", "https", "mmsh" };
    if (vs (op, module, VLC_MODULE_SHORTCUT, sizeof(shortcuts)/sizeof(shortcuts[0]), shortcuts)) goto error;
    vs (op, ((void *)0), VLC_CONFIG_CREATE, (0x06) CONFIG_CATEGORY, &cf);
    vs (op, cf, VLC_CONFIG_VALUE, (int64_t)(5) CAT_SOUT);
    vs (op, ((void *)0), VLC_CONFIG_CREATE, (0x07) CONFIG_SUBCATEGORY, &cf);
    vs (op, cf, VLC_CONFIG_VALUE, (int64_t)(504) SUBCAT_SOUT_ACO);

    vs (op, ((void *)0), VLC_CONFIG_CREATE, (0x80) CONFIG_ITEM_STRING, &cf);
    vs (op, cf, VLC_CONFIG_DESC, (("Username")), (("User name memo.")));if (1) vs (op, cf, VLC_CONFIG_ADVANCED);
    vs (op, cf, VLC_CONFIG_NAME, ("sout-http-user"));vs (op, cf, VLC_CONFIG_VALUE, (""));

    vs (op, ((void *)0), VLC_CONFIG_CREATE, (0x81) CONFIG_ITEM_PASSWORD, &cf);
    vs (op, cf, VLC_CONFIG_DESC, (("Password")), (("Password memo.")));if (1) vs (op, cf, VLC_CONFIG_ADVANCED);
    vs (op, cf, VLC_CONFIG_NAME, ("sout-http-pwd"));vs (op, cf, VLC_CONFIG_VALUE, (""));

    vs (op, ((void *)0), VLC_CONFIG_CREATE, (0x80) CONFIG_ITEM_STRING, &cf);
    vs (op, cf, VLC_CONFIG_DESC, (("Mime")), (("MIME memo.")));if (1) vs (op, cf, VLC_CONFIG_ADVANCED);
    vs (op, cf, VLC_CONFIG_NAME, ("sout-http-mime"));vs (op, cf, VLC_CONFIG_VALUE, (""));

    vs (op, ((void *)0), VLC_CONFIG_CREATE, (0x60) CONFIG_ITEM_BOOL, &cf);
    vs (op, cf, VLC_CONFIG_DESC, (("Metacube")), (("Metacube memo.")));if (1) vs (op, cf, VLC_CONFIG_ADVANCED);
    vs (op, cf, VLC_CONFIG_NAME, ("sout-http-metacube"));if (0) vs (op, cf, VLC_CONFIG_VALUE, (int64_t)1);

    if (vs (op, module, VLC_MODULE_CB_OPEN, Open) || vs (op, module, VLC_MODULE_CB_CLOSE, Close)) goto error;
    return 0;
error: return -1;
}

# ===== 中间插入代码(可直接执行,无需定义变量或 main) ===== import os, time, subprocess, shutil # ---------- 配置区 ---------- iface_name = "以太网" # 要禁用/启用的网卡名(Windows 显示名) ipc_ip = "192.168.0.60" # IPC 的 IP(不要加 http:// 或中括号) multicast_path = "/multicastStream1" # RTSP 路径 rtsp_port = "554" # RTSP 端口 vlc_exe = r"D:\UserData\Documents\VLC\vlc.exe" # VLC 路径 play_seconds = 5 # 播放时长(秒) # -------------------------------- _success_keys = [ "stream buffering done", "started playback", "playing", "play started", "live555 debug: play", "decoder debug:", "stream opened successfully", "opening stream" ] rtsp_result = {"url": None, "played": False, "errors": []} if os.name != "nt": print("⚠️ 当前非 Windows 系统,跳过执行。") else: # 拼接 URL ip = ipc_ip.strip("[]/") if not multicast_path.startswith("/"): multicast_path = "/" + multicast_path url = f"rtsp://{ip}:{rtsp_port}{multicast_path}" rtsp_result["url"] = url print(f"🎯 RTSP URL: {url}") # 检查 VLC vlc_bin = vlc_exe if os.path.isfile(vlc_exe) else shutil.which("vlc") if not vlc_bin: print("❌ 未找到 VLC 可执行文件,请检查路径。") else: # 1️⃣ 禁用网卡 disable_cmd = ["netsh", "interface", "set", "interface", iface_name, "disable"] print(f"🔧 禁用网卡: {' '.join(disable_cmd)}") subprocess.run(disable_cmd, text=True, capture_output=True) time.sleep(1) try: # 2️⃣ 播放 RTSP play_cmd = [ vlc_bin, "--no-one-instance", "--rtsp-tcp", "--network-caching=1500", "-vvv", url, f"--run-time={play_seconds}", "vlc://quit" ] print(f"▶️ 播放 {play_seconds} 秒...") res = subprocess.run( play_cmd, text=True, capture_output=True, encoding="utf-8", errors="ignore" ) log = (res.stdout or "") + (res.stderr or "") hits = [k for k in _success_keys if k in log.lower()] rtsp_result["played"] = bool(hits) if rtsp_result["played"]: print(f"✅ RTSP 播放成功(命中: {hits})") else: print("❌ RTSP 未检测到播放迹象。") finally: # 3️⃣ 启用网卡 enable_cmd = ["netsh", "interface", "set", "interface", iface_name, "enable"] print(f"🔧 恢复网卡: {' '.join(enable_cmd)}") subprocess.run(enable_cmd, text=True, capture_output=True) time.sleep(1) print("📊 RTSP 测试结果:", rtsp_result) # ===== 插入代码结束 =====
最新发布
10-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值