MediaSource.java revision 1df612099dde7e43249468d46e5b8064d8c33b77
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.FilterParameter; 244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.FilterContext; 254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.Frame; 264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.GLFrame; 274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.FrameFormat; 284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.FrameManager; 294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.KeyValueMap; 304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.MutableFrameFormat; 314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.NativeFrame; 324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.Program; 334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.filterfw.core.ShaderProgram; 344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.graphics.SurfaceTexture; 354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.media.MediaPlayer; 364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.os.ConditionVariable; 374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.io.IOException; 394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.io.FileDescriptor; 404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.lang.IllegalArgumentException; 414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.util.List; 424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport java.util.Set; 434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalaimport android.util.Log; 464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalapublic class MediaSource extends Filter { 484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** User-visible parameters */ 504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** The source URL for the media source. Can be an http: link to a remote 524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * resource, or a file: link to a local media file */ 534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @FilterParameter(name = "sourceUrl", isOptional = true, isUpdatable = true) 544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private String mSourceUrl = ""; 554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** An open asset file descriptor to a local media source. If set, 574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * overrides the sourceUrl field. Set to null to use the sourceUrl field 584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * instead. */ 594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @FilterParameter(name = "sourceAsset", isOptional = true, isUpdatable = true) 604a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private AssetFileDescriptor mSourceAsset; 614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Whether the filter will always wait for a new video frame, or whether it 634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala * will output an old frame again if a new frame isn't available. Defaults to true. 644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala */ 654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @FilterParameter(name = "waitForNewFrame", isOptional = true, isUpdatable = true) 664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mWaitForNewFrame = true; 674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Whether the media source should loop automatically or not. Defaults to true. */ 694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @FilterParameter(name = "loop", isOptional = true, isUpdatable = true) 704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mLooping = true; 714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer mMediaPlayer; 734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private GLFrame mMediaFrame; 744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private SurfaceTexture mSurfaceTexture; 754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private ShaderProgram mFrameExtractor; 764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MutableFrameFormat mOutputFormat; 774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MutableFrameFormat mMediaFormat; 784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private ConditionVariable mNewFrameAvailable; 794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private float[] mFrameTransform; 804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private final String mFrameShader = 824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "#extension GL_OES_EGL_image_external : require\n" + 834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "precision mediump float;\n" + 844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "uniform mat4 frame_transform;\n" + 854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "uniform samplerExternalOES tex_sampler_0;\n" + 864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "varying vec2 v_texcoord;\n" + 874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "void main() {\n" + 884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala " vec2 transformed_texcoord = (frame_transform * vec4(v_texcoord, 0., 1.) ).xy;" + 894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala " gl_FragColor = texture2D(tex_sampler_0, transformed_texcoord);\n" + 904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala "}\n"; 914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mGotSize; 934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mPrepared; 944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private boolean mPlaying; 951df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala private boolean mPaused; 964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final boolean LOGV = true; 984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final boolean LOGVV = false; 994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private static final String TAG = "MediaSource"; 1004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public MediaSource(String name) { 1024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala super(name); 1034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mNewFrameAvailable = new ConditionVariable(); 1044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameTransform = new float[16]; 1054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public String[] getInputNames() { 1094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return null; 1104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public String[] getOutputNames() { 1144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return new String[] { "video" }; 1154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public boolean acceptsInputFormat(int index, FrameFormat format) { 1194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return false; 1204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public FrameFormat getOutputFormat(int index) { 1244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Format matches that of a GLFrame, but don't want to access an OpenGL 1254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // context yet 1264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat = new MutableFrameFormat(FrameFormat.TYPE_BYTE, 1274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala FrameFormat.TARGET_GPU); 1284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.setBytesPerSample(4); 1291df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // Don't know dimensions until we open the media file 1301df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mOutputFormat.setDimensions(0, 0); 1314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaFormat = mOutputFormat.mutableCopy(); 1334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaFormat.setMetaValue(GLFrame.USE_EXTERNAL_TEXTURE, true); 1344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return mOutputFormat; 1364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala protected void prepare(FilterContext context) { 1404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Preparing MediaSource"); 1414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaFrame = (GLFrame)context.getFrameManager().newFrame(mMediaFormat); 1434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor = new ShaderProgram(mFrameShader); 1454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // SurfaceTexture defines (0,0) to be bottom-left. The filter framework 1464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // defines (0,0) as top-left, so do the flip here. 1474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.setSourceRect(0, 1, 1, -1); 1484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mSurfaceTexture = new SurfaceTexture(mMediaFrame.getTextureId()); 1504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public int open(FilterContext context) { 1544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Opening MediaSource"); 1554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return setupMediaPlayer(); 1564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 1594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public int process(FilterContext context) { 1604a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGVV) Log.v(TAG, "Processing new frame"); 1614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 1634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Something went wrong in initialization or parameter updates 1644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return Filter.STATUS_ERROR; 1654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mPlaying) { 1684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized(this) { 1694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala int waitCount = 0; 1704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala while (!mGotSize || !mPrepared) { 1714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala try { 1724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala this.wait(100); 1734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch (InterruptedException e) { 1744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // ignoring 1754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala waitCount++; 1774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (waitCount == 50) { 1784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "MediaPlayer timed out while preparing"); 1794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 1804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return Filter.STATUS_ERROR; 1814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.start(); 1854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 1871df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // Use last frame if paused, unless just starting playback, in which case 1881df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala // we want at least one valid frame before pausing 1891df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (!mPaused || !mPlaying) { 1901df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (mWaitForNewFrame) { 1911df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala boolean gotNewFrame; 1921df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala gotNewFrame = mNewFrameAvailable.block(1000); 1931df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala if (!gotNewFrame) { 1941df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala Log.e(TAG, "Timeout waiting for new frame"); 1951df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala return Filter.STATUS_ERROR; 1961df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 1971df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mNewFrameAvailable.close(); 1984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 1994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2001df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mSurfaceTexture.updateTexImage(); 2014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2021df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mSurfaceTexture.getTransformMatrix(mFrameTransform); 2031df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mFrameExtractor.setHostValue("frame_transform", mFrameTransform); 2041df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 2054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Frame output = context.getFrameManager().newFrame(mOutputFormat); 2074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mFrameExtractor.process(mMediaFrame, output); 2084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala putOutput(0, output); 2104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala output.release(); 2114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2121df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPlaying = true; 2131df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala 2144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return Filter.STATUS_WAIT_FOR_FREE_OUTPUTS; 2154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 2184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void close(FilterContext context) { 2194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer.isPlaying()) { 2204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.stop(); 2214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 2234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 2244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaSource closed"); 2254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 2284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void tearDown(FilterContext context) { 2294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaFrame != null) { 2304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaFrame.release(); 2314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala @Override 2354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void parametersUpdated(Set<String> updated) { 2364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (updated.contains("sourceUrl") && mSourceAsset == null) { 2374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 2384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Opening new source URL"); 2394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala setupMediaPlayer(); 2404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else if (updated.contains("sourceAsset") ) { 2424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 2434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) { 2444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "Opening new source URL"); 2464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.v(TAG, "Opening new source FD"); 2484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala setupMediaPlayer(); 2514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else if (updated.contains("loop")) { 2534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (isOpen()) { 2544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setLooping(mLooping); 2554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2591df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala synchronized public void pauseVideo(boolean pauseState) { 2601df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala mPaused = pauseState; 2611df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala } 2621df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala 2634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala /** Creates a media player, sets it up, and calls prepare */ 2644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized private int setupMediaPlayer() { 2654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = false; 2664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = false; 2674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPlaying = false; 2684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer != null) { 2704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Clean up existing media player 2714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.reset(); 2724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Create new media player 2744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = new MediaPlayer(); 2754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mMediaPlayer == null) { 2784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to create a media player!"); 2794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return Filter.STATUS_ERROR; 2804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 2824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Set up data sources, etc 2834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala try { 2844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceUrl); 2864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength()); 2884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch(IOException e) { 2904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 2914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e); 2924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 2934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e); 2944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 2954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 2964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 2974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return Filter.STATUS_ERROR; 2984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } catch(IllegalArgumentException e) { 2994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mSourceAsset == null) { 3004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e); 3014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 3024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e); 3034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.release(); 3054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer = null; 3064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return Filter.STATUS_ERROR; 3074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setLooping(mLooping); 3104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Bind it to our media frame 3124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setTexture(mSurfaceTexture); 3134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect Media Player to callbacks 3154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener); 3174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnPreparedListener(onPreparedListener); 3184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.setOnCompletionListener(onCompletionListener); 3194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala // Connect SurfaceTexture to callback 3214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mSurfaceTexture.setOnFrameAvailableListener(onMediaFrameAvailableListener); 3224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mMediaPlayer.prepareAsync(); 3244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer now preparing."); 3264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala return Filter.STATUS_WAIT_FOR_FREE_OUTPUTS; 3274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = 3304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnVideoSizeChangedListener() { 3314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 3324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer sent dimensions: " + width + " x " + height); 3334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (!mGotSize) { 3344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.setDimensions(width, height); 3354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } else { 3364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (mOutputFormat.getWidth() != width || 3374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mOutputFormat.getHeight() != height) { 3384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala Log.e(TAG, "Multiple video size change events received!"); 3394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized(this) { 3424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mGotSize = true; 3434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala this.notify(); 3444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnPreparedListener onPreparedListener = 3494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnPreparedListener() { 3504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onPrepared(MediaPlayer mp) { 3514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer is prepared"); 3524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala synchronized(this) { 3534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mPrepared = true; 3544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala this.notify(); 3554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private MediaPlayer.OnCompletionListener onCompletionListener = 3604a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new MediaPlayer.OnCompletionListener() { 3614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onCompletion(MediaPlayer mp) { 3624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGV) Log.v(TAG, "MediaPlayer has completed playback"); 3634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala private SurfaceTexture.OnFrameAvailableListener onMediaFrameAvailableListener = 3674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala new SurfaceTexture.OnFrameAvailableListener() { 3684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala public void onFrameAvailable(SurfaceTexture surfaceTexture) { 3694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala if (LOGVV) Log.v(TAG, "New frame from media player"); 3704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala mNewFrameAvailable.open(); 3714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala } 3724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala }; 3734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala 3744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala} 375