纹理查看视频和位图显示

时间:2015-03-12 11:59:57

标签: android android-canvas android-bitmap textureview

我有一个显示位图(占位符图像)的TextureView,当用户加载视频时,textureView应该显示视频。

我设法在纹理视图中播放视频并在纹理视图中显示位图,但是当按顺序完成时,我只得到一个黑屏。

在我的onSurfaceTextureAvailable方法中,我在曲面视图上绘制一个位图,如下所示:

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
    Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_add_clip);
    Canvas canvas = lockCanvas();
    canvas.drawBitmap(bm, (width/2)-(bm.getWidth()/2), (height/2)-(bm.getHeight()/2), null);
    unlockCanvasAndPost(canvas);
}

当用户从其图库中选择视频时,我将Uri加载到媒体播放器中并将曲面设置为媒体播放器。但是仍然显示位图。我试图通过清除画布来删除位图,它确实删除了位图,但纹理视图只是黑色,并且也不会显示视频。

public void setMediaPlayer(MediaPlayer mediaPlayer) {
    // Canvas canvas = lockCanvas();
    // canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    // unlockCanvasAndPost(canvas);

    Surface s = new Surface(getSurfaceTexture());
    mMediaPlayer = mediaPlayer;
    mMediaPlayer.setSurface(s);
    mMediaPlayer.setOnPreparedListener(this);
}

有些东西告诉我,用于显示视频的表面视图位于我在TextureAvailble上绘制的位图的后面。当我尝试清除画布时,我也清除了媒体播放器想要使用的表面。任何解决方案?

2 个答案:

答案 0 :(得分:5)

你的方法不起作用。

Surface是具有生产者 - 消费者关系的缓冲区队列。一次只能有一个生产者,你有两个生产者(Canvas和MediaPlayer)。当你致电mMediaPlayer.setSurface()时,它会附加MediaPlayer;当你致电lockCanvas()时,它会附加Canvas。你需要先分离一个,然后才能连接另一个。

(检查你的logcat输出 - 那里可能有一些"已经连接了#34;那里的投诉。)

问题是,虽然您应该能够分离MediaPlayer,但您无法分离Canvas。没有电话可以做到这一点。这是API中的一个不幸的工件。 (通过4.4&#34确认; KitKat",我怀疑它自那以后发生了变化。)

您有几个选择:

  1. 使用GLES绘制位图。您可以在Grafika PlayMovieSurface activity中看到一个示例 - 请参阅clearSurface()方法,该方法只会清除屏幕。使用GLES,您可以在表面上进行连接和分离。
  2. 将您的位图转换为单帧视频并通过MediaPlayer播放。
  3. 使用FrameLayout将ImageView放在视频窗口的顶部。在视频播放时隐藏ImageView。
  4. 我应该补充一点,我实际上并没有尝试从Surface分离MediaPlayer。较低级别的MediaCodec以这种方式工作,如Grafika播放器所示,所以我假设MediaPlayer也会干净利落地分离。但是,对于你的用例,#3可能是最简单的解决方案,并且不需要附加/分离体操。

答案 1 :(得分:0)

您可以使用opengl es将位图绘制到显示表面,然后以相同的方式绘制视频帧。我这样做了,效果很好。