2015-03-12 2 views
1

У меня есть 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); 
} 

Когда пользователь выбирает видео из своей галереи я загрузить Ури в медиа-проигрывателе и установите поверхность в медиаплеер , Но растровое изображение все еще отображается. Я попытался удалить растровое изображение, очистив холст, и он удаляет растровое изображение, но затем текстурный вид просто черный и не покажет видео.

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. И когда я пытаюсь очистить полотно, я также очищаю поверхность, которую хочет использовать медиаплеер. Любые решения?

ответ

5

Ваш подход не будет работать.

Поверхность представляет собой очередь буферов с отношением между производителем и потребителем. За один раз может быть только один продюсер, и у вас есть два продюсера (Canvas и MediaPlayer). Когда вы вызываете mMediaPlayer.setSurface(), он подключает MediaPlayer; когда вы вызываете lockCanvas(), он прикрепляет холст. Вы должны отсоединить один, прежде чем присоединить другое.

(Проверьте выход LogCat. - там, наверное, какие-то «уже подключены» жалобы есть)

Проблема, в то время как вы должны быть в состоянии отделить MediaPlayer, вы не можете отделить Canvas. Просто нет звонка, который делает это. Это неудачный артефакт в API. (Подтверждено через 4.4 "KitKat", и я сомневаюсь, что изменилось с тех пор.)

У вас есть несколько вариантов:

  1. Draw растрового изображения с GLES вместо этого. Вы можете увидеть пример в Grafika's PlayMovieSurface activity - см. Метод clearSurface(), который просто очищает экран. С GLES вы можете прикрепляться и отсоединяться от поверхности.
  2. Преобразуйте растровое изображение в однокадровое видео и воспроизведите его через MediaPlayer.
  3. Поместите ImageView поверх видеоокна с помощью FrameLayout. Спрячьте ImageView во время воспроизведения видео.

Я должен добавить, что я фактически не пытался отсоединить MediaPlayer от поверхности. Этот MediaCodec более низкого уровня работает таким образом, как показывает игрок Grafika, поэтому я предполагаю, что MediaPlayer также будет отключен. Для вашего случая использования, однако, № 3, вероятно, является самым простым решением и не требует подключения/снятия гимнастики.

+0

Спасибо Fadden очень ясно. Я пошел на вариант 3, потому что это самый простой. Переход к варианту 1 или 2 только увеличивает сложность. – Charx

0

Вы можете использовать opengl es, чтобы нарисовать растровое изображение на поверхности дисплея, а затем нарисовать видеокадр тем же способом. Я сделал так, и все работает отлично.