Для AdaptiveTrackSelection в Exoplayer я должен переключиться на одну дорожку с несколькими битрейтами вместо четырех дорожек с отдельными битрейтами? - PullRequest
0 голосов
/ 01 ноября 2018

В настоящее время у меня есть сервер, который транслирует четыре RTMP MediaSource s, один с источником видео 720p, один с источником видео 360p, один с источником видео 180p и один источник только для аудио. Если я хочу переключить разрешение, я должен остановить экземпляр ExoPlayer, подготовить другой трек, на который я хотел переключиться, и затем воспроизвести.

Код, который я использую для подготовки экземпляра ExoPlayer:

    TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
    TrackSelector trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);

    RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory(bandwidthMeter);
    ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
    factory = new AVControlExtractorMediaSource.Factory(rtmpDataSourceFactory);
    factory.setExtractorsFactory(extractorsFactory);

    createSource();

    //noinspection deprecation
    mPlayer = ExoPlayerFactory.newSimpleInstance(mActivity, trackSelector, new DefaultLoadControl(
            new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
            1000,  // min buffer
            2000, // max buffer
            1000, // playback
            1000,   //playback after rebuffer
            DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES,
            true
    ));

    vwExoPlayer.setPlayer(mPlayer);

    mPlayer.addAnalyticsListener(mAnalyticsListener);

С createSource(), являющимся:

private void createSource() {
    factory.setTrackPlaybackFlag(AVControlExtractorMediaSource.PLAYBACK_BOTH_AV);
    mMediaSource180 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_180()));
    mMediaSource180.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSource180"));

    mMediaSource360 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_360()));
    mMediaSource360.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSource360"));

    mMediaSource720 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_720()));
    mMediaSource720.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSource720"));

    factory.setTrackPlaybackFlag(AVControlExtractorMediaSource.PLAYBACK_AUDIO_ONLY);
    mMediaSourceAudio = factory.createMediaSource(Uri.parse(API.GAME_AUDIO_STREAM_URL()));
    mMediaSourceAudio.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSourceAudio"));
}

private void releaseSource() {
    mMediaSource180.releaseSource(null);
    mMediaSource360.releaseSource(null);
    mMediaSource720.releaseSource(null);
    mMediaSourceAudio.releaseSource(null);
}

И код, который я сейчас использую для переключения между этими MediaSources:

private void changeTrack(MediaSource source) {
    if (currentMediaSource == source) return;

    try {
        this.currentMediaSource = source;
        mPlayer.stop(true);
        mPlayer.prepare(source, true, true);
        mPlayer.setPlayWhenReady(true);

        if (source == mMediaSourceAudio) {
            if (!audioOnly) {
                try {
                    TransitionManager.beginDelayedTransition(rootView);
                } catch (Exception ignored) {

                }

                layAudioOnly.setVisibility(View.VISIBLE);
                vwExoPlayer.setVisibility(View.INVISIBLE);
                audioOnly = true;

                try {
                    GameQnAFragment fragment = findFragment(GameQnAFragment.class);
                    if (fragment != null) {
                        fragment.signAudioOnly();
                    }
                } catch (Exception e) {
                    Trace.e(e);
                }

                try {
                    GamePollingFragment fragment = findFragment(GamePollingFragment.class);
                    if (fragment != null) {
                        fragment.signAudioOnly();
                    }
                } catch (Exception e) {
                    Trace.e(e);
                }
            }
        } else {
            if (audioOnly) {
                TransitionManager.beginDelayedTransition(rootView);
                layAudioOnly.setVisibility(View.GONE);
                vwExoPlayer.setVisibility(View.VISIBLE);
                audioOnly = false;
            }
        }
    } catch (Exception ignore) {

    }
}

Я хотел реализовать плавное переключение между этими MediaSource, чтобы мне не нужно было останавливаться и заново готовиться, но похоже, что эта функция не поддерживается ExoPlayer.

Кроме того, регистрируется каждая структура MediaSource со следующим кодом:

MappingTrackSelector.MappedTrackInfo info = ((DefaultTrackSelector)trackSelector).getCurrentMappedTrackInfo();
    if(info != null) {
        for (int i = 0; i < info.getRendererCount(); i++) {
            TrackGroupArray trackGroups = info.getTrackGroups(i);
            if (trackGroups.length != 0) {
                for(int j = 0; j < trackGroups.length; j++) {
                    TrackGroup tg = trackGroups.get(j);
                    for(int k = 0; k < tg.length; k++) {
                        Log.i("track_info_"+i+"-"+j+"-"+k, tg.getFormat(k)+"");
                    }
                }
            }
        }
    }

Просто у меня есть 1 видеоформат и 1 аудиоформат каждый.

Мой текущий обходной путь - подготовить еще один экземпляр ExoPlayer в фоновом режиме, заменить работающий в данный момент экземпляр на тот, который будет завершен, и освободить старый экземпляр. Это несколько уменьшает разрыв между MediaSources, но не приближается к достижению плавных изменений разрешения, таких как Youtube.

Должен ли я реализовать свой собственный TrackSelector и вставить в него все 4 источника, должен ли я внедрить другой MediaSource, который обрабатывает все 4 источника, или я просто должен сказать коллеге, который поддерживает потоки, переключиться только на один RTMP MediaSource со своего рода манифестом, в котором перечислены все доступные разрешения для AdaptiveTrackSelection для переключения между ними?

1 Ответ

0 голосов
/ 02 ноября 2018

Адаптивная потоковая передача по битам разработана для легкого переключения между потоками с различной скоростью, но требует сегментирования потоков и загрузки проигрывателем сегмента видео по сегментам.

Таким образом, игрок может решить, какую скорость передачи данных выбрать для следующего сегмента, в зависимости от текущих условий сети (а также размера дисплея устройства и типа t). Плеер может без проблем, кроме разной скорости передачи и качества, переходить с одной скорости передачи на другую таким образом.

Смотрите здесь для дополнительной информации: https://stackoverflow.com/a/42365034/334402

Все вышеперечисленное опирается на протокол доставки, который поддерживает эту сегментацию и различные потоки битов. Наиболее распространенными сегодня являются HLS и MPEG-DASH.

Самый простой способ поддержать то, что, я думаю, вы ищете, - это ваш коллега, который предоставляет поток для его предоставления с использованием HLS и / или DASH.

Обратите внимание, что в настоящий момент требуются HLS и DASH, поскольку для устройств Apple требуется HLS, а для других устройств по умолчанию используется DASH. Традиционно HLS использовал TS в качестве контейнера для видео в сегментах, а DASH использовал фрагментированный MP4, но в настоящее время оба стремятся использовать CMAF, который по сути является фрагментированным MP4.

Таким образом, теоретически теперь для HLS и DASH можно использовать один набор видео с битрейтом - на практике это будет зависеть от того, зашифрован ли ваш контент или нет, поскольку HLS и apple использовали один режим шифрования, а все остальные - другой. прошлое. Сейчас это тоже меняется, но потребуется время, прежде чем все устройства поддержат новый подход, когда все устройства могут поддерживать один и тот же режим шифрования, поэтому, если ваши потоки зашифрованы, это является дополнительным осложнением на данный момент.

...