文章

MiguDelay 架构 11:收流、探测、解复用与解码

MiguDelay(DDLive)项目架构系列文档:收流、探测、解复用与解码。内容基于 2026-08-04 对指定重构分支的源码扫描结果整理。

MiguDelay 架构 11:收流、探测、解复用与解码

系列导航系列总览 · 上一篇:MiguDelay 架构 10:Gateway 与 TaskHandle 兼容边界 · 下一篇:MiguDelay 架构 12:Output 实时延时与时钟

扫描基线

  • 项目:MiguDelay(DDLive)
  • 分支:refactor/video-frame-provider
  • HEAD:d28ec061406e4e3df93e3d1a92478d71a9ad4908
  • 工作树:clean
  • 扫描日期:2026-08-04
  • 说明:内容以当前 HEAD 源码为准;仓库旧架构文档只作为检索线索。

1. 职责

收流链把网络 URL 转换为标准音视频帧并推给 Output。新应用层决定启动时机、contextId 和 generation;探测、解复用和解码仍由 legacy 媒体类执行。

2. 核心类

职责
StartRecvTask 创建或复用 context,探测、初始化 Output、注册 callback、启动网络流
NetworkRecvContext 持有 flow、两个 Output、媒体参数和 Delay Reader
RecvNetworkFlowFFmpeg FFmpeg 输入、demux、decode 和 callback
Output 接收实时帧
OutputWithLocalFileReader 接收长延时文件链音频/视频
StopRecvTask take context 并唯一停止资源

3. StartRecvTask 调用链

sequenceDiagram
    participant T as StartRecvTask
    participant H as TaskHandle
    participant C as NetworkRecvContext
    participant R as RecvNetworkFlowFFmpeg
    participant O as Output
    participant F as FileOutput

    T->>H: getRecvContext
    alt context missing
        T->>C: create context
    else context exists
        T->>R: stop old stream
        T->>O: uninit old output
        T->>F: uninit old file output
    end
    T->>R: detectStreamParams
    R-->>T: video and audio parameters
    T->>O: init OutputInitInfo
    T->>F: init OutputInitInfo
    T->>R: register frame callbacks
    T->>R: startStream
    T->>H: setRecvContext

4. generation 防护点

StartRecvInfo 携带 startGeneration 和共享 currentGeneration 原子 token。Task 在以下位置重新检查:

  1. 接触 context 前。
  2. getRecvContext() 后。
  3. 探测失败后。
  4. 探测成功后。
  5. startStream() 失败后。
  6. 写入 context map 前。

旧任务因此不能覆盖新 context,也不能将旧失败上报为当前失败。

5. 探测校验

  • 至少一个音轨。
  • 每轨 sample rate 和 channel 有效。
  • 多音轨在 sample rate、channel、out channel、sample format、codec、type 上一致。
  • 视频参数写入 VideoEncoderParams
  • 音频参数写入 vector<AudioEncoderParams>

6. OutputInitInfo

包括 width、height、frame-rate rational、audio-track count、sample rate、long-time-delay、only-live。

7. callback 数据流

1
2
3
4
5
6
7
8
RecvNetworkFlowFFmpeg
  -> NetVideoFrameProcessed
       -> Output.addVideoAVFrameInfo
  -> NetAudioFrameProcessed
       -> Output.addAudioAVFrameInfo
       -> OutputWithLocalFileReader.addAudioAVFrameInfo
  -> SourceDisconnected or SourceReconnected
       -> Output.clearFirstCache
flowchart LR
    URL["Network URL"] --> DEMUX["FFmpeg demux"]
    DEMUX --> VP["Video packets"]
    DEMUX --> AP["Audio packets"]
    VP --> VD["Video decoder"]
    AP --> AD["Audio decoder"]
    VD --> VF["MyVideoFrame"]
    AD --> AF["MyAudioFrame"]
    VF --> OUT["Output"]
    AF --> OUT
    AF --> FOUT["OutputWithLocalFileReader"]

8. 停止

StopRecvTask 使用 takeRecvContext(contextId) 获取唯一资源所有权,然后停止 flow、uninit 两个 Output、uninit Delay Readers 并释放 context。不存在 context 可按幂等完成处理。

9. 源码证据

  • src/code/module/taskhandle/recvstream/StartRecvTask.cpp
  • src/code/module/taskhandle/recvstream/StopRecvTask.cpp
  • src/code/module/demuxer/recvnetworkflow/recvNetworkFlowFFmpeg.*
  • src/code/module/decoder/**
  • src/code/module/taskhandle/TaskHandle.h

系列导航系列总览 · 上一篇:MiguDelay 架构 10:Gateway 与 TaskHandle 兼容边界 · 下一篇:MiguDelay 架构 12:Output 实时延时与时钟

本文由作者按照 CC BY 4.0 进行授权