1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.exoplayer2.transformerdemo; 17 18 import android.content.Context; 19 import android.graphics.Matrix; 20 import com.google.android.exoplayer2.C; 21 import com.google.android.exoplayer2.transformer.AdvancedFrameProcessor; 22 import com.google.android.exoplayer2.transformer.GlFrameProcessor; 23 import com.google.android.exoplayer2.util.Util; 24 25 /** 26 * Factory for {@link GlFrameProcessor GlFrameProcessors} that create video effects by applying 27 * transformation matrices to the individual video frames using {@link AdvancedFrameProcessor}. 28 */ 29 /* package */ final class AdvancedFrameProcessorFactory { 30 /** 31 * Returns a {@link GlFrameProcessor} that rescales the frames over the first {@value 32 * #ZOOM_DURATION_SECONDS} seconds, such that the rectangle filled with the input frame increases 33 * linearly in size from a single point to filling the full output frame. 34 */ createZoomInTransitionFrameProcessor(Context context)35 public static GlFrameProcessor createZoomInTransitionFrameProcessor(Context context) { 36 return new AdvancedFrameProcessor( 37 context, 38 /* matrixProvider= */ AdvancedFrameProcessorFactory::calculateZoomInTransitionMatrix); 39 } 40 41 /** 42 * Returns a {@link GlFrameProcessor} that crops frames to a rectangle that moves on an ellipse. 43 */ createDizzyCropFrameProcessor(Context context)44 public static GlFrameProcessor createDizzyCropFrameProcessor(Context context) { 45 return new AdvancedFrameProcessor( 46 context, /* matrixProvider= */ AdvancedFrameProcessorFactory::calculateDizzyCropMatrix); 47 } 48 49 /** 50 * Returns a {@link GlFrameProcessor} that rotates a frame in 3D around the y-axis and applies 51 * perspective projection to 2D. 52 */ createSpin3dFrameProcessor(Context context)53 public static GlFrameProcessor createSpin3dFrameProcessor(Context context) { 54 return new AdvancedFrameProcessor( 55 context, /* matrixProvider= */ AdvancedFrameProcessorFactory::calculate3dSpinMatrix); 56 } 57 58 private static final float ZOOM_DURATION_SECONDS = 2f; 59 private static final float DIZZY_CROP_ROTATION_PERIOD_US = 1_500_000f; 60 calculateZoomInTransitionMatrix(long presentationTimeUs)61 private static Matrix calculateZoomInTransitionMatrix(long presentationTimeUs) { 62 Matrix transformationMatrix = new Matrix(); 63 float scale = Math.min(1, presentationTimeUs / (C.MICROS_PER_SECOND * ZOOM_DURATION_SECONDS)); 64 transformationMatrix.postScale(/* sx= */ scale, /* sy= */ scale); 65 return transformationMatrix; 66 } 67 calculateDizzyCropMatrix(long presentationTimeUs)68 private static android.graphics.Matrix calculateDizzyCropMatrix(long presentationTimeUs) { 69 double theta = presentationTimeUs * 2 * Math.PI / DIZZY_CROP_ROTATION_PERIOD_US; 70 float centerX = 0.5f * (float) Math.cos(theta); 71 float centerY = 0.5f * (float) Math.sin(theta); 72 android.graphics.Matrix transformationMatrix = new android.graphics.Matrix(); 73 transformationMatrix.postTranslate(/* dx= */ centerX, /* dy= */ centerY); 74 transformationMatrix.postScale(/* sx= */ 2f, /* sy= */ 2f); 75 return transformationMatrix; 76 } 77 calculate3dSpinMatrix(long presentationTimeUs)78 private static float[] calculate3dSpinMatrix(long presentationTimeUs) { 79 float[] transformationMatrix = new float[16]; 80 android.opengl.Matrix.frustumM( 81 transformationMatrix, 82 /* offset= */ 0, 83 /* left= */ -1f, 84 /* right= */ 1f, 85 /* bottom= */ -1f, 86 /* top= */ 1f, 87 /* near= */ 3f, 88 /* far= */ 5f); 89 android.opengl.Matrix.translateM( 90 transformationMatrix, /* mOffset= */ 0, /* x= */ 0f, /* y= */ 0f, /* z= */ -4f); 91 float theta = Util.usToMs(presentationTimeUs) / 10f; 92 android.opengl.Matrix.rotateM( 93 transformationMatrix, /* mOffset= */ 0, theta, /* x= */ 0f, /* y= */ 1f, /* z= */ 0f); 94 return transformationMatrix; 95 } 96 } 97