MediaSource.java revision c8afe66093a29852779745ddf7c45dee6f0dc414
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 Talvalaimport android.util.Log;
474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
48a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala/**
49a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala * @hide
50a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala */
514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvalapublic class MediaSource extends Filter {
524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** User-visible parameters */
544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** The source URL for the media source. Can be an http: link to a remote
564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala     * resource, or a file: link to a local media file */
5721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "sourceUrl", hasDefault = true)
584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private String mSourceUrl = "";
594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
602dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    /** An open asset file descriptor to a local media source. Default is null */
6121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "sourceAsset", hasDefault = true)
629b393be2b4b7e70abe38237ba3eda3dc009d6230Eino-Ville Talvala    private AssetFileDescriptor mSourceAsset = null;
634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
64c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala    /** Whether the media source is a URL or an asset file descriptor. Defaults to false. */
65c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala    @GenerateFieldPort(name = "sourceIsUrl", hasDefault = true)
66c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala    private boolean mSelectedIsUrl = false;
67c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala
684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** Whether the filter will always wait for a new video frame, or whether it
694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala     * will output an old frame again if a new frame isn't available. Defaults to true.
704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala     */
7121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFinalPort(name = "waitForNewFrame", hasDefault = true)
724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mWaitForNewFrame = true;
734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** Whether the media source should loop automatically or not. Defaults to true. */
7521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "loop", hasDefault = true)
764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mLooping = true;
774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
78c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala    /** Volume control. Currently sound is piped directly to the speakers, so this defaults to mute. */
79c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala    @GenerateFieldPort(name = "volume", hasDefault = true)
80c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala    private float mVolume = 0.f;
812dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen
824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer mMediaPlayer;
834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private GLFrame mMediaFrame;
844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private SurfaceTexture mSurfaceTexture;
854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private ShaderProgram mFrameExtractor;
864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MutableFrameFormat mOutputFormat;
874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private ConditionVariable mNewFrameAvailable;
884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private float[] mFrameTransform;
894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private final String mFrameShader =
914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "#extension GL_OES_EGL_image_external : require\n" +
924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "precision mediump float;\n" +
934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "uniform mat4 frame_transform;\n" +
944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "uniform samplerExternalOES tex_sampler_0;\n" +
954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "varying vec2 v_texcoord;\n" +
964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "void main() {\n" +
974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "  vec2 transformed_texcoord = (frame_transform * vec4(v_texcoord, 0., 1.) ).xy;" +
984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "  gl_FragColor = texture2D(tex_sampler_0, transformed_texcoord);\n" +
994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "}\n";
1004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mGotSize;
1024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mPrepared;
1034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mPlaying;
1041df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala    private boolean mPaused;
105c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala    private boolean mCompleted;
1064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1078dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala    private final boolean mLogVerbose;
1084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private static final String TAG = "MediaSource";
1094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    public MediaSource(String name) {
1114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        super(name);
1124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mNewFrameAvailable = new ConditionVariable();
1134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mFrameTransform = new float[16];
1148dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala
1158dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
1164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
11921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void setupPorts() {
12021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        // Add input port
12121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        addOutputPort("video", ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
12221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                                                  FrameFormat.TARGET_GPU));
1234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
12521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    private void createFormats() {
12621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        mOutputFormat = ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
12721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                                           FrameFormat.TARGET_GPU);
1284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
1314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    protected void prepare(FilterContext context) {
1328dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Preparing MediaSource");
1334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
134511360e61650864ea22a171159efe073c80d0cdbMarius Renn        mFrameExtractor = new ShaderProgram(context, mFrameShader);
1354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // SurfaceTexture defines (0,0) to be bottom-left. The filter framework
1364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // defines (0,0) as top-left, so do the flip here.
1374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mFrameExtractor.setSourceRect(0, 1, 1, -1);
1384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
13921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        createFormats();
14021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn
141edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala        mMediaFrame = (GLFrame)context.getFrameManager().newBoundFrame(mOutputFormat,
142edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala                                                                       GLFrame.EXTERNAL_TEXTURE,
143edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala                                                                       0);
1444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mSurfaceTexture = new SurfaceTexture(mMediaFrame.getTextureId());
1452dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen
1464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
14921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void open(FilterContext context) {
1508dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Opening MediaSource");
1512dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        if (mLogVerbose) {
1522dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          if (mSelectedIsUrl) {
1532dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            Log.v(TAG, "Current URL is " + mSourceUrl);
1542dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          } else {
1552dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            Log.v(TAG, "Current source is Asset!");
1562dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          }
1572dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        }
1582dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        if (!setupMediaPlayer(mSelectedIsUrl)) {
1592dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          throw new RuntimeException("Error setting up MediaPlayer!");
16021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        }
1614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
16421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void process(FilterContext context) {
1656aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        // Note: process is synchronized by its caller in the Filter base class
1668dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Processing new frame");
1674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaPlayer == null) {
1694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            // Something went wrong in initialization or parameter updates
17021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn            throw new NullPointerException("Unexpected null media player!");
1714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
1724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
173c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        if (mCompleted) {
174c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            // Video playback is done, so close us down
175c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            closeOutputPort("video");
176c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            return;
177c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        }
178c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala
1794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (!mPlaying) {
1806aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            int waitCount = 0;
1816aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            while (!mGotSize || !mPrepared) {
1826aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                try {
183c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                    this.wait(100);
1846aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                } catch (InterruptedException e) {
1856aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                    // ignoring
1866aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                }
187c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                if (mCompleted) {
188c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                    // Video playback is done, so close us down
189c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                    closeOutputPort("video");
190c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                    return;
191c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                }
1926aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                waitCount++;
1936aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                if (waitCount == 50) {
1946aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                    mMediaPlayer.release();
19521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                    throw new RuntimeException("MediaPlayer timed out while preparing!");
1964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                }
1974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
1984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.start();
1994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
2004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2011df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        // Use last frame if paused, unless just starting playback, in which case
2021df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        // we want at least one valid frame before pausing
2031df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        if (!mPaused || !mPlaying) {
2041df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            if (mWaitForNewFrame) {
2051df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                boolean gotNewFrame;
2061df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                gotNewFrame = mNewFrameAvailable.block(1000);
2071df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                if (!gotNewFrame) {
208c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                    if (mCompleted) {
209c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                        // Video playback is done, so close us down
210c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                        closeOutputPort("video");
211c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                        return;
212c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                    } else {
213c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                        throw new RuntimeException("Timeout waiting for new frame!");
214c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                    }
2151df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                }
2161df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                mNewFrameAvailable.close();
2174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
2184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2191df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            mSurfaceTexture.updateTexImage();
2204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2211df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            mSurfaceTexture.getTransformMatrix(mFrameTransform);
2221df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            mFrameExtractor.setHostValue("frame_transform", mFrameTransform);
2231df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        }
2244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        Frame output = context.getFrameManager().newFrame(mOutputFormat);
2264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mFrameExtractor.process(mMediaFrame, output);
2274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2288dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        long timestamp = mSurfaceTexture.getTimestamp();
2298dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Timestamp: " + (timestamp / 1000000000.0) + " s");
2308dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        output.setTimestamp(timestamp);
2318dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala
23221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        pushOutput("video", output);
2334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        output.release();
2344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2351df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        mPlaying = true;
2364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
2374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
2394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    public void close(FilterContext context) {
2404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaPlayer.isPlaying()) {
2414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.stop();
2424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
2434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.release();
2444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer = null;
2458dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "MediaSource closed");
2464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
2474a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
2494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    public void tearDown(FilterContext context) {
2504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaFrame != null) {
2514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaFrame.release();
2524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
2534a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
2544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2552dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    // When updating the port values of the filter, users can update sourceIsUrl to switch
2562dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    //   between using URL objects or Assets.
2572dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    // If updating only sourceUrl/sourceAsset, MediaPlayer gets reset if the current player
2582dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    //   uses Url objects/Asset.
2592dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    // Otherwise the new sourceUrl/sourceAsset is stored and will be used when users switch
2602dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    //   sourceIsUrl next time.
2614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
26221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void fieldPortValueUpdated(String name, FilterContext context) {
2632dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        if (name.equals("sourceUrl")) {
2642dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen           if (isOpen()) {
2658dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala                if (mLogVerbose) Log.v(TAG, "Opening new source URL");
2662dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (mSelectedIsUrl) {
2672dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    setupMediaPlayer(mSelectedIsUrl);
2682dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                }
2694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
27021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        } else if (name.equals("sourceAsset") ) {
2714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            if (isOpen()) {
2722dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (mLogVerbose) Log.v(TAG, "Opening new source FD");
2732dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (!mSelectedIsUrl) {
2742dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    setupMediaPlayer(mSelectedIsUrl);
2754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                }
2764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
27721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        } else if (name.equals("loop")) {
2784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            if (isOpen()) {
27921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                mMediaPlayer.setLooping(mLooping);
2804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
2812dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        } else if (name.equals("sourceIsUrl")) {
2822dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (isOpen()){
2832dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (mSelectedIsUrl){
2842dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    if (mLogVerbose) Log.v(TAG, "Opening new source URL");
2852dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                } else {
2862dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    if (mLogVerbose) Log.v(TAG, "Opening new source Asset");
2872dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                }
2882dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                setupMediaPlayer(mSelectedIsUrl);
2892dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            }
290c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        } else if (name.equals("volume")) {
291c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            if (isOpen()) {
292c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                mMediaPlayer.setVolume(mVolume, mVolume);
293c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            }
2944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
2954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
2964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2971df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala    synchronized public void pauseVideo(boolean pauseState) {
2986aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        if (isOpen()) {
2996aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            if (pauseState && !mPaused) {
3006aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                mMediaPlayer.pause();
3016aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            } else if (!pauseState && mPaused) {
3026aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                mMediaPlayer.start();
3036aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            }
3046aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        }
3051df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        mPaused = pauseState;
3061df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala    }
3071df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala
3084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** Creates a media player, sets it up, and calls prepare */
3092dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    synchronized private boolean setupMediaPlayer(boolean useUrl) {
3104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mPrepared = false;
3114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mGotSize = false;
3124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mPlaying = false;
3136aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        mPaused = false;
314c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        mCompleted = false;
315c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala
316c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Setting up playback.");
3174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaPlayer != null) {
3194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            // Clean up existing media player
320c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "Resetting existing MediaPlayer.");
3214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.reset();
3224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        } else {
3234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            // Create new media player
324c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "Creating new MediaPlayer.");
3254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer = new MediaPlayer();
3264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaPlayer == null) {
329c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            throw new RuntimeException("Unable to create a MediaPlayer!");
3304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Set up data sources, etc
3334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        try {
3342dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (useUrl) {
335c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to URI " + mSourceUrl);
3364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mMediaPlayer.setDataSource(mSourceUrl);
3374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
338c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to asset " + mSourceAsset);
3394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength());
3404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        } catch(IOException e) {
342c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            mMediaPlayer.release();
343c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            mMediaPlayer = null;
3442dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (useUrl) {
345c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                throw new RuntimeException(String.format("Unable to set MediaPlayer to URL %s!", mSourceUrl), e);
3464a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
347c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                throw new RuntimeException(String.format("Unable to set MediaPlayer to asset %s!", mSourceAsset), e);
3484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
349c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        } catch(IllegalArgumentException e) {
3504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.release();
3514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer = null;
3522dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (useUrl) {
353c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                throw new RuntimeException(String.format("Unable to set MediaPlayer to URL %s!", mSourceUrl), e);
3544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
355c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                throw new RuntimeException(String.format("Unable to set MediaPlayer to asset %s!", mSourceAsset), e);
3564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setLooping(mLooping);
360c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        mMediaPlayer.setVolume(mVolume, mVolume);
3614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Bind it to our media frame
3634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setTexture(mSurfaceTexture);
3644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Connect Media Player to callbacks
3664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
3684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setOnPreparedListener(onPreparedListener);
3694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setOnCompletionListener(onCompletionListener);
3704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Connect SurfaceTexture to callback
3724a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mSurfaceTexture.setOnFrameAvailableListener(onMediaFrameAvailableListener);
3734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
374c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Preparing MediaPlayer.");
3754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.prepareAsync();
3764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
37721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        return true;
3784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
3794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener =
3814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new MediaPlayer.OnVideoSizeChangedListener() {
3824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
3838dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "MediaPlayer sent dimensions: " + width + " x " + height);
3844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            if (!mGotSize) {
3854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mOutputFormat.setDimensions(width, height);
3864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
3874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                if (mOutputFormat.getWidth() != width ||
3884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                    mOutputFormat.getHeight() != height) {
3894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                    Log.e(TAG, "Multiple video size change events received!");
3904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                }
3914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            synchronized(this) {
3934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mGotSize = true;
3944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                this.notify();
3954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
3984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer.OnPreparedListener onPreparedListener =
4004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new MediaPlayer.OnPreparedListener() {
4014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onPrepared(MediaPlayer mp) {
4028dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "MediaPlayer is prepared");
4034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            synchronized(this) {
4044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mPrepared = true;
4054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                this.notify();
4064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
4074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
4084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
4094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
4104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer.OnCompletionListener onCompletionListener =
4114a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new MediaPlayer.OnCompletionListener() {
4124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onCompletion(MediaPlayer mp) {
4138dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "MediaPlayer has completed playback");
414c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            synchronized(this) {
415c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala                mCompleted = true;
416c8afe66093a29852779745ddf7c45dee6f0dc414Eino-Ville Talvala            }
4174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
4184a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
4194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
4204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private SurfaceTexture.OnFrameAvailableListener onMediaFrameAvailableListener =
4214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new SurfaceTexture.OnFrameAvailableListener() {
4224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onFrameAvailable(SurfaceTexture surfaceTexture) {
4238dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "New frame from media player");
4244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mNewFrameAvailable.open();
4254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
4264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
4274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
4284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala}
429