TextureView+SurfaceTexture+OpenGL ES to play video (1)

Text/Zilei (author of Jianshu)
original link: http://www.jianshu.com/p/d3d3186eefcb
The copyright belongs to the author, please contact the author for authorization, and mark "author of Jianshu".

Recently, it has been found that there are endless video live broadcast applications, such as 233 mobile game live broadcast, Blue Whale live broadcast, Weibo, etc. Even Lao Luo, the great god of the android world, is also developing mobile game recording applications, and the technical content is quite high. Yes, I need to understand the UI rendering mechanism of the android system and a lot of low-level knowledge of the system, and I have recently been thinking about studying the UI rendering mechanism of android and using it as an entry to understand android.
Some time ago, I saw that Jay has entered the game circle and endorsed LOL. Emma made me feel a little more favorable towards LOL. It is also a relatively popular event for major game anchors to change jobs collectively, and the game circle is almost catching up with the entertainment circle. I heard that those well-known game anchors are all earning tens of millions of dollars in annual salary. I just want to say, I am a fool!

The subject

Well, before talking about the code implementation, let me talk about what the hell are TextureView, SurfaceTexture, and OpenGL ES, and how do I use these things to display a video.

TextureView, as the name suggests, is just a View control that inherits View. The explanation on the official website is as follows:
A TextureView can be used to display a content stream. Such a content stream can for instance be a video or an OpenGL scene. The content stream can come from the application's process as well as a remote process.
It can display a stream of content, such as a video stream, an OpenGL rendered scene, etc. These streams can be local program processes or remote process streams, which are a bit confusing. My understanding is that, for example, they can be local video streams or network video streams.
Note: TextureView uses a hardware accelerator to render, just like hard decoding and soft decoding of video, one relies on GPU decoding, and the other relies on CPU decoding.
So how to use this TextureView?
OK, SurfaceTexture is about to play now. From the naming of these two classes, we know that TextureView focuses on View, and SurfaceTexture focuses on Texture. Its official website explains:
Captures frames from an image stream as an OpenGL ES texture. The image stream may come from either camera preview or video decode.
That is to say, it can capture a frame of an image stream as an OpenGL texture or texture. This picture stream is mainly the preview from the camera or the decoding of the video. (I guess this feature shouldn't be used for many things).
At this point, the texture is also available, then OpenGL can also come out to work, it can bind the texture and draw it frame by frame on the TextureView, which forms the video image we see ( specifically about You can refer to SurfaceTexture and TextureView here .) Having
said that, it’s time to look at some code. Good code is like reading a literary novel. It’s so beautiful. It doesn’t mean that the code I wrote is beautiful, it’s just a pursuit. . . .

code

Start with the MainActivity main class:

public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener,
        MediaPlayer.OnPreparedListener{
    /**本地视频的路径*/
    public String videoPath = Environment.getExternalStorageDirectory().getPath()+"/aoa.mkv";
    private TextureView textureView;
    private MediaPlayer mediaPlayer;
    /**
    * 视频绘制前的配置就发生在这个对象所在类中.
    * 真正的绘制工作则在它的子类中VideoTextureSurfaceRenderer
    */
    private TextureSurfaceRenderer videoRenderer;
    private int surfaceWidth;
    private int surfaceHeight;
    private Surface surface;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textureView = (TextureView) findViewById(R.id.id_textureview);
        //注册一个SurfaceTexture,用于监听SurfaceTexure
        textureView.setSurfaceTextureListener(this);

    }
    /**
    * 播放视频的入口,当SurfaceTexure可得到时被调用
    */
    private void playVideo() {
        if (mediaPlayer == null) {
            videoRenderer = new VideoTextureSurfaceRenderer(this, textureView.getSurfaceTexture(), surfaceWidth, surfaceHeight);
            surface = new Surface(videoRenderer.getSurfaceTexture());
            initMediaPlayer();
        }
    }

    private void initMediaPlayer() {
        this.mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource(videoPath);
            mediaPlayer.setSurface(surface);
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.setLooping(true);
        } catch (IllegalArgumentException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (SecurityException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IllegalStateException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
    @Override
    public void onPrepared(MediaPlayer mp) {
        try {
            if (mp != null) {
                mp.start(); //视频开始播放了
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }


    @Override
    protected void onResume() {
        super.onResume();
        if (textureView.isAvailable()) {
            playVideo();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (videoRenderer != null) {
            videoRenderer.onPause();  //记得去停止视频的绘制线程
        }
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer =null;
        }
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        surfaceWidth = width;
        surfaceHeight = height;
        playVideo();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

}

This is the entry class of the program. I will not talk about how Mediaplayer plays the video source. There are actually many things in it. You can check it yourself. One thing I need to say is that MediaPlayer.setSurface(param)the parameters in it are generally paramSurfaceView.SurfaceHolder, and I use it directly here Surface( for Surface, please refer to here ), the difference between my video playback and other video playback is here. This article is temporarily written here, and the subsequent core drawing work will be written later when I have time. If there is any problem with the above, I hope you can give me more pointers, thank you very much!
Next articleTextureView+SurfaceTexture+OpenGL ES has been written to play video (2)

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326959546&siteId=291194637