14a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala/* 24a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * Copyright (C) 2011 The Android Open Source Project 34a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * 44a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); 54a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * you may not use this file except in compliance with the License. 64a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * You may obtain a copy of the License at 74a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * 84a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0 94a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * 104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * Unless required by applicable law or agreed to in writing, software 114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, 124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * See the License for the specific language governing permissions and 144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * limitations under the License. 154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala */ 164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalapackage android.filterpacks.videosrc; 194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.content.Context; 214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.content.res.AssetFileDescriptor; 224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.Filter; 234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.FilterContext; 244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.Frame; 254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.FrameFormat; 264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.FrameManager; 2721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.core.GenerateFieldPort; 2821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.core.GenerateFinalPort; 2921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.core.GLFrame; 304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.KeyValueMap; 314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.MutableFrameFormat; 324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.NativeFrame; 334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.Program; 344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.ShaderProgram; 3521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.format.ImageFormat; 364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.graphics.SurfaceTexture; 374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.media.MediaPlayer; 384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.os.ConditionVariable; 39855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvalaimport android.opengl.Matrix; 401ae8bcdf7dc3df7be3ca14b6f63d0009654fab69Jamie Gennisimport android.view.Surface; 414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.io.IOException; 434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.io.FileDescriptor; 444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.lang.IllegalArgumentException; 454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.util.List; 464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.util.Set; 474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.util.Log; 494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 50a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala/** 51a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala * @hide 52a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala */ 534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalapublic class MediaSource extends Filter { 544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** User-visible parameters */ 564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** The source URL for the media source. Can be an http: link to a remote 58855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala * resource, or a file: link to a local media file 59855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala */ 6021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFieldPort(name = "sourceUrl", hasDefault = true) 614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private String mSourceUrl = ""; 624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 632dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen /** An open asset file descriptor to a local media source. Default is null */ 6421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFieldPort(name = "sourceAsset", hasDefault = true) 659b393be2b4b7e70abe38237ba3eda3dc009d6230Eino-Ville Talvala private AssetFileDescriptor mSourceAsset = null; 664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 67855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala /** Whether the media source is a URL or an asset file descriptor. Defaults 68855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala * to false. 69855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala */ 70c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala @GenerateFieldPort(name = "sourceIsUrl", hasDefault = true) 71c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala private boolean mSelectedIsUrl = false; 72c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala 734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Whether the filter will always wait for a new video frame, or whether it 74855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala * will output an old frame again if a new frame isn't available. Defaults 75855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala * to true. 764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala */ 7721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFinalPort(name = "waitForNewFrame", hasDefault = true) 784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mWaitForNewFrame = true; 794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 80855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala /** Whether the media source should loop automatically or not. Defaults to 81855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala * true. 82855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala */ 8321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFieldPort(name = "loop", hasDefault = true) 844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mLooping = true; 854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 86855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala /** Volume control. Currently sound is piped directly to the speakers, so 87855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala * this defaults to mute. 88855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala */ 89c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala @GenerateFieldPort(name = "volume", hasDefault = true) 90c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala private float mVolume = 0.f; 912dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen 92855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala /** Orientation. This controls the output orientation of the video. Valid 93855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala * values are 0, 90, 180, 270 94855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala */ 95855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala @GenerateFieldPort(name = "orientation", hasDefault = true) 96855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala private int mOrientation = 0; 97855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer mMediaPlayer; 994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private GLFrame mMediaFrame; 1004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private SurfaceTexture mSurfaceTexture; 1014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private ShaderProgram mFrameExtractor; 1024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MutableFrameFormat mOutputFormat; 103855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala private int mWidth, mHeight; 1044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 10590397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala // Total timeouts will be PREP_TIMEOUT*PREP_TIMEOUT_REPEAT 10690397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala private static final int PREP_TIMEOUT = 100; // ms 107fa2124c46e4e6486465f6b85db7e6780eda46c3bEino-Ville Talvala private static final int PREP_TIMEOUT_REPEAT = 100; 10890397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala private static final int NEWFRAME_TIMEOUT = 100; //ms 10990397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala private static final int NEWFRAME_TIMEOUT_REPEAT = 10; 11090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala 111855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala // This is an identity shader; not using the default identity 112855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala // shader because reading from a SurfaceTexture requires the 113855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala // GL_OES_EGL_image_external extension. 1144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private final String mFrameShader = 1154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "#extension GL_OES_EGL_image_external : require\n" + 1164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "precision mediump float;\n" + 1174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "uniform samplerExternalOES tex_sampler_0;\n" + 1184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "varying vec2 v_texcoord;\n" + 1194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "void main() {\n" + 120855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala " gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n" + 1214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "}\n"; 1224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 123760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // The following transforms enable rotation of the decoded source. 124760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // These are multiplied with the transform obtained from the 125760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // SurfaceTexture to get the final transform to be set on the media source. 126760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // Currently, given a device orientation, the MediaSource rotates in such a way 127760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // that the source is displayed upright. A particular use case 128760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // is "Background Replacement" feature in the Camera app 129760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // where the MediaSource rotates the source to align with the camera feed and pass it 130760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // on to the backdropper filter. The backdropper only does the blending 131760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // and does not have to do any rotation 132760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // (except for mirroring in case of front camera). 133760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // TODO: Currently the rotations are spread over a bunch of stages in the 134760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // pipeline. A cleaner design 135760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // could be to cast away all the rotation in a separate filter or attach a transform 136760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi // to the frame so that MediaSource itself need not know about any rotation. 137855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala private static final float[] mSourceCoords_0 = { 1, 1, 0, 1, 138855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 0, 1, 0, 1, 139855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 1, 0, 0, 1, 140855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 0, 0, 0, 1 }; 141760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi private static final float[] mSourceCoords_270 = { 0, 1, 0, 1, 142855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 0, 0, 0, 1, 143855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 1, 1, 0, 1, 144855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 1, 0, 0, 1 }; 145855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala private static final float[] mSourceCoords_180 = { 0, 0, 0, 1, 146855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 1, 0, 0, 1, 147855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 0, 1, 0, 1, 148855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 1, 1, 0, 1 }; 149760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi private static final float[] mSourceCoords_90 = { 1, 0, 0, 1, 150855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 1, 1, 0, 1, 151855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 0, 0, 0, 1, 152855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 0, 1, 0, 1 }; 153855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 1544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mGotSize; 1554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mPrepared; 1564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mPlaying; 15790397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala private boolean mNewFrameAvailable; 158855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala private boolean mOrientationUpdated; 1591df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala private boolean mPaused; 160c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala private boolean mCompleted; 1614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1628dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala private final boolean mLogVerbose; 1634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final String TAG = "MediaSource"; 1644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public MediaSource(String name) { 1664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala super(name); 16790397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala mNewFrameAvailable = false; 1688dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala 1698dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE); 1704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 17321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void setupPorts() { 17421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn // Add input port 17521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn addOutputPort("video", ImageFormat.create(ImageFormat.COLORSPACE_RGBA, 17621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn FrameFormat.TARGET_GPU)); 1774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 17921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn private void createFormats() { 18021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn mOutputFormat = ImageFormat.create(ImageFormat.COLORSPACE_RGBA, 18121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn FrameFormat.TARGET_GPU); 1824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala protected void prepare(FilterContext context) { 1868dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Preparing MediaSource"); 1874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 188511360e61650864ea22a171159efe073c80d0cdbMarius Renn mFrameExtractor = new ShaderProgram(context, mFrameShader); 1894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // SurfaceTexture defines (0,0) to be bottom-left. The filter framework 1904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // defines (0,0) as top-left, so do the flip here. 1914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.setSourceRect(0, 1, 1, -1); 1924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 19321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn createFormats(); 1944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 19721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void open(FilterContext context) { 1982dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (mLogVerbose) { 1991cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala Log.v(TAG, "Opening MediaSource"); 2001cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala if (mSelectedIsUrl) { 2011cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala Log.v(TAG, "Current URL is " + mSourceUrl); 2021cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala } else { 2031cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala Log.v(TAG, "Current source is Asset!"); 2041cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala } 2052dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen } 2061cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala 2071cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala mMediaFrame = (GLFrame)context.getFrameManager().newBoundFrame( 2081cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala mOutputFormat, 2091cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala GLFrame.EXTERNAL_TEXTURE, 2101cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala 0); 2111cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala 2121cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala mSurfaceTexture = new SurfaceTexture(mMediaFrame.getTextureId()); 2131cfcfd55f22577bbc70cddb6137c286b8d3c8491Eino-Ville Talvala 2142dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (!setupMediaPlayer(mSelectedIsUrl)) { 2152dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen throw new RuntimeException("Error setting up MediaPlayer!"); 21621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } 2174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 22021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void process(FilterContext context) { 2216aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala // Note: process is synchronized by its caller in the Filter base class 2228dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Processing new frame"); 2234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 2254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Something went wrong in initialization or parameter updates 22621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new NullPointerException("Unexpected null media player!"); 2274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 229c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mCompleted) { 230c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala // Video playback is done, so close us down 231c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala closeOutputPort("video"); 232c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala return; 233c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala } 234c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala 2354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mPlaying) { 2366aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala int waitCount = 0; 23790397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Waiting for preparation to complete"); 2386aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala while (!mGotSize || !mPrepared) { 2396aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala try { 24090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala this.wait(PREP_TIMEOUT); 2416aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } catch (InterruptedException e) { 2426aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala // ignoring 2436aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 244c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mCompleted) { 245c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala // Video playback is done, so close us down 246c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala closeOutputPort("video"); 247c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala return; 248c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala } 2496aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala waitCount++; 25090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (waitCount == PREP_TIMEOUT_REPEAT) { 2516aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.release(); 25221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new RuntimeException("MediaPlayer timed out while preparing!"); 2534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 25590397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Starting playback"); 2564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.start(); 2574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2591df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // Use last frame if paused, unless just starting playback, in which case 2601df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // we want at least one valid frame before pausing 2611df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (!mPaused || !mPlaying) { 2621df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (mWaitForNewFrame) { 26390397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Waiting for new frame"); 26490397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala 26590397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala int waitCount = 0; 26690397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala while (!mNewFrameAvailable) { 26790397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (waitCount == NEWFRAME_TIMEOUT_REPEAT) { 26890397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mCompleted) { 26990397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala // Video playback is done, so close us down 27090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala closeOutputPort("video"); 27190397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala return; 27290397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala } else { 27390397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala throw new RuntimeException("Timeout waiting for new frame!"); 27490397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala } 27590397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala } 27690397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala try { 27790397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala this.wait(NEWFRAME_TIMEOUT); 27890397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala } catch (InterruptedException e) { 27990397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "interrupted"); 28090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala // ignoring 281c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala } 28290397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala waitCount++; 2831df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 28490397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala mNewFrameAvailable = false; 28590397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Got new frame"); 2864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2881df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mSurfaceTexture.updateTexImage(); 289855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mOrientationUpdated = true; 290855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala } 291855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala if (mOrientationUpdated) { 292855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala float[] surfaceTransform = new float[16]; 293855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mSurfaceTexture.getTransformMatrix(surfaceTransform); 294855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 295855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala float[] sourceCoords = new float[16]; 296855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala switch (mOrientation) { 297855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala default: 298855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala case 0: 299855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala Matrix.multiplyMM(sourceCoords, 0, 300855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala surfaceTransform, 0, 301855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mSourceCoords_0, 0); 302855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala break; 303855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala case 90: 304855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala Matrix.multiplyMM(sourceCoords, 0, 305855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala surfaceTransform, 0, 306855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mSourceCoords_90, 0); 307855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala break; 308855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala case 180: 309855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala Matrix.multiplyMM(sourceCoords, 0, 310855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala surfaceTransform, 0, 311855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mSourceCoords_180, 0); 312855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala break; 313855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala case 270: 314855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala Matrix.multiplyMM(sourceCoords, 0, 315855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala surfaceTransform, 0, 316855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mSourceCoords_270, 0); 317855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala break; 318855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala } 319760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi if (mLogVerbose) { 320760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi Log.v(TAG, "OrientationHint = " + mOrientation); 321760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi String temp = String.format("SetSourceRegion: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f", 322760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi sourceCoords[4], sourceCoords[5],sourceCoords[0], sourceCoords[1], 323760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi sourceCoords[12], sourceCoords[13],sourceCoords[8], sourceCoords[9]); 324760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi Log.v(TAG, temp); 325760eb949cf0abe299e6c6710cda5c52364945ae0Pannag Sanketi } 32653573cd771f2c731d1e7f1fad4df9beba09d237dPannag Sanketi mFrameExtractor.setSourceRegion(sourceCoords[4], sourceCoords[5], 32753573cd771f2c731d1e7f1fad4df9beba09d237dPannag Sanketi sourceCoords[0], sourceCoords[1], 32853573cd771f2c731d1e7f1fad4df9beba09d237dPannag Sanketi sourceCoords[12], sourceCoords[13], 32953573cd771f2c731d1e7f1fad4df9beba09d237dPannag Sanketi sourceCoords[8], sourceCoords[9]); 330855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mOrientationUpdated = false; 3311df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 3324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Frame output = context.getFrameManager().newFrame(mOutputFormat); 3344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.process(mMediaFrame, output); 3354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3368dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala long timestamp = mSurfaceTexture.getTimestamp(); 3378dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Timestamp: " + (timestamp / 1000000000.0) + " s"); 3388dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala output.setTimestamp(timestamp); 3398dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala 34021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn pushOutput("video", output); 3414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala output.release(); 3424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3431df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPlaying = true; 3444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 3474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void close(FilterContext context) { 3484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer.isPlaying()) { 3494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.stop(); 3504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 351855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mPrepared = false; 352855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mGotSize = false; 353855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mPlaying = false; 354855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mPaused = false; 355855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mCompleted = false; 356855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mNewFrameAvailable = false; 357855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala 3584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 3594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 360aae596d15186de172632499692d44bc5436108f7Eino-Ville Talvala mSurfaceTexture.release(); 361aae596d15186de172632499692d44bc5436108f7Eino-Ville Talvala mSurfaceTexture = null; 3628dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaSource closed"); 3634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 3664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void tearDown(FilterContext context) { 3674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaFrame != null) { 3684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaFrame.release(); 3694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3722dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen // When updating the port values of the filter, users can update sourceIsUrl to switch 3732dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen // between using URL objects or Assets. 3742dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen // If updating only sourceUrl/sourceAsset, MediaPlayer gets reset if the current player 3752dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen // uses Url objects/Asset. 3762dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen // Otherwise the new sourceUrl/sourceAsset is stored and will be used when users switch 3772dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen // sourceIsUrl next time. 3784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 37921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void fieldPortValueUpdated(String name, FilterContext context) { 38090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Parameter update"); 3812dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (name.equals("sourceUrl")) { 3822dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (isOpen()) { 3838dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Opening new source URL"); 3842dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (mSelectedIsUrl) { 3852dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen setupMediaPlayer(mSelectedIsUrl); 3862dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen } 3874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 38821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } else if (name.equals("sourceAsset") ) { 3894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 3902dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (mLogVerbose) Log.v(TAG, "Opening new source FD"); 3912dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (!mSelectedIsUrl) { 3922dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen setupMediaPlayer(mSelectedIsUrl); 3934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 39521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } else if (name.equals("loop")) { 3964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 39721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn mMediaPlayer.setLooping(mLooping); 3984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3992dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen } else if (name.equals("sourceIsUrl")) { 4002dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (isOpen()){ 4012dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (mSelectedIsUrl){ 4022dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (mLogVerbose) Log.v(TAG, "Opening new source URL"); 4032dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen } else { 4042dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (mLogVerbose) Log.v(TAG, "Opening new source Asset"); 4052dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen } 4062dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen setupMediaPlayer(mSelectedIsUrl); 4072dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen } 408c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala } else if (name.equals("volume")) { 409c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (isOpen()) { 410c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala mMediaPlayer.setVolume(mVolume, mVolume); 411c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala } 412855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala } else if (name.equals("orientation") && mGotSize) { 413855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala if (mOrientation == 0 || mOrientation == 180) { 414855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mOutputFormat.setDimensions(mWidth, mHeight); 415855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala } else { 416855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mOutputFormat.setDimensions(mHeight, mWidth); 417855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala } 418855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mOrientationUpdated = true; 4194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 4204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 4214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4221df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala synchronized public void pauseVideo(boolean pauseState) { 4236aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (isOpen()) { 4246aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (pauseState && !mPaused) { 4256aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.pause(); 4266aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } else if (!pauseState && mPaused) { 4276aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.start(); 4286aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 4296aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 4301df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPaused = pauseState; 4311df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 4321df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala 4334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Creates a media player, sets it up, and calls prepare */ 4342dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen synchronized private boolean setupMediaPlayer(boolean useUrl) { 4354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = false; 4364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = false; 4374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPlaying = false; 4386aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mPaused = false; 439c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala mCompleted = false; 44090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala mNewFrameAvailable = false; 441c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala 442c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Setting up playback."); 4434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer != null) { 44590397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala // Clean up existing media players 446c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Resetting existing MediaPlayer."); 4474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.reset(); 4484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 4494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Create new media player 450c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Creating new MediaPlayer."); 4514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = new MediaPlayer(); 4524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 4534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 455c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala throw new RuntimeException("Unable to create a MediaPlayer!"); 4564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 4574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Set up data sources, etc 4594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala try { 4602dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (useUrl) { 461c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to URI " + mSourceUrl); 4624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceUrl); 4634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 464c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to asset " + mSourceAsset); 4654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength()); 4664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 4674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch(IOException e) { 468c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala mMediaPlayer.release(); 469c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala mMediaPlayer = null; 4702dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (useUrl) { 471c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala throw new RuntimeException(String.format("Unable to set MediaPlayer to URL %s!", mSourceUrl), e); 4724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 473c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala throw new RuntimeException(String.format("Unable to set MediaPlayer to asset %s!", mSourceAsset), e); 4744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 475c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala } catch(IllegalArgumentException e) { 4764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 4774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 4782dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen if (useUrl) { 479c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala throw new RuntimeException(String.format("Unable to set MediaPlayer to URL %s!", mSourceUrl), e); 4804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 481c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala throw new RuntimeException(String.format("Unable to set MediaPlayer to asset %s!", mSourceAsset), e); 4824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 4834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 4844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setLooping(mLooping); 486c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala mMediaPlayer.setVolume(mVolume, mVolume); 4874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Bind it to our media frame 4891ae8bcdf7dc3df7be3ca14b6f63d0009654fab69Jamie Gennis Surface surface = new Surface(mSurfaceTexture); 4901ae8bcdf7dc3df7be3ca14b6f63d0009654fab69Jamie Gennis mMediaPlayer.setSurface(surface); 4911ae8bcdf7dc3df7be3ca14b6f63d0009654fab69Jamie Gennis surface.release(); 4924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect Media Player to callbacks 4944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener); 4964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnPreparedListener(onPreparedListener); 4974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnCompletionListener(onCompletionListener); 4984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 4994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect SurfaceTexture to callback 5004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mSurfaceTexture.setOnFrameAvailableListener(onMediaFrameAvailableListener); 5014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 502c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Preparing MediaPlayer."); 5034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.prepareAsync(); 5044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 50521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return true; 5064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 5084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = 5094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnVideoSizeChangedListener() { 5104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 5118dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaPlayer sent dimensions: " + width + " x " + height); 5124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mGotSize) { 513855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala if (mOrientation == 0 || mOrientation == 180) { 514855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mOutputFormat.setDimensions(width, height); 515855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala } else { 516855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mOutputFormat.setDimensions(height, width); 517855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala } 518855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mWidth = width; 519855b25acc20d38dfb98eff8bf73fbc441e174a92Eino-Ville Talvala mHeight = height; 5204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 5214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mOutputFormat.getWidth() != width || 5224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.getHeight() != height) { 5234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Multiple video size change events received!"); 5244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 52690397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala synchronized(MediaSource.this) { 5274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = true; 52890397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala MediaSource.this.notify(); 5294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 5324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 5334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnPreparedListener onPreparedListener = 5344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnPreparedListener() { 5354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onPrepared(MediaPlayer mp) { 5368dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaPlayer is prepared"); 53790397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala synchronized(MediaSource.this) { 5384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = true; 53990397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala MediaSource.this.notify(); 5404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 5434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 5444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnCompletionListener onCompletionListener = 5454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnCompletionListener() { 5464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onCompletion(MediaPlayer mp) { 5478dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaPlayer has completed playback"); 54890397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala synchronized(MediaSource.this) { 549c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala mCompleted = true; 550c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala } 5514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 5534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 5544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private SurfaceTexture.OnFrameAvailableListener onMediaFrameAvailableListener = 5554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new SurfaceTexture.OnFrameAvailableListener() { 5564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onFrameAvailable(SurfaceTexture surfaceTexture) { 5578dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "New frame from media player"); 55890397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala synchronized(MediaSource.this) { 55990397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "New frame: notify"); 56090397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala mNewFrameAvailable = true; 56190397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala MediaSource.this.notify(); 56290397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala if (mLogVerbose) Log.v(TAG, "New frame: notify done"); 56390397368b3af2279e6aa739182b4e50b26a90bebEino-Ville Talvala } 5644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 5654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 5664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 5674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala} 568