首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对于Exoplayer的AdaptiveTrackSelection,我应该切换到多个码率的单个音轨,而不是四个单独码率的音轨吗?

对于Exoplayer的AdaptiveTrackSelection,我应该切换到多个码率的单个音轨,而不是四个单独码率的音轨吗?
EN

Stack Overflow用户
提问于 2018-11-01 12:23:29
回答 1查看 894关注 0票数 0

目前,我有一个服务器可以传输四个RTMP MediaSource,一个有720p视频源,一个有360p视频源,一个有180p视频源,还有一个只有音频源。如果我想要切换分辨率,我必须停止ExoPlayer实例,准备我想要切换到的另一首曲目,然后播放。

我用来准备ExoPlayer实例的代码如下:

代码语言:javascript
运行
复制
    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()为:

代码语言:javascript
运行
复制
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之间切换的代码是:

代码语言:javascript
运行
复制
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结构:

代码语言:javascript
运行
复制
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)+"");
                    }
                }
            }
        }
    }

只是给我一种视频格式和一种音频格式。

我目前的解决方法是在后台准备另一个ExoPlayer实例,在准备完成后将当前运行的实例替换为该实例,然后释放旧实例。这在一定程度上减少了MediaSources之间的延迟,但无法实现像Youtube那样的无缝分辨率转换。

我是否应该实现自己的TrackSelector并将所有4个源打包到其中,我是应该实现另一个处理所有4个源的MediaSource,还是应该只告诉维护流的同事切换到一个RTMP MediaSource,并列出AdaptiveTrackSelection可以在它们之间切换的所有可用分辨率?

EN

回答 1

Stack Overflow用户

发布于 2018-11-02 20:01:05

自适应比特率流旨在允许在不同比特率流之间轻松切换,但它需要对流进行分段,并要求播放器逐段下载视频。

以这种方式,播放器可以根据当前网络条件(以及设备显示大小和T类型)来决定为下一段选择哪种比特率。除了不同的比特率和质量之外,播放器还能够以这种方式从一个比特率无缝移动到另一个比特率。

更多信息请看这里:https://stackoverflow.com/a/42365034/334402

所有这些都依赖于支持这种分段和不同比特率流的传送协议。目前最常见的是HLS和MPEG-DASH。

要支持我认为你正在寻找的东西,最简单的方法是让你的同事使用HLS和/或DASH来提供流。

请注意,目前,HLS和DASH都是必需的,因为苹果设备需要HLS,而其他设备倾向于默认使用DASH。传统上,HLS使用TS作为片段中的视频容器,DASH使用碎片MP4,但现在两者都使用MP4,这本质上是碎片CMAF。

所以从理论上讲,单个码率的视频现在可以用于HLS和DASH实际上这将取决于你的内容是否加密,就像HLS和苹果过去使用一种加密模式,而其他所有人使用另一种加密模式一样。这种情况现在也在改变,但在所有设备支持新方法之前需要时间,所有设备都可以支持相同的加密模式,所以如果你的流是加密的,这在目前是一个额外的复杂性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53095184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档