Android最简单的视频播放器之GLSurfaceView+OpenGL ES+MediaCodec硬件解码实现(四)


一、概述

  案例:使用硬件解码MediaCodec+OpenGL ES来实现一个视频播放器。

  源码下载

  重点概要:

    1.音视频文件提取器MediaExtractor

    2.音视频硬件解码API MediaCodec

    3.视频渲染使用OpenGL ES、音频渲染使用AudioTrack封装的AudioPlayer

    4.封装GLSurfaceView并将(1)+(2)+(3)+(4)桥接起来实现简单的视频播放器

    

 

 

二、重要代码实例讲解

  桥接(一)、(二)、(三)的代码让整个播放器串联起来。

  1.封装GLSurfaceView,并初始化Render

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;

/**
 * @ProjectName: TheSimpllestplayer
 * @Package: com.yw.thesimpllestplayer.renderview
 * @ClassName: RenderGLSurfaceView
 * @Description: 封装GLSurfaceView
 * @Author: wei.yang
 * @CreateDate: 2021/11/6 16:30
 * @UpdateUser: 更新者:wei.yang
 * @UpdateDate: 2021/11/6 16:30
 * @UpdateRemark: 更新说明:
 * @Version: 1.0
 */
public class RenderGLSurfaceView extends GLSurfaceView {
    private VideoDrawer videoDrawer;
    private VideoRender videoRender;

    public RenderGLSurfaceView(Context context) {
        super(context);
        initRender();
    }

    public RenderGLSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initRender();
    }

    /**
     * 初始化渲染器
     */
    private void initRender() {
        setEGLContextClientVersion(2);
        //初始化绘制器
        videoDrawer = new VideoDrawer();
        videoDrawer.setVideoSize(1080, 1920);
        //初始化渲染器
        videoRender = new VideoRender();
        videoRender.addDrawer(videoDrawer);
        setRenderer(videoRender);
    }

    public VideoDrawer getVideoDrawer() {
        return videoDrawer;
    }

    public VideoRender getVideoRender() {
        return videoRender;
    }
}

 

  2.具体的播放器页面

  

package com.yw.thesimpllestplayer.ui;

import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Surface;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.yw.thesimpllestplayer.BaseActivity;
import com.yw.thesimpllestplayer.R;
import com.yw.thesimpllestplayer.mediaplayer.decoder.AudioDecoder;
import com.yw.thesimpllestplayer.mediaplayer.decoder.VideoDecoder;
import com.yw.thesimpllestplayer.renderview.RenderGLSurfaceView;
import com.yw.thesimpllestplayer.renderview.VideoDrawer;
import com.yw.thesimpllestplayer.renderview.VideoRender;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ProjectName: TheSimpllestplayer
 * @Package: com.yw.thesimpllestplayer.ui
 * @ClassName: SimplePlayerActivity
 * @Description: 简单的视频播放器
 * @Author: wei.yang
 * @CreateDate: 2021/11/6 15:59
 * @UpdateUser: 更新者:wei.yang
 * @UpdateDate: 2021/11/6 15:59
 * @UpdateRemark: 更新说明:
 * @Version: 1.0
 */
public class SimplePlayerActivity extends BaseActivity {
    private RenderGLSurfaceView surfaceView;
    private String videoPath = "/storage/emulated/0/DCIM/Camera/share_06909c9c4e74c23ff62eba7701038719.mp4";

    private VideoDecoder videoDecoder;
    private AudioDecoder audioDecoder;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_player);
        initViews();
    }

    private void initViews() {
        surfaceView = findViewById(R.id.surfaceView);
        findViewById(R.id.btnChoiceVideo).setOnClickListener(v -> {
            choiceVideo();
        });
        findViewById(R.id.btnPlay).setOnClickListener(v -> {
            if (videoPath != null && videoDecoder != null && audioDecoder != null) {
                //开始播放
                videoDecoder.goOn();
                audioDecoder.goOn();
            } else {
                Toast.makeText(SimplePlayerActivity.this, "请先初始化播放器", Toast.LENGTH_SHORT).show();
            }
        });
        findViewById(R.id.btnStop).setOnClickListener(v -> {
            if (videoPath != null && videoDecoder != null && audioDecoder != null) {
                //暂停播放
                videoDecoder.pause();
                audioDecoder.pause();
            } else {
                Toast.makeText(SimplePlayerActivity.this, "请先初始化播放器", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void videoPathCallback(String videoPath) {
        this.videoPath = videoPath;
        initPlayer();
    }


    private void initPlayer() {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        videoDecoder = new VideoDecoder(videoPath, new Surface(surfaceView.getVideoDrawer().getSurfaceTexture()));
        threadPool.execute(videoDecoder);

        audioDecoder = new AudioDecoder(videoPath);
        threadPool.execute(audioDecoder);

        //开始播放
//        videoDecoder.goOn();
//        audioDecoder.goOn();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (videoDecoder != null && audioDecoder != null) {
            videoDecoder.goOn();
            audioDecoder.goOn();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (videoDecoder != null && audioDecoder != null) {
            videoDecoder.pause();
            audioDecoder.pause();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (videoDecoder != null) {
            videoDecoder.stop();
        }
        if (audioDecoder != null) {
            audioDecoder.stop();
        }
    }
}

 

三、总结

  1.SimplePlayerActivity.java类可以选择视频播放路径,并可以执行开始播放、暂停播放以及按返回键的时候销毁播放器

  2.RenderGLSurfaceView.java封装了VideoRender以及VideoDrawer

  3.如果视频播放路径不为空则初始化音视频编解码器VideoDecoder及AudioDecoder


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM