Objective-C的AVFoundation使用学习笔记

2023-04-09  本文已影响0人  寻心_0a46

AVFoundation

AVFoundation框架结合了几个主要的技术领域,这些领域涵盖了在苹果平台上检查、播放、捕获和处理视听媒体的广泛任务。

AVPlayer - 播放器

AVPlayer(播放器)是一个控制器对象,它管理媒体资产的播放和计时。使用AVPlayer的实例来播放本地和远程基于文件的媒体,例如QuickTime电影和MP3音频文件,以及使用HTTP Live Streaming(基于 HTTP 的自适应比特率流通信协议)服务的视听媒体。

使用AVPlayer(播放器)一次播放单个媒体资源,可以使用其replaceCurrentItemWithPlayerItem:方法重用播放器实例来播放其他媒体资源,但它一次只管理单个媒体资源的播放。该框架还提供了一个名为AVQueuePlayer的类的子类,用于创建和管理按顺序播放的媒体资源的队列。

使用AVPlayer播放媒体资源,AVFoundation使用AVAsset类对其进行建模。AVAsset只对媒体的静态方面建模,例如其持续时间或创建日期,并且就其本身而言,不适合用AVPlayer播放。要播放一个资源,需要在AVPlayerItem中创建一个动态对应的实例,该对象为AVPlayer实例播放的资源的计时和表示状态建模

AVPlayer是一个动态对象,其状态不断变化。观察播放器状态有两种方法:

  1. 一般状态观察:可以使用键值观察(KVO)来观察播放器许多动态属性的状态变化,例如它的currentItem或它的播放速率。

  2. 定时状态观察:KVO适用于一般状态观察,但并不适用于观察持续变化的状态,如播放的时间。AVPlayer提供了两种观察时间变化的方法:
    addPeriodicTimeObserverForInterval:queue:usingBlock:
    addBoundaryTimeObserverForTimes:queue:usingBlock:
    这些方法允许分别周期性地或按边界观察时间的变化。当发生变化时,调用提供给这些方法的回调块或闭包,让你有机会采取一些行动,如更新播放器用户界面的状态。

AVPlayer和AVPlayerItem是非视觉对象,这意味着它们本身无法在屏幕上呈现资源的视频。在屏幕上呈现视频内容有两种主要方法:

  1. AVKit:呈现视频内容的最佳方式是在iOS和tvOS中使用AVKit框架的AVPlayerViewController类,或者在macOS中使用AVPlayerView类。这些类提供视频内容,以及播放控件和其他媒体功能,为您提供全功能的播放体验。

  2. AVPlayerLayer:当为播放器创建自定义界面时,使用AVPlayerLayer。可以将该层设置为视图的后台层,或者直接将其添加到层的层次结构中。与AVPlayerView和AVPlayerViewController不同的是,AVPlayerLayer不呈现任何播放控件,它只呈现屏幕上的视觉内容。需要自定义构建播放传输控件来播放、暂停和查找媒体。

除了使用AVKit或AVPlayerLayer呈现的视觉内容外,还可以使用AVSynchronizedLayer呈现与播放时间同步的动画内容。使用AVSynchronizedLayer将播放计时传递给它的层子树。可以使用AVSynchronizedLayer在核心动画中创建自定义效果,如动画的下三分之一或视频过渡,并让它们与播放器当前AVPlayerItem的时间同步播放。

重要:AVPlayer对象需要强引用

AVPlayer (AVPlayerPlaybackControl) - 播放器播放控制相关

AVPlayer (AVPlayerPlaybackControl)常用函数
- (void)play

函数描述AVPlayer开始播放当前项目。调用此方法与将速率设置为1.0相同。在iOS 16之前,只能在主线程或队列上调用此方法。

- (void)pause

函数描述AVPlayer 暂停播放当前项目。调用此方法与将速率设置为0.0相同。

AVPlayer (AVPlayerItemControl) - 播放器操作播放项相关

AVPlayer (AVPlayerItemControl)常用函数
- (void)replaceCurrentItemWithPlayerItem:(nullable AVPlayerItem *)item;

函数描述用新的播放项替换当前播放项。播放器对播放项的替换会立即发生,并且替换的播放项会成为播放器的当前播放项。只能在AVPlayer的实例上调用这个方法,使用AVPlayer的当前播放项(currentItem)调用此方法没有效果,在AVQueuePlayer的实例上调用它会导致系统抛出异常。

参数 :

item :播放器(AVPlayer)对象要播放的新项目。

AVPlayer (AVPlayerTimeControl) - 播放器时间控制相关

AVPlayer (AVPlayerTimeControl)常用函数
- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL finished))completionHandler API_AVAILABLE(macos(10.7), ios(5.0), tvos(9.0), watchos(1.0));

函数描述请求播放器以时间公差值指定的精度量内将播放跳转到指定时间,并在跳转完成或中断时调用处理程序的completionHandler代码块。所跳转的时间将在【参数time - 参数beforetolerance, 参数time + 参数afterTolerance】的范围内,但为提高效率可能与指定的时间不同。通过为toleranceBefore与toleranceAfter传递一个时间值kCMTimeZero要求进行精确跳转,精确跳转可能会产生额外的解码延迟,这可能会影响跳转性能。

将参数toleranceBefore设置为kCMTimePositiveInfinity,将参数toleranceAfter设置为kCMTimePositiveInfinity,那么调用此方法与调用seekToTime:方法相同。

如果跳转请求完成而没有被另一个跳转请求或任何其他操作中断,则将调用指定的完成处理程序,并将finished参数设置为YES。如果任何先前仍在处理中的跳转请求被中断,将调用指定的完成处理程序,并将finished参数设置为NO。

参数 :

time : 要跳转的时间。

toleranceBefore :要跳转的时间(time)之前允许的公差。

toleranceAfter : 要跳转的时间(time)之后允许的公差。

completionHandler :当跳转操作完成或被中断时要调用的block。block有一个参数finished,用于指示跳转操作是否已完成。

\color{red}{例如:调用播放跳转的代码示例}

[self.player seekToTime:CMTimeMake(floorf(self.totalTime * value), 1)
            toleranceBefore:kCMTimeZero
             toleranceAfter:kCMTimeZero
          completionHandler:^(BOOL finished) {
        if (finished) {
            //播放器播放
            [self hy_play];
            //标记播放进度跳转已结束
            self->_isSeek = NO;
            //执行回调
            if (completionBlock) {
                completionBlock();
            }
        }
    }];

AVPlayer (AVPlayerTimeObservation) - 播放器时间观察相关

AVPlayer (AVPlayerTimeObservation)常用函数
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;

函数描述请求在播放期间定期调用给定的块,以报告更改的时间。只要希望播放器调用时间观察者,就必须保持对返回值的强引用。必须将此方法的每个调用与对应的removeTimeObserver:的调用相匹配,释放观察者对象而不调用removeTimeObserver:函数将导致未定义的行为

系统按照指定的时间间隔周期性地调用块,根据当前播放项的时间轴进行解释。每当时间跳跃或播放开始或停止时,它也会调用块。如果间隔对应的实时间隔非常短,播放器调用块的频率可能比应用程序请求的要低。即便如此,播放器仍然会频繁地调用区块,以便客户端在其终端用户界面中适当地更新当前时间的指示。

重要提示:在回调块中使用弱引用self以防止创建保留循环。

参数 :

interval :根据播放器当前时间的进度,系统在正常播放期间调用块的时间间隔。

queue : 系统调用块的调度队列。不支持传递并发队列,会导致未定义的行为。
如果传递NULL,系统将使用主队列。

block :系统周期性调用的块,该块采用单个参数,为系统调用块的时间。

返回值 : 一个不透明对象,可以作为参数传递给removeTimeObserver:取消观察。

\color{red}{下面的示例说明了如何在正常播放期间设置系统每半秒调用一次回调:}

- (void)addPeriodicTimeObserver {
    //每半秒调用一次回调
    CMTime interval = CMTimeMakeWithSeconds(0.5, NSEC_PER_SEC);
    // 调用回调的队列
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    // 添加时间观察者
    self.timeObserverToken =
        [self.player addPeriodicTimeObserverForInterval:interval
                                                  queue:mainQueue
                                             usingBlock:^(CMTime time) {
            //使用弱引用自我
            //更新播放器传输UI
        }];
}

AVPlayerItem - 播放项

在播放期间为资源的计时和表示状态建模的对象。AVPlayerItem(播放器项)存储对AVAsset对象的引用,该对象表示要播放的媒体。如果需要在将资源排入队列以供播放之前检查它,请调用其load:方法以检索一个或多个属性的值。或者可以通过将所需属性传递给其init((asset:automaticallyLoadedAssetKeys:)初始值设定项来告诉播放项自动加载所需属性。当播放项准备好播放时,请求的资源属性即可使用。

AVPlayerItem常用属性
@property (readonly) AVPlayerItemStatus status;

属性描述播放项的状态。创建播放项时,其状态为AVPlayerItemStatusUnknown,这意味着其媒体尚未加载,尚未排队播放。将播放器项目与AVPlayer关联后,立即开始对项目的媒体进行排队,并为播放做好准备。当播放器项目的媒体已加载并准备好使用时,其状态将更改为AVPlayerItemStatusReadyToPlay。可以使用键值观察(KVO)来观察此更改

typedef NS_ENUM(NSInteger, AVPlayerItemStatus) {
        //未知状态
    AVPlayerItemStatusUnknown = 0,
        //准备播放
    AVPlayerItemStatusReadyToPlay = 1,
        //加载失败
    AVPlayerItemStatusFailed = 2
};
AVPlayerItem常用函数
- (instancetype)initWithURL:(NSURL *)URL;

函数描述创建一个带有指定URL的播放器项目。该方法立即返回播放项,但状态为AVPlayerItemStatusUnknown。将AVPlayerItem(播放器项目)与AVPlayer相关联,立即开始将其媒体排队并准备播放。如果URL包含播放项目可以使用的有效数据,它的状态稍后更改为AVPlayerItemStatusReadyToPlay。如果URL不包含有效的数据或播放器项目不能使用,它的状态稍后更改为AVPlayerItemStatusFailed。可以通过查询播放器项目的错误属性来确定失败的性质。

参数 :

URL :标识要播放的媒体资源的URL。

返回值 :一个新的播放器项目,使用准备URL。

- (instancetype)initWithAsset:(AVAsset *)asset;

函数描述:为指定的资源创建一个播放器项目。

参数 :

asset :要播放的AVAsset。

返回值 : 一个新的播放器项目,初始化为播放资源。

\color{red}{最简单的例子,三行代码就可以播放声音:}

AVPlayerItem *playerItem = [[AVPlayerItem alloc]initWithURL:[NSURL URLWithString:@"http://www.runoob.com/try/demo_source/horse.mp3"]];
//AVPlayer对象需要强引用
self.player = [[AVPlayer alloc]initWithPlayerItem:playerItem];
[self.player play];

AVPlayerItem (AVPlayerItemPlayability) - 播放项可播放性相关

AVPlayerItem (AVPlayerItemPlayability)常用属性
@property (readonly) NSArray<NSValue *> *loadedTimeRanges;

属性描述:一组时间范围,指示随时可用的媒体数据。该数组包含NSValue对象,该对象包含一个CMTimeRange值,该值指示播放器项具有可用媒体数据的时间范围。返回的时间范围可能不连续。

AVPlayerItem (AVPlayerItemInspection) - 播放项检查相关

AVPlayerItem (AVPlayerItemInspection)常用属性
@property (readonly) CMTime duration API_AVAILABLE(macos(10.7), ios(4.3), tvos(9.0), watchos(1.0));

属性描述:播放项的持续时间(播放项时长)。

不考虑播放项的forwardPlaybackEndTime或reversePlaybackEndTime。在加载基础资源的持续时间之前,此属性的值将被报告为kCMTimeIndefinite。有两种方法可以确保duration的值在变为可用后才被访问:

对于直播流,duration的值可以保持kCMTimeIndefinite。

AVAudioSession - 音频会话

AVAudioSession(音频会话)对象向系统传达如何在应用程序中使用音频的意图。音频会话充当应用程序和操作系统之间的中介,进而也充当底层音频硬件之间的中介。使用音频会话向操作系统传达应用程序音频的一般性质,而无需详细说明特定行为或与音频硬件的必要交互。将这些详细信息的管理委派给音频会话,这样可以确保操作系统能够最佳地管理用户的音频体验。

所有iOS、tvOS和watchOS应用程序都有一个默认的音频会话,该会话预先配置了以下行为:

尽管默认音频会话提供有用的行为,但它通常不会提供媒体应用程序所需的音频行为。要更改默认行为,需要配置应用程序的音频会话类别。

可以使用六种可能的类别,但AVAudioSessionCategoryPlayback是播放应用程序最常用的类别,此类别表示音频播放是应用程序的核心功能。当指定此类别时,应用程序的音频将在响铃/静音开关设置为静音模式(仅限iOS)时继续,如果在后台模式下播放音频或在AirPlay和“画中画”中播放也可以使用此类别

使用AVAudioSession对象来配置应用程序的音频会话。这个类是一个单例对象,用于设置音频会话的类别、模式和其他配置。可以在应用程序的整个生命周期中与音频会话进行交互,但在应用程序启动时执行此配置通常很有用,
当使用setActive:error:或setActive:withOptions:error:方法激活会话时,音频会话将使用此配置。

设置音频会话的类别后,可以随时激活音频会话,但通常最好将此呼叫推迟到应用程序开始音频播放。延迟通话可确保不会过早中断正在进行的任何其他背景音频。

AVAudioSession常用属性
@property (readonly, getter=isOtherAudioPlaying) BOOL otherAudioPlaying API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);

属性描述一个布尔值,指示另一个应用程序是否正在播放音频。如果任何其他音频正在播放,该属性返回YES。

AVAudioSession常用函数
+ (AVAudioSession *)sharedInstance API_AVAILABLE(ios(3.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);

函数描述:返回音频会话共享单例。

- (BOOL)setActive:(BOOL)active error:(NSError **)outError API_AVAILABLE(ios(3.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);

函数描述激活或关闭应用程序的音频会话。如果另一个音频会话的优先级高于应用程序的(例如电话),并且两个音频会话都不允许混合,则试图激活应用程序的音频会话将失败。如果音频会话中有正在运行的音频对象,那么再次激活则该会话将停止音频对象的运行,并返回一个AVAudioSessionErrorCodeIsBusy错误。当取消激活会话时,返回值为falseExpression,但激活状态变为deactivate。

参数 :

active : 使用YES来激活应用程序的音频会话,或使用NO来禁用它。

outError :在输入端,指向错误对象的指针。如果发生错误,框架将指针设置为描述错误的NSError对象。如果你不想要错误信息,传入nil。

返回值 : 如果会话的活动状态成功更改,则为YES,否则为NO。

- (BOOL)setCategory:(AVAudioSessionCategory)category error:(NSError **)outError API_AVAILABLE(ios(3.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);

函数描述设置音频会话的类别。音频会话的类别定义了应用程序如何使用音频,通常在激活会话之前设置类别。也可以在会话处于活动状态时设置类别,但这将导致立即更改音频路由。

需要注意的是与其单独设置类别和模式属性,不如使用setCategory:mode:options:error:或setCategory:mode:routeSharingPolicy:options:error:方法同时设置它们。

参数 :

category : 要应用于音频会话的类别。AVAudioSessionCategory定义了支持的类别值。

outError : 在输入端,指向错误对象的指针。如果发生错误,指针是一个描述错误的NSError对象。如果你不想要错误信息,传入nil。

返回值 :如果音频会话类别设置成功则为YES,否则则为NO。

AVAudioSession常用通知
OS_EXPORT NSNotificationName const  AVAudioSessionRouteChangeNotification API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0));

通知描述当它的音频路由改变时,系统发出的通知,例如监测耳机。此通知的userInfo字典包含AVAudioSessionRouteChangeReasonKey和AVAudioSessionRouteChangePreviousRouteKey键,它们提供了路由变化的信息。系统将此通知发布到一个辅助线程上。

OS_EXPORT NSNotificationName const  AVAudioSessionInterruptionNotification API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0));

通知描述当音频中断发生时,系统发出的通知,例如别的软件播放音乐、来电话。通知的用户信息字典包含AVAudioSessionInterruptionTypeKey键。如果中断类型是AVAudioSessionInterruptionTypeBegan,系统中断了应用程序的音频会话,它不再处于活动状态。如果中断类型是AVAudioSessionInterruptionTypeEnded,此字典还包含AVAudioSessionInterruptionOptionKey键。从iOS 10开始,当系统暂停应用程序进程时,会停用应用程序的音频会话。当应用程序再次开始运行时,它会收到一个中断通知,说明系统已经停用了它的音频会话。这个通知必须在时间上延迟,因为系统只能在应用程序再次运行时发送它。如果系统因此暂停了应用程序的音频会话,用户信息字典包含值为YES的AVAudioSessionInterruptionWasSuspendedKey键。
如果将音频会话配置为不可混合(AVAudioSessionCategoryPlayback, AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategorySoloAmbient和AVAudioSessionCategoryMultiRoute类别的默认行为),当应用程序进入后台时,如果应用程序不积极使用音频,则禁用应用程序的音频会话。这样做可以避免应用程序的音频会话被系统停用(并收到这个有点混乱的通知)。

OS_EXPORT NSNotificationName const  AVAudioSessionSilenceSecondaryAudioHintNotification API_AVAILABLE(ios(8.0), watchos(2.0), tvos(9.0));

通知描述当其他应用程序的主音频开始和停止时,系统发布的通知。监听此通知,以确保当可选辅助音频静音应该开始或结束时,系统会通知你的应用程序。系统只将此通知发送给当前处于前台并具有活动音频会话的注册监听器。

此通知的userInfo字典包含AVAudioSessionSilenceSecondaryAudioHintTypeKey的AVAudioSessionSilence SecondaryAudioChintType值。使用音频提示类型确定辅助音频静音应该开始还是结束。系统将此通知发布到主线程上。

AVURLAsset - URL中媒体的资源

在本地或远程URL中表示媒体的资源。这个类是AVAsset的一个具体子类。当您创建如下所示的资源时,系统将创建并返回AVURLAsset的实例。

此类是AVAsset的具体子类。如下图所示创建资产时,系统将创建并返回AVURLAsset的实例:

NSURL *url = [NSURL URLWithString:@"https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3"];
id asset = [AVAsset assetWithURL:[NSURL URLWithString:@""]];

在许多情况下,这是创建AVURLAsset实例的适当方法。,但是当您需要对AVURLAsset的初始化进行更细粒度的控制时,您也可以直接实例化AVURLAsset。AVURLAsset的初始化方法接受一个选项字典,您可以使用它为特定的目的定制资产的初始化。例如,如果您正在为一个HLS流创建一个资产,您可能希望在它通过蜂窝网络连接时阻止它检索其媒体。例如可以通过提供如下所示的初始化选项和值来做到这一点。

NSURL *url = [NSURL URLWithString:@"https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3"];
NSDictionary *options = @{AVURLAssetAllowsCellularAccessKey : @(NO)};
AVURLAsset *urlAsset = [[AVURLAsset alloc]initWithURL:url options:options];
AVURLAsset常用属性
@property (nonatomic, readonly) AVAssetResourceLoader *resourceLoader API_AVAILABLE(macos(10.9), ios(6.0), tvos(9.0)) API_UNAVAILABLE(watchos);

属性描述资源的资源加载器对象。在加载过程中,系统可能会要求资源加载器协助加载资源。例如,需要解密的资源可能要求资源加载器提供适当的解密密钥。可以将代理对象分配给资源加载器对象,并使用代理来拦截这些请求并提供适当的响应。例如 :

[asset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];

AVAssetResourceLoader - 资源加载器

一个对象,用来传递AVURLAsset资源请求的URL。不必自己创建资源加载器对象(AVAssetResourceLoader),相反可以从AVURLAsset对象的resourceLoader属性中检索一个资源加载器,并使用它分配自定义的代理对象,与该对象关联的代理必须采用AVAssetResourceLoaderDelegate协议。

AVAssetResourceLoaderDelegate代理函数
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest API_AVAILABLE(macos(10.9), ios(6.0), tvos(9.0)) API_UNAVAILABLE(watchos);

函数描述询问代理是否要加载所请求的资源。当代码需要帮助来加载指定的资源时,资源加载器对象调用此方法。例如资源加载器可能调用此方法来加载使用自定义URL方案指定的解密密钥。

从该方法返回YES,只意味着调用方将加载,或至少尝试加载资源。在某些实现中,加载资源的实际工作可能在另一个线程上启动,异步运行到资源加载代理,工作是立即开始还是很快开始是客户机应用程序的实现细节。

可以同步或异步加载资源。在这两种情况下,必须在完成时通过调用请求对象的finishLoadingWithResponse:data:redirect:或finishLoadingWithError:方法来指示操作的成功或失败。如果异步加载资源,在从该方法返回之前,还必须在loadingRequest参数中存储对对象的强引用。

如果从该方法返回NO,则资源加载器将该资源的加载视为失败。

参数 :

resourceLoader :发出请求的资源加载器对象。

loadingRequest :加载请求对象,它包含有关所请求资源的信息。

返回值 :如果代理可以加载loadingRequest参数指定的资源,则为YES,否则为NO。

- (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest API_AVAILABLE(macos(10.9), ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);

函数描述通知代理先前的加载请求已被取消。当不再需要来自该资源的数据时,或者当加载请求被来自同一资源的新数据请求所取代时,可以取消以前发出的加载请求。例如,如果要完成一个seek操作,就必须加载一个不同于先前请求范围的字节范围,那么先前的请求可能会在委托仍在处理它时被取消。

参数 :

resourceLoader : 资源加载器。

loadingRequest :已取消的加载请求。

AVAssetResourceLoadingRequest - 资源加载器资源请求对象

封装来自资源加载器对象(AVAssetResourceLoader)有关资源请求的对象。当AVURLAsset对象需要帮助加载资源时,它会请求其AVAssetResourceLoader对象提供帮助。资源加载器通过创建此对象的实例来封装请求,然后将其交给其代理对象进行处理。代理使用此对象中的信息执行请求并报告操作的成功或失败。

AVAssetResourceLoadingRequest常用属性
@property (nonatomic, readonly, nullable) AVAssetResourceLoadingDataRequest *dataRequest API_AVAILABLE(macos(10.9), ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);

属性描述请求的资源数据的范围。AVAssetResourceLoadingDataRequest的一个实例,指示正在请求的资源数据范围。如果未请求任何数据,则此属性的值为nil。

@property (nonatomic, readonly) NSURLRequest *request;

属性描述请求资源的URL请求对象。使用此属性中的值来标识所请求的资源并制定适当的响应对象。

AVAssetResourceLoadingRequest常用函数
- (void)finishLoading API_AVAILABLE(macos(10.9), ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);

函数描述使调用方认为请求的处理已经完成。如果存在dataRequest,并且根据请求的requestdoffset和requestdlength属性的值,如果资源不包含请求的全部数据,那么在提供与资源包含的相同数量的请求数据后,调用finishLoading。

AVAssetResourceLoadingDataRequest - 资源加载器资源请求信息对象

用于从资源请求中设置请求数据的对象,资源加载请求引用该资源

AVAssetResourceLoaderDelegate使用AVAssetResourceLoadingDataRequest类来进行实际的数据读取,并且它的方法将在必要时被调用,为AVAssetResourceLoadingRequest实例获取数据。

当实现了AVAssetResourceLoaderDelegate协议的资源加载代理接收到AVAssetResourceLoadingRequest的实例作为代理的resourceLoader:shouldWaitForLoadingOfRequestedResource:方法的第二个参数时,它可以选择承担加载引用资源的责任。如果它接受这个责任,通过返回YES,它必须检查AVAssetResourceLoadingRequest实例的dataRequest属性是否不是nil,如果它不是nil,资源加载代理将被告知底层媒体系统所需要的资源中的字节范围。作为响应,数据由一个或多个respondWithData调用提供,以提供所请求的数据。根据方便性或效率,可以根据资源加载代理确定数据的增量提供。

当AVAssetResourceLoadingRequest方法finishLoading被调用时,数据请求被认为是完全满足的。如果尚未提供所请求的全部字节范围,则底层媒体系统假定资源的长度仅限于所提供的内容。

AVAssetResourceLoadingDataRequest常用属性
@property (nonatomic, readonly) long long requestedOffset;

属性描述请求的第一个字节在资源中的位置。当所有可以提供的请求字节都被加载时,包括AVAssetResourceLoadingRequest实例中可能的contentInformationRequest数据(包含调用方),委托应该通过调用finishLoading进行响应。

如果requestdoffset值超出了资源的内容长度,AVAssetResourceLoadingRequest实例将被发送一个finishLoading消息,而不调用任何respondWithData:。

@property (nonatomic, readonly) NSInteger requestedLength;

属性描述请求数据的长度(以字节为单位)。如果资源的内容长度未知,则requestedLength和requestedOffset属性的和可能大于实际的内容长度。当出现这种情况时,应用程序必须尝试提供从requestdoffset属性开始请求的数据与资源包含的一样多。应用程序必须在成功时调用AVAssetResourceLoadingRequest实例的finishLoading方法,或者在加载过程中遇到错误时调用finishLoadingWithError:方法。

@property (nonatomic, readonly) long long currentOffset;

属性描述下一个字节在资源中的位置。当增量加载数据时,在此值之前的字节就已经提供。您应该从这个偏移量开始加载,并通过调用respondWithData:方法返回数据。

AVAssetResourceLoadingDataRequest常用函数
- (void)respondWithData:(NSData *)data;

函数描述为加载请求提供数据。这个方法可以在AVAssetResourceLoadingDataRequest的同一个实例上被多次调用,以增量地提供所请求的数据的全部范围。每次调用时,都会更新currentOffset属性的值,以匹配所提供的数据量。

参数:

data : 包含部分或所有请求字节的NSData实例。

AVAssetResourceLoadingContentInformationRequest - 查询资源加载请求引用的资源的基本信息

用于检索资源加载请求引用的资源的基本信息的查询。当资源加载代理(它必须实现AVAssetResourceLoaderDelegate协议)在resourceLoader:shouldWaitForLoadingOfRequestedResource:方法被调用时接收到一个AVAssetResourceLoadingRequest的实例并承担加载资源的责任时,它必须检查AVAssetResourceLoadingRequest的contentInformationRequest属性是否为nil,当该值不是nil时,请求包含对AVAssetResourceLoadingContentInformationRequest封装的信息的查询。为了响应这样的查询,资源加载代理应该在调用AVAssetResourceLoadingRequest方法finishLoading之前适当地设置内容信息请求的属性值。

调用finishLoading时,其contentInformationRequest属性的属性值将部分决定如何处理所请求的资源。例如,如果请求资源的URL是AVURLAsset的URL,而资源加载委托将contentType设置为底层媒体系统不识别的媒体文件类型,则AVURLAsset上的操作很可能会失败,例如播放。

AVAssetResourceLoadingContentInformationRequest常用属性
@property (nonatomic, copy, nullable) NSString *contentType;

属性描述指定被请求的资源所包含的数据类型的UTI(Uniform Type Identifier(简称UTI),iOS系统中为了更好的进行类型标识,而提供的一套共用的规范)。在完成加载AVAssetResourceLoadingRequest实例之前,如果它的contentInformationRequest属性不是nil,将这个属性的值设置为一个UTI,表示被请求的资源所包含的数据类型。

@property (nonatomic, getter=isByteRangeAccessSupported) BOOL byteRangeAccessSupported;

属性描述一个布尔值,指示是否支持对资源的任意字节范围的随机访问。在完成加载AVAssetResourceLoadingRequest实例之前,如果它的contentInformationRequest属性不是nil,如果它支持对资源的任意字节范围的随机访问,则将该属性的值设置为YES。对于必须增量加载的资源,这类资源包括任何包含媒体数据的资源,如果此属性不是YES,则可能会导致资源加载失败。
如果此属性是YES,则可以多次请求部分资源。

@property (nonatomic) long long contentLength;

属性描述请求资源的长度(以字节为单位)。在完成加载AVAssetResourceLoadingRequest实例之前,如果它的contentInformationRequest属性不是nil,将contentLength属性的值设置为被请求资源所包含的字节数。

上一篇下一篇

猜你喜欢

热点阅读