TextureView實現視頻播放

TextureView在4.0(API level 14)中引入。它可以將內容流直接投影到View中,可以用於實現Live preview等功能。和SurfaceView不同,它不會在WMS中單獨創建窗口,而是作爲View hierachy中的一個普通View,因此可以和其它普通View一樣進行移動,旋轉,縮放,動畫等變化。值得注意的是TextureView必須在硬件加速的窗口中。它顯示的內容流數據可以來自App進程或是遠端進程。從類圖中可以看到,TextureView繼承自View,它與其它的View一樣在View hierachy中管理與繪製。TextureView重載了draw()方法,其中主要把SurfaceTexture中收到的圖像數據作爲紋理更新到對應的HardwareLayer中。SurfaceTexture.OnFrameAvailableListener用於通知TextureView內容流有新圖像到來。SurfaceTextureListener接口用於讓TextureView的使用者知道SurfaceTexture已準備好,這樣就可以把SurfaceTexture交給相應的內容源。Surface爲BufferQueue的Producer接口實現類,使生產者可以通過它的軟件或硬件渲染接口爲SurfaceTexture內部的BufferQueue提供graphic buffer。

結構類圖如下

這裏不囉嗦解釋,具體看官方API文檔

Textureview API

MainView

自定義一個view,注意TextureView中的draw方法和onDraw方法都是被定義成final的,不能被子類覆蓋。所以必須可以通過實現TextureView.SurfaceTextureListener 接口,然後重寫onSurfaceTextureAvailable方法,把你想添加的功能加到這個方法裏即可,這裏加入播放視頻的功能

package com.test.xingliu.texturesample;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.view.Surface;
import android.view.TextureView;

import java.io.IOException;

/**
 * Created by Xingliu on 2016/12/5.
 */
public class MainView extends TextureView implements TextureView.SurfaceTextureListener {
    private static final String FILE_NAME = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov";

    private MediaPlayer mMediaPlayer;


    public MainView(Context context) {
        super(context);
        initView();

    }

    public void stopPlay() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }

    }

    private void initView() {
        setSurfaceTextureListener(this);

    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {

        Surface surface = new Surface(surfaceTexture);
        try {

            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setDataSource(FILE_NAME);
            mMediaPlayer.setSurface(surface);
            mMediaPlayer.prepareAsync();
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mMediaPlayer.start();
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
    }
}

對應的activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="176dp"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <com.test.xingliu.texturesample.MainView
        android:id="@+id/textureView"
        android:layout_width="match_parent"
        android:layout_height="176dp"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin" />


</LinearLayout>

MainActivity

package com.test.xingliu.texturesample;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MainView(this));
    }

    @Override
    protected void onDestroy() {
        new MainView(this).stopPlay();
        super.onDestroy();
    }


}

mainifest文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.xingliu.texturesample">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

效果圖如下,由於資源是網絡上的,需要聯網才能播放

這裏寫圖片描述

需要注意到是在硬件加速的情況下,TextureView是用GPU渲染的,軟件上的Canvas是不能進行處理的,而TextureView必須在硬件加速的窗口中,可以調用lockcanvas()方法來獲取canvas

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章