Implementar la gestión de bloqueos

TVSDK proporciona API y código de muestra para la gestión de periodos de interrupción.

Para implementar la gestión de bloqueos, incluido el suministro de contenido alternativo durante la interrupción:

  1. Configure la aplicación para detectar etiquetas de bloqueo en un manifiesto de flujo en directo.

    public void createMediaPlayer { 
        ... 
        String[] blackoutTags = {BLACKOUTTAG}; 
        PSDKConfig.setSubscribedTags(blackoutTags); 
        // For example: PTSDKConfig.setSubscribedTags({"#EXT-OATCLS-SCTE35"}); 
    }
    
  2. Cree oyentes de eventos para eventos de metadatos temporizados en flujos en primer y segundo plano.

    private MediaPlayer createMediaPlayer() { 
        mediaPlayer.addEventListener(MediaPlayer.Event.PLAYBACK, _playbackEventListener); 
        mediaPlayer.addEventListener(MediaPlayer.Event.BLACKOUTS, _blackoutsEventListener); 
    }
    
  3. Implemente controladores de eventos de metadatos temporizados para flujos en primer y segundo plano.

    Primer plano:

    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. Gestione los objetos TimedMetadata cuando se ejecute el tiempo MediaPlayer .

    _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. Cree métodos para cambiar contenido al principio y al final del periodo de interrupción.

    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. Actualice rangos no buscables si el rango de interrupción está en DVR en el flujo de reproducción.

    // 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]; 
                } 
            } 
        } 
    }
    
    NOTA

    Actualmente, para varios flujos en directo de velocidad de bits, ocasionalmente los perfiles de velocidad de bits ajustable (ABR) pueden no estar sincronizados. Esto provoca objetos timedMetadata duplicados para la misma etiqueta suscrita. Para evitar cálculos incorrectos que no se pueden buscar, es muy recomendable comprobar si hay intervalos que no se pueden buscar superpuestos después de los cálculos, como en el siguiente ejemplo:

    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); 
    }
    

En esta página

Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free
Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now