MediaSource.java revision a3bfbe5389c6146abe318a7add3fa688d69bc01b
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; 394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.io.IOException; 414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.io.FileDescriptor; 424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.lang.IllegalArgumentException; 434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.util.List; 444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.util.Set; 454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.util.Log; 484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 49a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala/** 50a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala * @hide 51a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala */ 524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalapublic class MediaSource extends Filter { 534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** User-visible parameters */ 554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** The source URL for the media source. Can be an http: link to a remote 574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * resource, or a file: link to a local media file */ 5821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFieldPort(name = "sourceUrl", hasDefault = true) 594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private String mSourceUrl = ""; 604a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** An open asset file descriptor to a local media source. If set, 624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * overrides the sourceUrl field. Set to null to use the sourceUrl field 634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * instead. */ 6421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFieldPort(name = "sourceAsset", hasDefault = true) 654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private AssetFileDescriptor mSourceAsset; 664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Whether the filter will always wait for a new video frame, or whether it 684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * will output an old frame again if a new frame isn't available. Defaults to true. 694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala */ 7021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFinalPort(name = "waitForNewFrame", hasDefault = true) 714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mWaitForNewFrame = true; 724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Whether the media source should loop automatically or not. Defaults to true. */ 7421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFieldPort(name = "loop", hasDefault = true) 754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mLooping = true; 764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer mMediaPlayer; 784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private GLFrame mMediaFrame; 794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private SurfaceTexture mSurfaceTexture; 804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private ShaderProgram mFrameExtractor; 814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MutableFrameFormat mOutputFormat; 824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private ConditionVariable mNewFrameAvailable; 834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private float[] mFrameTransform; 844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private final String mFrameShader = 864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "#extension GL_OES_EGL_image_external : require\n" + 874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "precision mediump float;\n" + 884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "uniform mat4 frame_transform;\n" + 894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "uniform samplerExternalOES tex_sampler_0;\n" + 904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "varying vec2 v_texcoord;\n" + 914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "void main() {\n" + 924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala " vec2 transformed_texcoord = (frame_transform * vec4(v_texcoord, 0., 1.) ).xy;" + 934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala " gl_FragColor = texture2D(tex_sampler_0, transformed_texcoord);\n" + 944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "}\n"; 954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mGotSize; 974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mPrepared; 984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mPlaying; 991df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala private boolean mPaused; 1004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final boolean LOGV = true; 1024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final boolean LOGVV = false; 1034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final String TAG = "MediaSource"; 1044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public MediaSource(String name) { 1064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala super(name); 1074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mNewFrameAvailable = new ConditionVariable(); 1084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameTransform = new float[16]; 1094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 11221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void setupPorts() { 11321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn // Add input port 11421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn addOutputPort("video", ImageFormat.create(ImageFormat.COLORSPACE_RGBA, 11521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn FrameFormat.TARGET_GPU)); 1164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 11821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn private void createFormats() { 11921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn mOutputFormat = ImageFormat.create(ImageFormat.COLORSPACE_RGBA, 12021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn FrameFormat.TARGET_GPU); 1214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala protected void prepare(FilterContext context) { 1254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Preparing MediaSource"); 1264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor = new ShaderProgram(mFrameShader); 1284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // SurfaceTexture defines (0,0) to be bottom-left. The filter framework 1294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // defines (0,0) as top-left, so do the flip here. 1304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.setSourceRect(0, 1, 1, -1); 1314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 13221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn createFormats(); 13321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn 134edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala mMediaFrame = (GLFrame)context.getFrameManager().newBoundFrame(mOutputFormat, 135edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala GLFrame.EXTERNAL_TEXTURE, 136edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala 0); 1374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mSurfaceTexture = new SurfaceTexture(mMediaFrame.getTextureId()); 1384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 14121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void open(FilterContext context) { 1424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Opening MediaSource"); 14321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn if (!setupMediaPlayer()) { 14421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new RuntimeException("Error setting up MediaPlayer!"); 14521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } 1464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 14921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void process(FilterContext context) { 1506aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala // Note: process is synchronized by its caller in the Filter base class 1514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGVV) Log.v(TAG, "Processing new frame"); 1524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 1544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Something went wrong in initialization or parameter updates 15521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new NullPointerException("Unexpected null media player!"); 1564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mPlaying) { 1596aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala int waitCount = 0; 1606aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala while (!mGotSize || !mPrepared) { 1616aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala try { 16221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn this.wait(100); 1636aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } catch (InterruptedException e) { 1646aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala // ignoring 1656aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 1666aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala waitCount++; 1676aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (waitCount == 50) { 1686aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.release(); 16921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new RuntimeException("MediaPlayer timed out while preparing!"); 1704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.start(); 1734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1751df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // Use last frame if paused, unless just starting playback, in which case 1761df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // we want at least one valid frame before pausing 1771df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (!mPaused || !mPlaying) { 1781df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (mWaitForNewFrame) { 1791df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala boolean gotNewFrame; 1801df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala gotNewFrame = mNewFrameAvailable.block(1000); 1811df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (!gotNewFrame) { 18221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new RuntimeException("Timeout waiting for new frame!"); 1831df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 1841df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mNewFrameAvailable.close(); 1854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1871df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mSurfaceTexture.updateTexImage(); 1884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1891df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mSurfaceTexture.getTransformMatrix(mFrameTransform); 1901df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mFrameExtractor.setHostValue("frame_transform", mFrameTransform); 1911df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 1924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Frame output = context.getFrameManager().newFrame(mOutputFormat); 1944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.process(mMediaFrame, output); 1954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 19621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn pushOutput("video", output); 1974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala output.release(); 1984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1991df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPlaying = true; 2004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 2034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void close(FilterContext context) { 2044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer.isPlaying()) { 2054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.stop(); 2064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 2084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 2094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaSource closed"); 2104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 2134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void tearDown(FilterContext context) { 2144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaFrame != null) { 2154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaFrame.release(); 2164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 22021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void fieldPortValueUpdated(String name, FilterContext context) { 22121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn if (name.equals("sourceUrl") && mSourceAsset == null) { 2224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 2234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Opening new source URL"); 2244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala setupMediaPlayer(); 2254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 22621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } else if (name.equals("sourceAsset") ) { 2274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 2284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) { 2294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Opening new source URL"); 2314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.v(TAG, "Opening new source FD"); 2334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala setupMediaPlayer(); 2364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 23721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } else if (name.equals("loop")) { 2384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 23921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn mMediaPlayer.setLooping(mLooping); 2404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2441df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala synchronized public void pauseVideo(boolean pauseState) { 2456aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (isOpen()) { 2466aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (pauseState && !mPaused) { 2476aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.pause(); 2486aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } else if (!pauseState && mPaused) { 2496aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.start(); 2506aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 2516aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 2521df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPaused = pauseState; 2531df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 2541df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala 2554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Creates a media player, sets it up, and calls prepare */ 25621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn synchronized private boolean setupMediaPlayer() { 2574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = false; 2584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = false; 2594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPlaying = false; 2606aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mPaused = false; 2614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer != null) { 2634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Clean up existing media player 2644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.reset(); 2654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Create new media player 2674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = new MediaPlayer(); 2684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 2714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to create a media player!"); 27221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return false; 2734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Set up data sources, etc 2764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala try { 2774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceUrl); 2794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength()); 2814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch(IOException e) { 2834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e); 2854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e); 2874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 2894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 29021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return false; 2914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch(IllegalArgumentException e) { 2924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e); 2944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e); 2964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 2984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 29921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return false; 3004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setLooping(mLooping); 3034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Bind it to our media frame 3054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setTexture(mSurfaceTexture); 3064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect Media Player to callbacks 3084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener); 3104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnPreparedListener(onPreparedListener); 3114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnCompletionListener(onCompletionListener); 3124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect SurfaceTexture to callback 3144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mSurfaceTexture.setOnFrameAvailableListener(onMediaFrameAvailableListener); 3154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.prepareAsync(); 3174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer now preparing."); 31921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return true; 3204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = 3234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnVideoSizeChangedListener() { 3244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 3254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer sent dimensions: " + width + " x " + height); 3264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mGotSize) { 3274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.setDimensions(width, height); 3284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 3294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mOutputFormat.getWidth() != width || 3304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.getHeight() != height) { 3314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Multiple video size change events received!"); 3324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized(this) { 3354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = true; 3364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala this.notify(); 3374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnPreparedListener onPreparedListener = 3424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnPreparedListener() { 3434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onPrepared(MediaPlayer mp) { 3444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer is prepared"); 3454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized(this) { 3464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = true; 3474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala this.notify(); 3484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnCompletionListener onCompletionListener = 3534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnCompletionListener() { 3544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onCompletion(MediaPlayer mp) { 3554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer has completed playback"); 3564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private SurfaceTexture.OnFrameAvailableListener onMediaFrameAvailableListener = 3604a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new SurfaceTexture.OnFrameAvailableListener() { 3614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onFrameAvailable(SurfaceTexture surfaceTexture) { 3624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGVV) Log.v(TAG, "New frame from media player"); 3634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mNewFrameAvailable.open(); 3644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala} 368