前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个ExoPlayer原生播放问题引起的思考

一个ExoPlayer原生播放问题引起的思考

作者头像
马上就说
发布2021-04-29 14:56:26
3.2K0
发布2021-04-29 14:56:26
举报
文章被收录于专栏:码上就说码上就说
问题背景

我们在使用ExoPlayer播放视频的视频发现一种特殊的M3U8视频,播放总是失败。 而且报如下的错误:

代码语言:javascript
复制
ExoPlayerImplInternal: Source error.
    com.google.android.exoplayer2.ParserException: Cannot find sync byte. Most likely not a Transport Stream.
        at com.google.android.exoplayer2.extractor.ts.TsExtractor.read(TsExtractor.java:260)
        at com.google.android.exoplayer2.source.hls.e.f(HlsMediaChunk.java:284)
        at com.google.android.exoplayer2.source.hls.e.load(HlsMediaChunk.java:209)
        at com.google.android.exoplayer2.upstream.Loader$a.run(Loader.java:330)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)

这样的报错似乎是ExoPlayer的原生问题,我们赶紧找到ExoPlayer的源码:

https://github.com/google/ExoPlayer/blob/release-v2/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java

原生报错的地方找到了,但是接下来我们还需要解决下面几个问题:

  • TS格式是怎么样的?
  • ExoPlayer为什么要这样修改?
  • 正确的修改方式是什么样的?
TS格式解析

正常的TS Packet是188字节,其层次结果如下:

名称

位数

备注

sync_byte

8b

同步字节,固定为0x47

transport_error_indicator

1b

传输错误指示符,表明在ts头的adapt域后有一个无用字节,通常都为0,这个字节算在adapt域长度内

payload_unit_start_indicator

1b

负载单元起始标示符,一个完整的数据包开始时标记为1

transport_priority

1b

传输优先级,0为低优先级,1为高优先级,通常取0

pid

13b

pid值

transport_scrambling_control

2b

传输加扰控制,00表示未加密

adaptation_field_control

2b

是否包含自适应区,‘00’保留;‘01’为无自适应域,仅含有效负载;‘10’仅含自适应域,无有效负载;‘11’为同时带有自适应域和有效负载。

continuity_counter

4b

递增计数器,从0-f,起始值不一定取0,但必须是连续的

已经规定好了每一个TS Packet大小是188字节,识别TS Packet大小的重要标志是读sync_byte位,两个sync_byte之间相距188字节,说明它是标准的TS格式。

但是,制定的标准,有的遵守标准,有的不一定遵守标准。真的发生的标准不遵守怎么办?

这次ExoPlayer发生播放这样视频失败的原因,就是因为视频源没有遵守TS Packet大小为188字节的规则,这样的错误很尴尬,它违反了标准,但是它前188字节是标准的TS数据。

我们先追踪一下ExoPlayr这段修改的原因。

ExoPlayer这样修改的原因

先放上两个源码修改链接:

https://github.com/google/ExoPlayer/commit/0697fb3955d8a30edb935cc428d515e2fd9d48cb

https://github.com/google/ExoPlayer/issues/3149

从注释来看,google觉得每次加载不一定要等到TS_SYNC_BYTE才算加载成功,但是他们显然又怕当前不是标准的TS流,就加了一个兜底,要是当前读到的位置超过两个188字节还是没有发现TS_SYNC_BYTE,说明当前大概率不是TS流的格式。

这样的判断在标准上而言是没有什么问题的。

我们应该怎么改

我们遇到这样的播放失败,只能采用两种办法了?

  • 向M3U8的提供方提意见,最好修改一下TS内部格式,让其符合标准。
  • 定制化修改ExoPlayer源码,适配这种异常的类型。

第一种难度可能要点高,不太现实,毕竟让服务方给你改东西,人接不太原因。那就只好播放器去适配,播放器将这个校验去掉有没有问题? 从对TS格式分析来看,这样的修改不太完美,但是从播放器的兜底处理来看,这样的处理基本没有风险。因为最坏的结果就是播放失败。已经有兜底方案了,应该没有问题。

制定了标准,总有人不去遵守。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 音视频平凡之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题背景
  • TS格式解析
  • ExoPlayer这样修改的原因
  • 我们应该怎么改
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档