日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android视频裁剪适配,类似于ImageView的scaleType=centerCrop

發布時間:2023/12/9 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android视频裁剪适配,类似于ImageView的scaleType=centerCrop 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們經常會遇到播放視頻的需求,最近幾年全面屏、劉海屏的出現使得屏幕的比例各種各樣,下面是視頻適配各種屏幕比例,類似于ImageView的scaleType=“centerCrop”。

public class ClipVideoView extends GLSurfaceView {/*** MediaPlayer*/private MediaPlayer mediaPlayer;/*** 視頻路徑*/private String videoPath;/*** OnPreparedListener*/private MediaPlayer.OnPreparedListener mOnPreparedListener;/*** 構造函數*/public ClipVideoView(Context context) {this(context, null);}/*** 構造函數*/public ClipVideoView(Context context, AttributeSet attrs) {super(context, attrs);init();}/*** 初始化*/private void init() {Logger.d("ClipVideoView init");setEGLContextClientVersion(2);setPreserveEGLContextOnPause(true);setRenderer(new VideoRenderer(getContext()));setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);}/*** 設置視頻播放監聽器*/public void setPreparedListener(MediaPlayer.OnPreparedListener onPreparedListener) {mOnPreparedListener = onPreparedListener;}/*** 播放視頻*/public void start(String path) {if (mediaPlayer == null) {Logger.d("start video mediaPlayer is null,path:" + path);videoPath = path;return;}try {Logger.d("start video path:" + path);mediaPlayer.reset();mediaPlayer.setLooping(true);mediaPlayer.setDataSource(path);mediaPlayer.prepare();mediaPlayer.start();if (mOnPreparedListener != null) {mOnPreparedListener.onPrepared(null);}} catch (Exception e) {Logger.e("play video error:" + e + " video path:" + path);}}@Overridepublic void onResume() {super.onResume();if (mediaPlayer != null && !"".equals(videoPath)) {Logger.d("video restart");mediaPlayer.start();}}@Overridepublic void onPause() {super.onPause();if (mediaPlayer != null && mediaPlayer.isPlaying()) {Logger.d("video pause");mediaPlayer.pause();}}/*** 銷毀*/public void release() {if (mediaPlayer != null) {Logger.d("video release");mediaPlayer.stop();mediaPlayer.release();mediaPlayer = null;}}private class VideoRenderer implements Renderer {/*** TAG*/private static final String TAG = "VideoRenderer";/*** context*/private Context context;/*** 紋理id*/int textureId = -1;/*** 坐標點*/private final int COORDS_PER_VERTEX = 3;/*** 坐標點*/private final int TEXCOORDS_PER_VERTEX = 2;/*** float size*/private static final int FLOAT_SIZE = 4;/*** 定點坐標*/private final float[] QUAD_COORDS = {-1.0f, 1.0f, 0.0f, // top left-1.0f, -1.0f, 0.0f, // bottom left1.0f, -1.0f, 0.0f, // bottom right1.0f, 1.0f, 0.0f // top right};/*** 紋理坐標*/private float[] quadTexCoords = {0.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f};/*** index*/private final short[] index = {0, 1, 2, 0, 2, 3};/*** 頂點*/private FloatBuffer quadVertices;/*** 紋理*/private FloatBuffer quadTexCoord;/*** 索引*/private ShortBuffer shortBuffer;/*** program*/private int quadProgram = -1;/*** 頂點參數索引*/private int quadPositionParam = -1;/*** 紋理參數索引*/private int quadTexCoordParam = -1;/*** oes*/private int uTextureSamplerLocation = -1;/*** 是否有新的一針視頻*/private boolean updateSurface = false;/*** SurfaceTexture*/private SurfaceTexture surfaceTexture;/*** 鎖*/private Object lock = new Object();/*** 構造函數*/public VideoRenderer(Context context) {this.context = context;}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {Logger.d("onSurfaceCreated");int[] textures = new int[1];GLES20.glGenTextures(1, textures, 0);textureId = textures[0];int textureTarget = GLES11Ext.GL_TEXTURE_EXTERNAL_OES;GLES20.glBindTexture(textureTarget, textureId);GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);int vertexShader =ShaderUtil.loadGLShader(TAG, context, GLES20.GL_VERTEX_SHADER, R.raw.base_vertex);int fragmentShader =ShaderUtil.loadGLShader(TAG, context, GLES20.GL_FRAGMENT_SHADER, R.raw.base_fragment_oes);quadProgram = GLES20.glCreateProgram();GLES20.glAttachShader(quadProgram, vertexShader);GLES20.glAttachShader(quadProgram, fragmentShader);GLES20.glLinkProgram(quadProgram);GLES20.glUseProgram(quadProgram);ShaderUtil.checkGLError(TAG, "Program creation");quadPositionParam = GLES20.glGetAttribLocation(quadProgram, "a_Position");quadTexCoordParam = GLES20.glGetAttribLocation(quadProgram, "a_TexCoordinate");uTextureSamplerLocation = GLES20.glGetUniformLocation(quadProgram, "u_Texture");ShaderUtil.checkGLError(TAG, "Program parameters");mediaPlayer = new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setLooping(true);surfaceTexture = new SurfaceTexture(textureId);Surface surface = new Surface(surfaceTexture);surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {@Overridepublic void onFrameAvailable(SurfaceTexture surfaceTexture) {synchronized (lock) {updateSurface = true;}}});mediaPlayer.setSurface(surface);if (!"".equals(videoPath) && !mediaPlayer.isPlaying()) {start(videoPath);}}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {Logger.d("onSurfaceChanged");GLES20.glViewport(0, 0, width, height);GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);quadVertices = ByteBuffer.allocateDirect(QUAD_COORDS.length * FLOAT_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();quadVertices.put(QUAD_COORDS);quadVertices.position(0);float videoRatio = 16.0F / 9;Log.d(TAG, "width:" + width + " height:" + height);float viewRatio = ((float) width) / height;Log.d(TAG, "videoRatio:" + videoRatio + " viewRatio:" + viewRatio);if (viewRatio < videoRatio) {float s = (1 - (9 / 16.F * viewRatio)) / 2.0F;float[] texCoord = {0.0f + s, 1.0f,1.0f - s, 1.0f,1.0f - s, 0.0f,0.0f + s, 0.0f};Log.d(TAG, Arrays.toString(texCoord));quadTexCoord = ByteBuffer.allocateDirect(texCoord.length * FLOAT_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();quadTexCoord.put(texCoord);quadTexCoord.position(0);} else if (viewRatio > videoRatio) {float s = (1 - (16 / (9 * viewRatio))) / 2.0F;float[] texCoord = {0.0f, 1.0f - s,1.0f, 1.0f - s,1.0f, 0.0f + s,0.0f, 0.0f + s};Log.d(TAG, Arrays.toString(texCoord));quadTexCoord = ByteBuffer.allocateDirect(texCoord.length * FLOAT_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();quadTexCoord.put(texCoord);quadTexCoord.position(0);} else {quadTexCoord = ByteBuffer.allocateDirect(quadTexCoords.length * FLOAT_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();quadTexCoord.put(quadTexCoords);quadTexCoord.position(0);}shortBuffer = ByteBuffer.allocateDirect(index.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();shortBuffer.put(index);shortBuffer.position(0);}@Overridepublic void onDrawFrame(GL10 gl) {synchronized (lock) {if (updateSurface) {surfaceTexture.updateTexImage();updateSurface = false;}}GLES20.glUseProgram(quadProgram);// Set the vertex positions.quadVertices.position(0);GLES20.glEnableVertexAttribArray(quadPositionParam);GLES20.glVertexAttribPointer(quadPositionParam, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, quadVertices);// Set the texture coordinates.quadTexCoord.position(0);GLES20.glEnableVertexAttribArray(quadTexCoordParam);GLES20.glVertexAttribPointer(quadTexCoordParam, TEXCOORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, quadTexCoord);GLES20.glActiveTexture(GLES20.GL_TEXTURE0);GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);GLES20.glUniform1i(uTextureSamplerLocation, 0);GLES20.glDrawElements(GLES20.GL_TRIANGLES, index.length, GLES20.GL_UNSIGNED_SHORT, shortBuffer);// Disable vertex arraysGLES20.glDisableVertexAttribArray(quadPositionParam);GLES20.glDisableVertexAttribArray(quadTexCoordParam);}} }

base_vertex.glsl文件:

attribute vec4 a_Position; attribute vec2 a_TexCoordinate;varying vec2 v_TexCoord;void main() {v_TexCoord = a_TexCoordinate;gl_Position = a_Position; }

base_fragment.glsl文件:

#extension GL_OES_EGL_image_external : require precision mediump float;uniform samplerExternalOES u_Texture; varying vec2 v_TexCoord;void main() {gl_FragColor = texture2D(u_Texture, v_TexCoord); }

2個glsl文件放在:res/raw 目錄下:

ShareUtil:

/** Copyright 2017 Google Inc. All Rights Reserved.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/ package com.jd.lib.armart.arcore.arcore.rendering;import android.content.Context; import android.opengl.GLES20; import android.util.Log;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader;/*** des: shader 工具類* [@author]: mengqingdong* [@date]: 2019-08-14 09:52*/ public class ShaderUtil {/*** Converts a raw text file, saved as a resource, into an OpenGL ES shader.** @param type The type of shader we will be creating.* @param resId The resource ID of the raw text file about to be turned into a shader.* @return The shader object handler.*/public static int loadGLShader(String tag, Context context, int type, int resId) {String code = readRawTextFile(context, resId);int shader = GLES20.glCreateShader(type);GLES20.glShaderSource(shader, code);GLES20.glCompileShader(shader);// Get the compilation status.final int[] compileStatus = new int[1];GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);// If the compilation failed, delete the shader.if (compileStatus[0] == 0) {Log.e(tag, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shader));GLES20.glDeleteShader(shader);shader = 0;}if (shader == 0) {throw new RuntimeException("Error creating shader.");}return shader;}/*** Checks if we've had an error inside of OpenGL ES, and if so what that error is.** @param label Label to report in case of error.* @throws RuntimeException If an OpenGL error is detected.*/public static void checkGLError(String tag, String label) {int lastError = GLES20.GL_NO_ERROR;// Drain the queue of all errors.int error;while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {Log.e(tag, label + ": glError " + error);lastError = error;}if (lastError != GLES20.GL_NO_ERROR) {throw new RuntimeException(label + ": glError " + lastError);}}/*** Converts a raw text file into a string.** @param resId The resource ID of the raw text file about to be turned into a shader.* @return The context of the text file, or null in case of error.*/private static String readRawTextFile(Context context, int resId) {InputStream inputStream = context.getResources().openRawResource(resId);try {BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));StringBuilder sb = new StringBuilder();String line;while ((line = reader.readLine()) != null) {sb.append(line).append("\n");}reader.close();return sb.toString();} catch (IOException e) {e.printStackTrace();}return null;} }

同時在AndroidManifest.xml 文件中添加如下代碼:

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

視頻播放使用的是系統MediaPlayer,如果沒有包體大小的限制建議使用ijkplayer。

總結

以上是生活随笔為你收集整理的Android视频裁剪适配,类似于ImageView的scaleType=centerCrop的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美一区二区网站 | 国产人成一区二区三区影院 | 校园春色自拍偷拍 | 亚洲图片自拍偷拍区 | 国产成人一区在线观看 | www.久久婷婷 | 美女131爽爽爽做爰视频 | 天天射日日 | 久久精品国产av一区二区三区 | 中国黄色在线视频 | 亚洲国产日韩在线 | 亚洲系列第一页 | 欧美狠狠| 亚洲国产一二三 | sm在线观看 | 精品九九在线 | 骚色综合 | 五月天丁香 | 中文字幕高清在线 | 国产九色| 中文字幕乱码无码人妻系列蜜桃 | 中文字幕观看av | aaa一区二区 | 亚洲一区二区不卡在线观看 | 91在线日本 | 在线免费不卡视频 | 欧美激情999 | 日批毛片| www,av在线 | 在线观看亚洲免费视频 | 色欲久久久天天天精品综合网 | 中文字幕一区二区三区在线视频 | 日韩精品一区二区三区 | 调教少妇视频 | 黑人巨大精品一区二区在线 | 国语av | 亚洲A∨无码国产精品 | 性少妇videosexfre| 成年人在线观看 | 捆绑最紧bdsm视频 | 国产一av| 国产精品久久777777毛茸茸 | 欧美成人做爰大片免费看黄石 | 欧美视频在线不卡 | 亚洲色诱 | 99热这里只有精品66 | 免费黄色链接 | 国产成人精品一区二区在线观看 | mm131国产精品 | 黄色污网站在线观看 | 欧美三级黄色 | 可以免费看的黄色网址 | 影音先锋国产资源 | 在线观看精品国产 | 日韩欧美资源 | 亚洲一二三精品 | 夜夜爽天天干 | 欧美日韩视频在线播放 | 中文字幕在线观看高清 | 另类ts人妖一区二区三区 | 欧美日韩成人一区二区三区 | 三级艳丽杨钰莹三级 | 爱情岛论坛自拍亚洲品质极速最新章 | 123成人网| 欧美不卡一区 | 国产裸体永久免费视频网站 | 中文字幕va | 国产精品suv一区二区三区 | 新天堂网| 97超碰超碰 | 男女男精品视频网站 | 欧美在线一卡 | 特级西西人体 | 美女毛片在线 | 熟女俱乐部一区二区 | a天堂资源| 久久大尺度 | 三级视频网 | jav中文字幕| 欧美日韩在线视频免费观看 | 成人精品在线观看视频 | 成人短视频在线免费观看 | 亚洲毛片在线播放 | a√在线 | 久久久天天| 中文字幕国产剧情 | 久久精品一区二区免费播放 | 亚洲精品一品 | 成人亚洲玉足脚交系列 | 91免费片 | 亚洲综合站 | www.婷婷| 亚洲欧美一区二区三 | 欧美人妻少妇一区二区三区 | 美日韩免费视频 | 中文字幕一区二区三区不卡 | 日日夜夜操操 | 我要操婊 | 一级一片免费看 |