美文网首页
从AVPlayer的AVPeriodicTimebaseObse

从AVPlayer的AVPeriodicTimebaseObse

作者: 双鱼子曰1987 | 来源:发表于2020-12-03 11:13 被阅读0次

一、崩溃包裹

分析Bugly奔溃日志,发现以下一个错误:
*** -[AVPeriodicTimebaseObserver initWithTimebase:interval:queue:block:] invalid parameter not satisfying: ((Boolean)(CMTimeCompare(interval, kCMTimeZero) > 0))

错误堆栈如下:

CoreFoundation  ___exceptionPreprocess + 216
1 libobjc.A.dylib   objc_exception_throw + 56
2 AVFCore   ___68-[AVPeriodicTimebaseObserver initWithTimebase:interval:queue:block:]_block_invoke
3 AVFCore   -[AVPlayer addPeriodicTimeObserverForInterval:queue:usingBlock:] + 132
...

由上可知,错误是在监听AVPlayer 播放进度 addPeriodicTimeObserverForInterval:queue:usingBlock: 的时候,非法入参引起的。

二、AVPlayer 播放进度的监听

iOS播放视频常常使用系统的AVPlayer类,视频的进度是通过注册监听获得的。方法如下- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
该方法需要指定一个queue,然后在时间间隔interval内通过block回调回来。

  • 注意:必须使用- (void)removeTimeObserver:(id)observer; 移除监听。
    不移除并不会倒是crash,但是这个queue的线程是不会释放的,会占用你大量的内存资源。如果很多AVPlayer都没有得到移除的话,结果是灾难性的。

    苹果的官方文档标注如下:
    An object conforming to the NSObject protocol. You must retain this returned value as long as you want the time observer to be invoked by the player.Pass this object to -removeTimeObserver: to cancel time observation.

  • CMTime. timescale <= 0 的时候,就会引起上面的崩溃。

三、说说CMTime

3.1、CMTime的基本概念
  • 打印一个CMTime变量如下
po CMTimeMakeWithSeconds(60, 600);

(CMTime) time = 36000 600ths of a second {
  value = 36000  60*600
  timescale = 600
  flags = kCMTimeFlags_Valid
  epoch = 0
}
  • iOS系统中,将CMTime被定义为一个结构体如下,表示
typedef struct
{
    CMTimeValue value;
    CMTimeScale timescale;
    CMTimeFlags flags; //flags 为一个位枚举
    CMTimeEpoch epoch;
} CMTime;

typedef int64_t CMTimeValue;
typedef int32_t CMTimeScale;
typedef int64_t CMTimeEpoch;

我们一般关心 valuetimescale 的赋值。

  • CMTime被用来表示时间与帧数之间的关系,关系为 value/timescale = seconds

3.2、CMTime常用操作方法

  • 通过宏CMTIME_IS_VALID 判断CMTime是否有效值,宏定义如下:
    #define CMTIME_IS_VALID(time) ((Boolean)(((time).flags & kCMTimeFlags_Valid) != 0))

  • 创建CMTime变量,一般通过以下两个方法
    CMTime CMTimeMake(int64_t value, int32_t timescale)
    其中,value当前第几帧,timescale每秒多少帧。当前播放时间:seconds =value/timescale

    CMTime CMTimeMakeWithSeconds(Float64 seconds, int32_t preferredTimescale)
    seconds当前时间,preferredTimescale每秒多少帧。此时Value = seconds * preferredTimescale
    文档指出,当preferredTimescale is <= 0,CMTime是一个非法的值,会导致crash,错误如上。

  • 表示零秒kCMTimeZero,其对应的结构体如下

(CMTime) time1 = 0 seconds {
  value = 0
  timescale = 1
  flags = kCMTimeFlags_Valid
  epoch = 0
}
  • 将CMTime转化为秒,方法如下
    Float64 CMTimeGetSeconds(CMTime time)

  • 比较两个CMTime的大小,方法如下
    int32_t CMTimeCompare(CMTime time1, CMTime time2)
    time1 < time2,-1;time1 > time2,1;time1 == time2,0

    CMTime CMTimeMinimum(CMTime time1,CMTime time2)
    返回 time1 与 time2 中较小的值

    CMTime CMTimeMaximum(CMTime time1,CMTime time2)
    返回 time1 与 time2 中较大的值

  • CMTime CMTimeAbsoluteValue(CMTime time)
    返回 time 的绝对值


其他

视频合成中CMTime的理解,以及利用CMTime实现过渡效果
CGTime CMTimeRange CMTimeMapping 小结

相关文章

网友评论

      本文标题:从AVPlayer的AVPeriodicTimebaseObse

      本文链接:https://www.haomeiwen.com/subject/jgfmwktx.html