• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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