首页 文章

AAC音频流可在Android的VLC中播放,但不能在Exoplayer中播放

提问于
浏览
0

我有一个RTMP流我想在我的应用程序中使用Exoplayer库播放 . 我的设置如下:

TrackSelector trackSelector = new DefaultTrackSelector();
RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory(bandwidthMeter);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
factory = new ExtractorMediaSource.Factory(rtmpDataSourceFactory);
factory.setExtractorsFactory(extractorsFactory);
createSource();

mPlayer = ExoPlayerFactory.newSimpleInstance(mActivity, trackSelector, new DefaultLoadControl(
        new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
        1000,  // min buffer
        3000, // max buffer
        1000, // playback
        2000,   //playback after rebuffer
        DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES,
        true
));
vwExoPlayer.setPlayer(mPlayer);
mPlayer.addListener(mVideoStreamHandler);
mPlayer.addVideoListener(new VideoListener() {
    @Override
    public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
        Log.d("hasil", "onVideoSizeChanged: w:" + width + ", h:" + height);
        String res = width + "x" + height;
        resolution.setText(res);
    }
    @Override
    public void onRenderedFirstFrame() {
    }
});

createSource() 的位置如下:

private void createSource() {
    mMediaSource180 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_180));
    mMediaSource360 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_360));
    mMediaSource720 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_720));
    mMediaSourceAudio = factory.createMediaSource(Uri.parse(API.GAME_AUDIO_STREAM_URL));
}

我目前的问题是只有前三个 ExtractorMediaSourceExoplayer 中正常工作 . mMediaSourceAudio 拒绝在 Exoplayer 中播放,但在适用于Android的VLC媒体播放器中工作得很好 .

现在我怀疑格式是AAC-LTP,或者需要VLC中可用编解码器而不是默认Android中的编解码器的任何AAC变体 . 但是,我无法访问编码过程,所以我不确定 .

如果不是这样,那是什么?

编辑:

我一直在调试 BandwidthMeter 并添加了 MediaSourceEventListener . 当我使用普通视频源时,会调用 onDownstreamFormatChanged() ,但在使用该音频流源时则不会 .

此外, BandwidthMeter 工作正常,在视频流进入时,字节总是在流的所有部分下载,更多字节,但仅在仅音频流中,当我调用 mPlayer.getBufferedPosition() 时,返回的值始终为0 . ,当我使用音频流源时,没有调用OMX代码 - 没有设置解码器 .

我看到格式错误的音频流,还是需要更改Exoplayer的设置?

编辑2:

进一步调试显示,在所有视频流和音频流中,使用相同的 FlvExtractor . 即使视频流具有 avc 视频轨道编码和 mp4a-latm 音频轨道编码 . 这是正常的吗?

2 回答

  • 0

    事实证明这是因为流被识别为有两个轨道/ sampleQueue . 一个音频轨道和一个空格式轨道 . 该空轨道应该是视频轨道,根据流的 flvHeader 标志应该存在 .

    现在,我通过使用自定义 MediaPeriod 创建自定义 MediaSource 来解决这个问题 . 所述自定义 MediaPeriod 具有分隔 SampleQueue 的视频和音频轨道的代码,然后当我想播放仅音频流时使用仅音频 SampleQueue[] 而不是源 SampleQueue[] .

    虽然这给了我另一个值得关注的问题:在rtmp流中有's something one can do to alter the '有音轨( flag & 0x04 )和视频轨道( flag & 0x01 )'标志,对吧?

  • 0

    感谢您的评论,我是ExoPlayer的新手 . 但是您的评论帮助我调试并获得了多个问题的解决方法 .

    我尝试使用自定义MediaSource和自定义MediaPeriod来解决此音频问题 . 我观察到视频格式数据出现在视频音频流的音频数据之后,因此函数maybeFinishPrepare()将在调用onPrepared之前等待获取视频和音频格式标签数据,如果首先接收到视频tagData . 首先接收到的音频数据,它不会等待并将调用onPrepare() .

    通过上述更改,我能够单独播放音频和video_audio wowza流,其中带有tagTypes的rtmp tagHeader按照视频tagData的顺序出现,然后是音频数据 .

    我无法使用与srs服务器相同的补丁来播放具有相同更改的audio_only和video_audio流 . srs服务器按音频顺序给出tagData,然后是视频tagData,

    所以,我在FlvExtractor中进一步调试 . 在readFlvHeader中,我重写了hasAudio和hasVideo变量 . 这些变量将根据前几个tagHeaders(5或6)进行设置 . 我在循环中使用peekFully输入6次 . 在获取tagType和tagDataSize之后的每个循环中,tagDataSize用于input.advancePeekPosition(),而tagType用于标识我们是否在tagData中有音频/视频格式数据 . 在查看前6个连续的tagHeaders之后,我能够获得hasAudio和hasVideo的实际值,并忽略了用于设置这些变量的flvHeaders.flags .

    自定义FlvExtractor解决方法,看起来比自定义MediaSource / MediaPeriod更干净,因为我们将根据需要创建那些许多轨道,因为我们正在设置正确的hasVideo / hasAudio值 .

相关问题