V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
JusticeLanding
V2EX  ›  FFmpeg

FFmpeg 解码器如何识别码流格式变了?

  •  
  •   JusticeLanding · 2022-11-02 15:03:07 +08:00 · 2583 次点击
    这是一个创建于 781 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前,小弟在做基于 ffplay 的播放器,目前碰到个问题。

    有这么个场景,服务端那边跟播放器一个 ts 链接里,有可能碰到 264 数据后面直接紧跟着 265 的数据。

    而播放器不知道码流切换了,264 的 AVCodec 碰到 265 的数据,当然就报错,导致播放器卡住。

    现在在想,如何不修改服务端的情况,264 解码器识别出切 265 了,还有 265 解码器识别出切 264 了。

    尝试在 libavcodec 里的 h2645_parse.c 里把错误识别,抛出去,但是可能小弟对 ffmepg 还不够熟悉,有些正常解码 264 的情况也会有解码失败的报错。

    所以,有大神能指导下吗?想要直接去拦截比特数据,找起始码 0001 ,识别 264 、265 ,但是这好像要 ffmpeg 很底层,稍上层拿到的都是 pkt ,frame 。这也太难了

    17 条回复    2022-11-04 09:35:30 +08:00
    noErr
        1
    noErr  
       2022-11-02 15:53:13 +08:00
    如果生产端上没有给不同的 ts , 那就只能这样处理,二进制是少不了了。
    JusticeLanding
        2
    JusticeLanding  
    OP
       2022-11-02 16:16:29 +08:00
    @noErr 二进制好底层,我抛个解码错误,都改半天,往上抛了好几层才到 av_read_frame ,感觉打断了好几个解码流程,最后也没改好。

    二进制那得更底层,底层自己也不怎么会,网络上数据包过来,ffmpeg 在哪重新组装的都还没找到。

    现在,生产端说在用 h264 的格式编造一个 sei ,在这个 sei 里告诉我格式变了,可是我好像没能在 av_read_frame 里拿到最后这个他编造的 sei 帧。理论上应该是可行的吧,编造一个跟前面格式一样的 sei ,告诉我当前格式播完了。
    ysc3839
        3
    ysc3839  
       2022-11-02 16:31:22 +08:00
    “264 数据后面直接紧跟着 265 的数据”具体是什么情况?发个示例数据来看看?

    另外不推荐用 ffplay 做播放器,硬解渲染啥的仅仅是个能用的状态,推荐用 mpv 。
    JusticeLanding
        4
    JusticeLanding  
    OP
       2022-11-02 17:01:13 +08:00
    @ysc3839 生产端的设备根据协议,只用一个 ts 链接。没有重开 ts 链接的流程,当前协议下,264 帧数据发完,会继续发 265 数据。
    ysc3839
        5
    ysc3839  
       2022-11-02 17:08:45 +08:00
    @JusticeLanding 你这说了跟没说一样,还是需要示例数据
    lhr_lovehoney
        6
    lhr_lovehoney  
       2022-11-02 18:01:32 +08:00
    数据做队列个先判断 SEI ?再丢进 ffmpeg
    MrKrabs
        7
    MrKrabs  
       2022-11-02 18:20:47 +08:00
    那只能自己先解析一下数据了呗
    psyche08
        8
    psyche08  
       2022-11-02 18:52:01 +08:00
    sei 的处理在 h264_sei.c 里,简单粗暴的方法在 read_thread 放个变量,ff_h264_sei_decode 里面改一下
    yangxin0
        9
    yangxin0  
       2022-11-02 19:07:28 +08:00
    按道理来说从 ts 里面解析出来的单路流都是同一个 codec ,我在想你是说的 HLS 协议吧,这个里面 m3u8 里面有一系列的 ts 文件,解析不同 ts 里面的流用不同的 codec 。不晓得我理解对不对。
    Huelse
        10
    Huelse  
       2022-11-02 20:07:01 +08:00
    像楼上说的用 hls 然后依赖播放器自己解析似乎可以,或者我以前想的一个人方法就是 map 来分流,像输出多分辨率那样
    iamzuoxinyu
        11
    iamzuoxinyu  
       2022-11-02 23:03:55 +08:00
    不至于修改 ffmpeg 代码的,可以在外部手动分析出 packet 的 codec id 。
    zhttp
        12
    zhttp  
       2022-11-03 10:27:06 +08:00
    感觉最好的方法还是自己解网络包,解出来 h264/h265 码流判断类型然后用对应的解码器。
    JusticeLanding
        13
    JusticeLanding  
    OP
       2022-11-03 19:05:47 +08:00
    @ysc3839 多谢回复。

    示例数据如下: https://www.upload.ee/files/14636322/264_265mixed.ts.html

    一段 264 、265 连着的 ts ,其中 sei 中加了 end_flag 用来表示 264 结束了,还在尝试 read_frame 捕获到这个 sei 。
    JusticeLanding
        14
    JusticeLanding  
    OP
       2022-11-03 19:07:21 +08:00
    @lhr_lovehoney 没有先做 sei 队列,整个都是 ffmpeg 接管的,拿 ts 的 url 用 avformat_open ,去打开这个 url 。数据靠 ffmpeg 的 http.c 组装拼接而来。
    JusticeLanding
        15
    JusticeLanding  
    OP
       2022-11-03 19:08:46 +08:00
    @psyche08 这办法狠,那得埋个指针到 ffmpeg 里面去,h264_sei.c 和 h265_sei.c 里面能修改。
    ysc3839
        16
    ysc3839  
       2022-11-03 19:41:56 +08:00   ❤️ 1
    @JusticeLanding 用 Wireshark 看了下,第 82572 个包处重新出现了 PAT ,估计是 H265 流的开始,可以从这做切分。
    82572 4.604567015 MPEG TS 188 Program Association Table (PAT)
    82573 4.604622780 MPEG TS 188 Program Map Table (PMT)

    我不太熟悉 FFmpeg ,不知道能否只 demux ts 拿到 H264 H265 流。

    让我来写的话我会用 GStreamer 的 tsdemux 插件解出 H264 H265 流,然后传给 mpv 播放。
    https://gstreamer.freedesktop.org/documentation/mpegtsdemux/tsdemux.html
    https://mpv.io/manual/master/#embedding-into-other-programs-libmpv

    选 GStreamer 是因为它可以直接用字符串描述处理管道,可以省很多代码,自己程序这里基本就只需要对接一下 appsink 来接收数据,包括数据输入都可以直接用字符串描述,不需要写代码。
    播放选 mpv 是因为硬解以及渲染部分很完善,ffplay 的硬解和渲染部分太简陋了。
    JusticeLanding
        17
    JusticeLanding  
    OP
       2022-11-04 09:35:30 +08:00
    @ysc3839 谢谢大佬的分析,目前 sei 里的 end_flag 的 1 解析到了,试着靠这个把播放器停掉。后面用 GS 自己再搞搞看。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   890 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:40 · PVG 04:40 · LAX 12:40 · JFK 15:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.