實施封鎖處理

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

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

  1. 設定您的應用程式,以偵測即時串流資訊清單中的封鎖標籤。

    public void createMediaPlayer { 
        ... 
        String[] blackoutTags = {BLACKOUTTAG}; 
        PSDKConfig.setSubscribedTags(blackoutTags); 
        // For example: PTSDKConfig.setSubscribedTags({"#EXT-OATCLS-SCTE35"}); 
    }
    
  2. 為前景和背景串流中的計時中繼資料事件建立事件接聽程式。

    private MediaPlayer createMediaPlayer() { 
        mediaPlayer.addEventListener(MediaPlayer.Event.PLAYBACK, _playbackEventListener); 
        mediaPlayer.addEventListener(MediaPlayer.Event.BLACKOUTS, _blackoutsEventListener); 
    }
    
  3. 為前景和背景串流實作計時中繼資料事件處理常式。

    前景:

    private final MediaPlayer.PlaybackEventListener _playbackEventListener =  
              new MediaPlayer.PlaybackEventListener() { 
        ... 
    
        @override 
        public void onTimedMetadata(TimedMetadata timedMetadata) { 
            if (timedMetadata.getName().equal(BLACKOUTTAG) &&  
                !_timedMetadataList.contains(timedMetadata)) { 
                  _timedMetadataList.add(timedMetadata); 
            } 
        } 
        ... 
    } 
    
    private final MediaPlayer.BlackoutsEventListener _blackoutsEventListener =  
      new MediaPlayer.BlackoutsEventListener() { 
        @Override 
        public void onTimedMetadataInBackgroundItem(TimedMetadata timedMetadata) { 
            TimedMetadata.Type type = timedMetadata.getType(); 
            if (type.equals(TimedMetadata.Type.TAG) && _mediaPlayer.getPlaybackRange() != null  
                && _mediaPlayer.getPlaybackRange().getDuration() > 0) { 
                if (!_timedMetadataList.contains(timedMetadata) && isBlackoutMetadata(timedMetadata)) { 
                    _timedMetadataList.add(timedMetadata); 
                } 
            } 
        } 
    
        @Override 
        public void onBackgroundManifestFailed() { 
            ... 
        } 
    }; 
    
  4. MediaPlayer時間運行時處理TimedMetadata對象。

    _playbackClockEventListener = new Clock.ClockEventListener() { 
        @Override 
        public void onTick(String name) { 
            getActivity().runOnUiThread(new Runnable() { 
                @Override 
                public void run() { 
                    /* handle timedmetadata object list  */ 
                    if (_mediaPlayer != null && _timedMetadataList != null  
                        && _timedMetadataList.size() > 0) { 
                        if (_lastKnownStatus == MediaPlayer.PlayerState.PLAYING) { 
                            long localTime = _mediaPlayer.getLocalTime(); 
                            handleTimedMetadataList(localTime);      
                        } 
                    } 
                }                        
            }); 
        } 
    };
    
  5. 建立在封鎖期開始和結束時切換內容的方法。

    private void handleTimedMetadataList(long currentTime) { 
        for (int i = 0; i < _timedMetadataList.size(); i++) { 
            TimedMetadata timedMetadata = _timedMetadataList.get(i); 
            long diff = localTime - timedMetadata.getTime(); 
            if (!_timedMetadataDispatchedList.contains(timedMetadata) 
                && diff >= 0 
                && diff <= PLAYBACK_CLOCK_INTERVAL 
                && _mediaPlayer.shouldTriggerSubscribedTagEvent()) { 
                    // switch to blackout content 
                if (!_inBlackout && isBlackoutStartTimedMetadata(timedMetadata)) { 
                    MediaResource blackoutMediaResource = createBlackoutMediaResource(timedMetadata); 
    
                    //1. register current item as background item 
                    _mediaPlayer.registerCurrentItemAsBackgroundItem(); 
    
                    //2. replace current item with blackout item 
                    _mediaPlayer.replaceCurrentItem(blackoutMediaResource); 
    
                    //3. update qos metrics 
                    _mediaQosProvider.updateMetrics(_mediaPlayer); 
    
                    //4. maintain state 
                    _inBlackout = true; 
                    resetTimedMetada(); 
    
                    break; 
                } 
                // switch back to main content 
                else if (_inBlackout && isBlackoutEndTimedMetadata(timedMetadata)) { 
                    //1. register current item as background item 
                    _mediaPlayer.unregisterCurrentBackgroundItem(); 
    
                    //2. replace current item with blackout item 
                    _mediaPlayer.replaceCurrentItem(_oldMediaResource); 
    
                    //3. update qos metrics 
                    _mediaQosProvider.updateMetrics(_mediaPlayer); 
    
                    //4. maintain state 
                    _inBlackout = false; 
                    resetTimedMetada(); 
    
                    break; 
                } 
            } 
        } 
    }
    
  6. 如果封鎖期範圍在播放串流的DVR中,請更新不可查看的範圍。

    // prepare and update blackout nonSeekable ranges 
    
    List<TimeRange> blackoutRanges = prepareBlackoutRanges(_timedMetadataList); 
    if (blackoutRanges != null && blackoutRanges.size() > 0) { 
        int size = blackoutRanges.size(); 
        TimeRange[] blackoutRangesArray = blackoutRanges.toArray(new TimeRange[size]); 
        BlackoutMetadata blackoutMetadata = new BlackoutMetadata(blackoutRangesArray); 
        updateBlackoutMetadata(blackoutMetadata); 
    } 
    
    // function to update blackout metadata 
    private void updateBlackoutMetadata(BlackoutMetadata blackoutMetadata) { 
        MediaPlayerItem currentItem = _mediaPlayer.getCurrentItem(); 
        if (currentItem != null) { 
            Metadata metadata = currentItem.getResource().getMetadata(); 
            if (metadata != null) { 
                MetadataNode metadataNode = ((MetadataNode) metadata); 
                metadataNode.setNode(DefaultMetadataKeys.BLACKOUT_METADATA_KEY.getValue(),  
                                     blackoutMetadata); 
    
                for (int i = 0; i < blackoutMetadata.getNonSeekableRanges().length; i++) { 
                    TimeRange timeRange = blackoutMetadata.getNonSeekableRanges()[i]; 
                } 
            } 
        } 
    }
    
    注意

    目前針對多位元速率即時串流,有時可調整位元速率(ABR)描述檔會不同步。 這會導致相同訂閱標籤的timedMetadata物件重複。 為避免不正確的不可查找計算,強烈建議在計算後檢查重疊的不可查找範圍,例如在以下示例中:

    List<TimeRange> rangesToRemove = new ArrayList<TimeRange>(); 
    
    for (int i = 0; i < nonSeekableRanges.size() - 1; i++) { 
        TimeRange range1 = nonSeekableRanges.get(i); 
        TimeRange range2 = nonSeekableRanges.get(i + 1); 
        if (range1.contains(range2.getBegin()) && !rangesToRemove.contains(range2)) { 
           rangesToRemove.add(range2); 
        } else if (range2.contains(range1.getBegin()) && !rangesToRemove.contains(range1)) { 
           rangesToRemove.add(range1); 
       } 
    } 
    
    if (nonSeekableRanges.size() > 0 && rangesToRemove.size() > 0) { 
        nonSeekableRanges.removeAll(rangesToRemove); 
        for (int i = 0; i < rangesToRemove.size(); i++) { 
            TimeRange range = rangesToRemove.get(i); 
        } 
    } 
    
    if (nonSeekableRanges.size() > 0 && rangesToRemove.size() > 0) { 
        nonSeekableRanges.removeAll(rangesToRemove); 
    }
    

本頁內容