實施封鎖處理

TVSDK提供API和范常式式碼,以處理封鎖期。

要實施封鎖期處理並在封鎖期間提供替代內容,請執行以下操作:

  1. 設定您的應用程式以訂閱即時串流資訊清單中的封鎖標籤。
 - (void) createMediaPlayer:(PTMediaPlayerItem *)item
 { 
     [PTSDKConfig setSubscribedTags:[NSArray arrayWithObject:<INSERT-BLACKOUT-TAG>]];
     // For example:  
     // [PTSDKConfig setSubscribedTags:[NSArray arrayWithObject:@"#EXT-OATCLS-SCTE35"]];
 }
  1. PTTimedMetadataChangedNotification添加通知偵聽程式。

    - (void)addobservers 
    { 
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaPlayerSubscribedTagIdentified:)  
          name:PTTimedMetadataChangedNotification object:self.player.currentItem]; 
    }
    
  2. 在前景中實現PTTimedMetadata對象的監聽器方法。

    例如:

    - (void)onMediaPlayerSubscribedTagIdentified:(NSNotification *)notification 
    { 
        NSDictionary *userInfo = [notification userInfo]; 
        PTTimedMetadata *timedMetadata = [(PTTimedMetadata *)[userInfo objectForKey:PTTimedMetadataKey]  
          retain]; 
    
     if ([timedMetadata.name isEqualToString:<INSERT-BLACKOUT-TAG>]) 
        { 
         // handle tag. For example: store it in a dictionary keyed by time to be handled when  
         //   playback time = timedMetadata time. 
            NSNumber *timedMetadataStartTime =  
              [NSNumber numberWithInt:(int)CMTimeGetSeconds(timedMetadata.time)]; 
            [timedMetadataCollection setObject:timedMetadata forKey:timedMetadataStartTime]; 
        } 
    
        [timedMetadata release]; 
    }
    
  3. 在播放期間使用持續更新來處理TimedMetadata物件。

    - (void)onMediaPlayerTimeChange:(NSNotification *)notification 
    { 
        @synchronized(self) 
        { 
            CMTimeRange seekableRange = self.player.seekableRange; 
            if (CMTIMERANGE_IS_VALID(seekableRange)) 
            { 
                _currentTime = (int) CMTimeGetSeconds(self.player.currentTime); 
                if (isnan(_currentTime)) 
                { 
                    _currentTime = 0; 
                } 
                [self handleCollectionAtTime:_currentTime]; 
            } 
        } 
    }
    
  4. 新增PTTimedMetadata處理常式,以切換至替代內容,並返回主要內容,如PTTimedMetadata物件及其播放時間所示。

    - (void)handleCollectionAtTime:(int)currentTime 
    { 
        NSArray *allKeys = nil; 
        NSMutableArray * timedMetadatasToDelete = [[[NSMutableArray alloc]init]autorelease]; 
    
        if (!_inBlackout && timedMetadataCollection) 
        { 
            allKeys = [timedMetadataCollection allKeys]; 
            int count = [allKeys count]; 
            for (int i=count-1; i>-1; i--) 
            { 
                NSNumber *currTimedMetadataTime = allKeys[i]; 
                PTTimedMetadata *currTimedMetadata =  
                  [timedMetadataCollection objectForKey:currTimedMetadataTime]; 
    
                if (currentTime == [currTimedMetadataTime integerValue] &&  
                                   currTimedMetadata.name == <INSERT-BLACKOUT-TAG> &&  
                                   [self isBlackoutStart: currTimedMetadata]) 
                { 
                                    PTAdMetadata *newItemAdMetadata =  
                                      [self createAlternateMediaMetadata];            
    
                // 1. Turn off preroll on the alternate media item. 
                    newItemAdMetadata.enableLivePreroll = NO; 
    
                                PTMediaPlayerItem *newItem =  
                                  [[PTMediaPlayerItem alloc]initWithUrl: 
                                    <INSERT-ALTERNATE-STREAM-URL mediaId:<INSERT-ALTERNATE-STREAM- 
                                     MEDIA-ID> metadata:newItemAdMetadata];
    
               // 2. Register the current (original playback item) in background. 
                    [self.player registerCurrentItemAsBackgroundItem]; 
    
               // 3. Replace the current playback item with the alternate stream. 
                     [self.player replaceCurrentItemWithPlayerItem:newItem]; 
    
               // 4. Reset observers. 
                    [self removeObservers]; 
                    [self addobservers]; 
    
               // 5. Register listener on the subscribed tags in background item. 
                    [[NSNotificationCenter defaultCenter] addObserver:self  
                       selector:@selector(onSubscribedTagInBackground:)  
                        name:PTTimedMetadataChangedInBackgroundNotification  
                          object:self.player.currentItem]; 
    
               // 6. Register listener on the error in background item. 
                             [[NSNotificationCenter defaultCenter]  
                                addObserver:self selector:@selector(onBackgroundManifestError:)  
                                name:PTBackgroundManifestErrorNotification   
                                  object:self.player.currentItem]; 
    
               // 7. Resume playback 
                         [self.player play]; 
    
                        // 8. Set boolean to true to handle blackout end. 
                      _inBlackout = YES; 
                      break; 
                } 
            } 
        } 
        else if (_inBlackout && backgroundTimedMetadataCollection) 
        { 
            allKeys = [backgroundTimedMetadataCollection allKeys]; 
            int count = [allKeys count]; 
            for (int i=count-1; i>-1; i--) 
            { 
                NSNumber *currTimedMetadataTime = allKeys[i]; 
                PTTimedMetadata *currTimedMetadata =  
                  [backgroundTimedMetadataCollection objectForKey:allKeys[i]]; 
    
                if (currentTime == ([currTimedMetadataTime integerValue] &&  
                  currTimedMetadata.name == <INSERT-BLACKOUT-TAG>  &&  
                  [self isBlackoutEnd:currTimedMetadata] ) 
                {      
                                   // 1. Come out of blackout. Unregister background item. 
                               [self.player unregisterCurrenBackgroundItem]; 
    
                        PTMetadata *metadata = [self createMetadata]; 
                        PTAdMetadata *adMetadata =  
                          (PTAdMetadata *)[currMetadata metadataForKey:PTAdResolvingMetadataKey]; 
                              adMetadata.enableLivePreroll = NO; 
    
                                PTMediaPlayerItem *item =  
                                  [[[PTMediaPlayerItem alloc] initWithUrl:<INSERT-ORIGINAL-URL>  
                                    mediaId:<INSERT-ORIGINAL-MEDIAID> metadata:metadata autorelease]; 
    
                                    // 2. Switch back to original item. 
                        [self.player replaceCurrentItemWithPlayerItem:item]; 
                        self.player.autoPlay = YES; 
                        [self removeObservers]; 
    
                        // 3. Remove background item listener. 
                        [[NSNotificationCenter defaultCenter] removeObserver:self  
                           name:PTTimedMetadataChangedInBackgroundNotification  
                        object:self.player.currentItem]; 
    
                                   [[NSNotificationCenter defaultCenter] removeObserver:self  
                                      name:PTBackgroundManifestErrorNotification 
                        object:self.player.currentItem]; 
                        [self addobservers]; 
                        [self.player play]; 
    
                                // 4. Update boolean to correctly maintain the current state. 
                        _inBlackout = NO; 
                        break; 
                } 
            } 
        } 
    }
    
  5. 在後台為PTTimedMetadata對象實施偵聽器方法。

    - (void)onSubscribedTagInBackground:(NSNotification *)notification 
    { 
        NSDictionary *userInfo = [notification userInfo]; 
        PTTimedMetadata *timedMetadata = [(PTTimedMetadata *) 
          [userInfo objectForKey:PTTimedMetadataKey] retain]; 
    
        if ([timedMetadata.name isEqualToString:<INSERT-BLACKOUT-TAG>]) 
        { 
            NSNumber *timedMetadataStartTime =  
              [NSNumber numberWithInt:(int)CMTimeGetSeconds(timedMetadata.time)]; 
            [backgroundTimedMetadataCollection  
               setObject:timedMetadata forKey:timedMetadataStartTime]; 
        } 
    
        [timedMetadata release]; 
    }
    
  6. 實作背景錯誤的監聽器方法。

    - (void) onBackgroundManifestError:(NSNotification *)notification 
    { 
        NSLog (@"onBackgroundManifestError"); 
    }
    
  7. 如果封鎖範圍位於播放串流的DVR上,請更新不可見的範圍。

    // This sample assumes that blackoutStartTimedMetadata is the PTTimedMetadata  
    // object that indicated "blackout start", and assuming blackoutEndTimedMetadata is the  
    // PTTimedMetadataObject that indicated "blackout end". Since in this case they are both  
    // in DVR, both are notified to the application before playback starts. This is the right  
    // time for the application to set this range in DVR as non-seekable range. 
    
    CMTime ignoreRangeStart = blackoutStartTimedMetadata.time; 
    CMTime ignoreRangeDuration = CMTimeMakeWithSeconds(CMTimeMakeWithSeconds  
      (CMTimeGetSeconds(blackoutEndTimedMetadata.time) -   
         CMTimeGetSeconds(blackoutStartTimedMetadata.time)),  
           blackoutEndTimedMetadata.time.timescale); 
    
    CMTimeRange ignoreRange = CMTimeRangeMake(ignoreRangeStart, ignoreRangeDuration); 
    NSArray *ignoreRangeArray = [NSArray arrayWithObject:[NSValue valueWithCMTimeRange:ignoreRange]]; 
    PTBlackoutMetadata *blackoutMetadata =  
      [[PTBlackoutMetadata alloc]initWithNonSeekableRanges:ignoreRangeArray]; 
    PTMetadata *currMetadata = self.item.metadata; 
    
    if (currMetadata) 
    { 
        [currMetadata setMetadata:blackoutMetadata forKey:PTBlackoutMetadataKey] 
    }
    

本頁內容