MediaSource.java revision 8dd704358d808382465666354fc891af59b21e18
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) 659b393be2b4b7e70abe38237ba3eda3dc009d6230Eino-Ville Talvala private AssetFileDescriptor mSourceAsset = null; 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 1018dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala private final boolean mLogVerbose; 1024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final String TAG = "MediaSource"; 1034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public MediaSource(String name) { 1054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala super(name); 1064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mNewFrameAvailable = new ConditionVariable(); 1074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameTransform = new float[16]; 1088dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala 1098dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE); 1104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 11321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void setupPorts() { 11421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn // Add input port 11521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn addOutputPort("video", ImageFormat.create(ImageFormat.COLORSPACE_RGBA, 11621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn FrameFormat.TARGET_GPU)); 1174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 11921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn private void createFormats() { 12021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn mOutputFormat = ImageFormat.create(ImageFormat.COLORSPACE_RGBA, 12121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn FrameFormat.TARGET_GPU); 1224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala protected void prepare(FilterContext context) { 1268dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Preparing MediaSource"); 1274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor = new ShaderProgram(mFrameShader); 1294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // SurfaceTexture defines (0,0) to be bottom-left. The filter framework 1304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // defines (0,0) as top-left, so do the flip here. 1314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.setSourceRect(0, 1, 1, -1); 1324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 13321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn createFormats(); 13421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn 135edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala mMediaFrame = (GLFrame)context.getFrameManager().newBoundFrame(mOutputFormat, 136edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala GLFrame.EXTERNAL_TEXTURE, 137edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala 0); 1384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mSurfaceTexture = new SurfaceTexture(mMediaFrame.getTextureId()); 1394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 14221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void open(FilterContext context) { 1438dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Opening MediaSource"); 14421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn if (!setupMediaPlayer()) { 14521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new RuntimeException("Error setting up MediaPlayer!"); 14621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } 1474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 15021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void process(FilterContext context) { 1516aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala // Note: process is synchronized by its caller in the Filter base class 1528dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Processing new frame"); 1534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 1554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Something went wrong in initialization or parameter updates 15621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new NullPointerException("Unexpected null media player!"); 1574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mPlaying) { 1606aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala int waitCount = 0; 1616aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala while (!mGotSize || !mPrepared) { 1626aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala try { 16321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn this.wait(100); 1646aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } catch (InterruptedException e) { 1656aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala // ignoring 1666aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 1676aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala waitCount++; 1686aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (waitCount == 50) { 1696aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.release(); 17021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new RuntimeException("MediaPlayer timed out while preparing!"); 1714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.start(); 1744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1761df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // Use last frame if paused, unless just starting playback, in which case 1771df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // we want at least one valid frame before pausing 1781df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (!mPaused || !mPlaying) { 1791df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (mWaitForNewFrame) { 1801df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala boolean gotNewFrame; 1811df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala gotNewFrame = mNewFrameAvailable.block(1000); 1821df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (!gotNewFrame) { 18321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn throw new RuntimeException("Timeout waiting for new frame!"); 1841df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 1851df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mNewFrameAvailable.close(); 1864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1881df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mSurfaceTexture.updateTexImage(); 1894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1901df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mSurfaceTexture.getTransformMatrix(mFrameTransform); 1911df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mFrameExtractor.setHostValue("frame_transform", mFrameTransform); 1921df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 1934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Frame output = context.getFrameManager().newFrame(mOutputFormat); 1954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.process(mMediaFrame, output); 1964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1978dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala long timestamp = mSurfaceTexture.getTimestamp(); 1988dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Timestamp: " + (timestamp / 1000000000.0) + " s"); 1998dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala output.setTimestamp(timestamp); 2008dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala 20121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn pushOutput("video", output); 2024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala output.release(); 2034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2041df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPlaying = true; 2054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 2084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void close(FilterContext context) { 2094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer.isPlaying()) { 2104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.stop(); 2114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 2134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 2148dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaSource closed"); 2154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 2184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void tearDown(FilterContext context) { 2194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaFrame != null) { 2204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaFrame.release(); 2214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 22521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void fieldPortValueUpdated(String name, FilterContext context) { 22621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn if (name.equals("sourceUrl") && mSourceAsset == null) { 2274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 2288dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Opening new source URL"); 2294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala setupMediaPlayer(); 2304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 23121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } else if (name.equals("sourceAsset") ) { 2324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 2338dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) { 2344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2358dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Opening new source URL"); 2364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.v(TAG, "Opening new source FD"); 2384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala setupMediaPlayer(); 2414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 24221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } else if (name.equals("loop")) { 2434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 24421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn mMediaPlayer.setLooping(mLooping); 2454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2491df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala synchronized public void pauseVideo(boolean pauseState) { 2506aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (isOpen()) { 2516aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala if (pauseState && !mPaused) { 2526aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.pause(); 2536aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } else if (!pauseState && mPaused) { 2546aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mMediaPlayer.start(); 2556aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 2566aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala } 2571df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPaused = pauseState; 2581df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 2591df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala 2604a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Creates a media player, sets it up, and calls prepare */ 26121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn synchronized private boolean setupMediaPlayer() { 2624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = false; 2634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = false; 2644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPlaying = false; 2656aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala mPaused = false; 2664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer != null) { 2684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Clean up existing media player 2694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.reset(); 2704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Create new media player 2724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = new MediaPlayer(); 2734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 2764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to create a media player!"); 27721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return false; 2784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Set up data sources, etc 2814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala try { 2824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceUrl); 2844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength()); 2864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch(IOException e) { 2884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e); 2904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e); 2924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 2944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 29521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return false; 2964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch(IllegalArgumentException e) { 2974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e); 2994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 3004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e); 3014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 3034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 30421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return false; 3054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setLooping(mLooping); 3084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Bind it to our media frame 3104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setTexture(mSurfaceTexture); 3114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect Media Player to callbacks 3134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener); 3154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnPreparedListener(onPreparedListener); 3164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnCompletionListener(onCompletionListener); 3174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect SurfaceTexture to callback 3194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mSurfaceTexture.setOnFrameAvailableListener(onMediaFrameAvailableListener); 3204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.prepareAsync(); 3224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3238dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaPlayer now preparing."); 32421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn return true; 3254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = 3284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnVideoSizeChangedListener() { 3294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 3308dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaPlayer sent dimensions: " + width + " x " + height); 3314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mGotSize) { 3324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.setDimensions(width, height); 3334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 3344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mOutputFormat.getWidth() != width || 3354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.getHeight() != height) { 3364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Multiple video size change events received!"); 3374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized(this) { 3404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = true; 3414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala this.notify(); 3424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnPreparedListener onPreparedListener = 3474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnPreparedListener() { 3484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onPrepared(MediaPlayer mp) { 3498dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaPlayer is prepared"); 3504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized(this) { 3514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = true; 3524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala this.notify(); 3534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnCompletionListener onCompletionListener = 3584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnCompletionListener() { 3594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onCompletion(MediaPlayer mp) { 3608dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "MediaPlayer has completed playback"); 3614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private SurfaceTexture.OnFrameAvailableListener onMediaFrameAvailableListener = 3654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new SurfaceTexture.OnFrameAvailableListener() { 3664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onFrameAvailable(SurfaceTexture surfaceTexture) { 3678dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "New frame from media player"); 3684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mNewFrameAvailable.open(); 3694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala} 373