1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2012 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw.decoder; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.annotation.TargetApi; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.SurfaceTexture; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.SurfaceTexture.OnFrameAvailableListener; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.media.MediaCodec; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.media.MediaCodec.BufferInfo; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.media.MediaFormat; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.Surface; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameImage2D; 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.ImageShader; 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.TextureSource; 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer; 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link TrackDecoder} that decodes a video track and renders the frames onto a 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link SurfaceTexture}. 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * This implementation uses the GPU for image operations such as copying 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * and color-space conversion. 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks@TargetApi(16) 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class GpuVideoTrackDecoder extends VideoTrackDecoder { 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Identity fragment shader for external textures. 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final String COPY_FRAGMENT_SHADER = 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "#extension GL_OES_EGL_image_external : require\n" + 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "precision mediump float;\n" + 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "uniform samplerExternalOES tex_sampler_0;\n" + 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "varying vec2 v_texcoord;\n" + 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "void main() {\n" + 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks " gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n" + 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "}\n"; 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final TextureSource mTextureSource; 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final SurfaceTexture mSurfaceTexture; // Access guarded by mFrameMonitor. 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final float[] mTransformMatrix; 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final int mOutputWidth; 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final int mOutputHeight; 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private ImageShader mImageShader; 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private long mCurrentPresentationTimeUs; 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GpuVideoTrackDecoder( 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int trackIndex, MediaFormat format, Listener listener) { 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks super(trackIndex, format, listener); 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Create a surface texture to be used by the video track decoder. 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTextureSource = TextureSource.newExternalTexture(); 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture = new SurfaceTexture(mTextureSource.getTextureId()); 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.detachFromGLContext(); 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.setOnFrameAvailableListener(new OnFrameAvailableListener() { 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onFrameAvailable(SurfaceTexture surfaceTexture) { 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks markFrameAvailable(); 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mOutputWidth = format.getInteger(MediaFormat.KEY_WIDTH); 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mOutputHeight = format.getInteger(MediaFormat.KEY_HEIGHT); 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTransformMatrix = new float[16]; 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected MediaCodec initMediaCodec(MediaFormat format) { 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Surface surface = new Surface(mSurfaceTexture); 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks MediaCodec mediaCodec = MediaCodec.createDecoderByType( 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks format.getString(MediaFormat.KEY_MIME)); 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mediaCodec.configure(format, surface, null, 0); 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks surface.release(); 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mediaCodec; 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected boolean onDataAvailable( 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks MediaCodec codec, ByteBuffer[] buffers, int bufferIndex, BufferInfo info) { 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks boolean textureAvailable = waitForFrameGrab(); 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCurrentPresentationTimeUs = info.presentationTimeUs; 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Only render the next frame if we weren't interrupted. 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks codec.releaseOutputBuffer(bufferIndex, textureAvailable); 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (textureAvailable) { 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (updateTexture()) { 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks notifyListener(); 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return false; 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Waits for the texture's {@link OnFrameAvailableListener} to be notified and then updates 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the internal {@link SurfaceTexture}. 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private boolean updateTexture() { 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Wait for the frame we just released to appear in the texture. 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mFrameMonitor) { 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks try { 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks while (!mFrameAvailable) { 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFrameMonitor.wait(); 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.attachToGLContext(mTextureSource.getTextureId()); 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.updateTexImage(); 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.detachFromGLContext(); 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return true; 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } catch (InterruptedException e) { 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return false; 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void copyFrameDataTo(FrameImage2D outputVideoFrame, int rotation) { 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks TextureSource targetTexture = TextureSource.newExternalTexture(); 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.attachToGLContext(targetTexture.getTextureId()); 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.getTransformMatrix(mTransformMatrix); 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ImageShader imageShader = getImageShader(); 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks imageShader.setSourceTransform(mTransformMatrix); 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int outputWidth = mOutputWidth; 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int outputHeight = mOutputHeight; 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (rotation != 0) { 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float[] targetCoords = getRotationCoords(rotation); 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks imageShader.setTargetCoords(targetCoords); 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (needSwapDimension(rotation)) { 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputWidth = mOutputHeight; 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputHeight = mOutputWidth; 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputVideoFrame.resize(new int[] { outputWidth, outputHeight }); 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks imageShader.process( 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks targetTexture, 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputVideoFrame.lockRenderTarget(), 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputWidth, 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputHeight); 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputVideoFrame.setTimestamp(mCurrentPresentationTimeUs * 1000); 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outputVideoFrame.unlock(); 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks targetTexture.release(); 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.detachFromGLContext(); 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void release() { 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks super.release(); 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mFrameMonitor) { 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTextureSource.release(); 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSurfaceTexture.release(); 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /* 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * This method has to be called on the MFF processing thread. 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private ImageShader getImageShader() { 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mImageShader == null) { 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mImageShader = new ImageShader(COPY_FRAGMENT_SHADER); 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mImageShader.setTargetRect(0f, 1f, 1f, -1f); 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mImageShader; 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Get the quad coords for rotation. 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param rotation applied to the frame, value is one of 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {ROTATE_NONE, ROTATE_90_RIGHT, ROTATE_180, ROTATE_90_LEFT} 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return coords the calculated quad coords for the given rotation 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static float[] getRotationCoords(int rotation) { 196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch(rotation) { 197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case MediaDecoder.ROTATE_90_RIGHT: 198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new float[] { 0f, 0f, 0f, 1f, 1f, 0f, 1f, 1f }; 199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case MediaDecoder.ROTATE_180: 200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new float[] { 1f, 0f, 0f, 0f, 1f, 1f, 0f, 1f }; 201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case MediaDecoder.ROTATE_90_LEFT: 202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new float[] { 1f, 1f, 1f, 0f, 0f, 1f, 0f, 0f }; 203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case MediaDecoder.ROTATE_NONE: 204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new float[] { 0f, 1f, 1f, 1f, 0f, 0f, 1f, 0f }; 205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks default: 206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unsupported rotation angle."); 207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 211