7

我正在使用 Exoplayer 在 android 中连续播放视频作为播放列表。当我播放低质量的 mp4 视频时,它可以正常工作,但是当我在播放列表中播放一两个视频后尝试播放更高质量的 mp4 视频时,屏幕不显示任何内容,并且日志给出以下异常

com.google.android.exoplayer.MediaCodecTrackRenderer$DecoderInitializationException: 解码器初始化失败: OMX.amlogic.avc.decoder.awesome, MediaFormat(video/avc, 198826, 1920, 1080, -1.0, -1, -1, -1, -1, -1)

即使我第一次播放相同的高质量视频,然后第二次抛出此异常。当视频大小超过 80mb 时,会抛出此异常。是缓冲区大小问题吗?有人可以指导我吗?非常感谢您

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adplayertexture);   
    AdplayerTexture=(TextureView)findViewById(R.id.AdPlayerTexture);
    AdplayerTexture.setBackgroundColor(Color.BLACK);
        AdplayerTexture.setSurfaceTextureListener(this);
  }
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
    int height) {

 AdPlayerSurface = new Surface( surface); 
 playMedia(AdPlayerSurface);
}


private void playMedia(Surface surface){
mediaplayer=new ExoPlayer();
mediaplayer.play(this,Videopathlist[CurrentVideoIndex],surface;
 mediaplayer.addListener(this);   
   }

@Override
public void onStateChanged(boolean playWhenReady, int playbackState) {

if (playbackState == ExoPlayer.STATE_ENDED) {
//releasing the resources   
    mediaplayer.DestroyPlayer();
AdPlayerSurface.release();

AdPlayerSurface=new Surface(AdplayerTexture.getSurfaceTexture());
    CurrentVideoIndex++;
playMedia(AdPlayerSurface);
}

这是 root2mediaplayer 类中的函数 play()

public void playMedia(Activity playerActivity,String mediapath,final long Position,Surface mediasurface){
    String Systemroot = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
try{
    File myFile=new File(Systemroot + java.io.File.separator + "Videos"
            + java.io.File.separator
            + mediapath);
    Uri uri = Uri.fromFile(myFile);
    final int numRenderers = 2;

    SampleSource sampleSource = 
            new FrameworkSampleSource(playerActivity, uri, /* headers */ null, numRenderers);

    // Build the track renderers
    TrackRenderer    videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);

    TrackRenderer    audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);

    // Build the ExoPlayer and start playback
    MoviePlayer = ExoPlayer.Factory.newInstance(numRenderers);
    MoviePlayer.prepare(videoRenderer, audioRenderer);

    MoviePlayer.addListener(this);
    // Pass the surface to the video renderer.
    MoviePlayer.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, mediasurface);

            MoviePlayer.seekTo(Position);
            MoviePlayer.setPlayWhenReady(true);
}catch(Exception e){

e.printStackTrace();
FileLog("exception in mediaplayer");
}
4

2 回答 2

7

在不查看完整代码且不知道您看到此问题的设备/平台的情况下(尽管从您的问题来看,它看起来像 AMLOGIC 的 ah/w 平台),我只能猜测您可能没有在播放器中释放 MediaCodec 资源当播放结束和/或您切换播放新视频时。

MediaCodec 在https://github.com/google/ExoPlayer/blob/master/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java的 releaseCodec() API 中发布。

当您停止播放第一个视频并开始播放播放列表中的下一个视频时,您可能需要检查是否确实调用了它。

通常,所有高端移动平台都具有基于硬件的解码器,这些解码器使用系统上有限的专用视频内存(只能由硬件解码器访问)来解码帧。在某些平台上,如果系统中的某个其他应用程序(或同一个应用程序)创建了另一个基于硬件的解码器的另一个实例,并且在进入后台时没有释放它(在 Activity生命周期语言,onStop 等)。

此外,如果解码器被销毁时没有释放专用显存,您将在几个视频播放会话中由于泄漏而耗尽平台上可用的有限显存。

当您创建和销毁 MediaCodec 实例(或者在您的情况下,停止并开始播放播放列表中的下一个视频)时,请注意完整的平台 adb 日志。这可能会给你一些线索。

希望我的高级建议对您解决问题有所帮助。祝你好运!!!。

于 2015-04-18T20:41:45.447 回答
0

您应该能够重用相同的 ExoPlayer 和 Surface 实例,而不是完全拆除 ExoPlayer 和 Surface。

只需停止 ExoPlayer,创建新的 FrameworkSampleSource/MediaCodec{Audio,Video}TrackRender 对象,然后prepare再次调用。

新代码将执行以下操作:

  • 电影播放器​​.stop()
  • MoviePlayer.seekTo(0)
  • 新的 FrameworkSampleSource 和 MediaCodec{Audio,Video}TrackRenders
  • MoviePlayer.prepare(newVideoRenderer, newAudioRenderer)

请参阅停止方法的注释:

/** * 停止播放。如果意图 * 是暂停播放,请使用 {@code setPlayWhenReady(false)} 而不是此方法。*

* 调用此方法将导致播放状态转换为 * {@link ExoPlayer#STATE_IDLE}。播放器实例仍然可以使用,如果不再需要播放器,仍必须在播放器上调用 * {@link ExoPlayer#release()}。*

* 调用此方法不会重置播放位置。如果此播放器实例将用于 * 从其开始播放另一个视频,则应在停止 * 播放器之后并为下一个视频准备之前调用 {@code seekTo(0)}。*/

于 2015-04-25T07:24:33.433 回答