MediaSource.java revision 2dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1
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
612dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    /** An open asset file descriptor to a local media source. Default is null */
6221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "sourceAsset", hasDefault = true)
639b393be2b4b7e70abe38237ba3eda3dc009d6230Eino-Ville Talvala    private AssetFileDescriptor mSourceAsset = null;
644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** Whether the filter will always wait for a new video frame, or whether it
664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala     * will output an old frame again if a new frame isn't available. Defaults to true.
674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala     */
6821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFinalPort(name = "waitForNewFrame", hasDefault = true)
694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mWaitForNewFrame = true;
704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** Whether the media source should loop automatically or not. Defaults to true. */
7221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "loop", hasDefault = true)
734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mLooping = true;
744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
752dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    /** Whether the media source is a URL or an asset file descriptor. Defaults to false. */
762dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    @GenerateFieldPort(name = "sourceIsUrl", hasDefault = true)
772dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    private boolean mSelectedIsUrl = false;
782dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen
794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer mMediaPlayer;
804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private GLFrame mMediaFrame;
814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private SurfaceTexture mSurfaceTexture;
824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private ShaderProgram mFrameExtractor;
834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MutableFrameFormat mOutputFormat;
844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private ConditionVariable mNewFrameAvailable;
854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private float[] mFrameTransform;
864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private final String mFrameShader =
884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "#extension GL_OES_EGL_image_external : require\n" +
894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "precision mediump float;\n" +
904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "uniform mat4 frame_transform;\n" +
914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "uniform samplerExternalOES tex_sampler_0;\n" +
924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "varying vec2 v_texcoord;\n" +
934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "void main() {\n" +
944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "  vec2 transformed_texcoord = (frame_transform * vec4(v_texcoord, 0., 1.) ).xy;" +
954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "  gl_FragColor = texture2D(tex_sampler_0, transformed_texcoord);\n" +
964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            "}\n";
974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mGotSize;
994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mPrepared;
1004a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private boolean mPlaying;
1011df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala    private boolean mPaused;
1024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1038dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala    private final boolean mLogVerbose;
1044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private static final String TAG = "MediaSource";
1054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    public MediaSource(String name) {
1074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        super(name);
1084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mNewFrameAvailable = new ConditionVariable();
1094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mFrameTransform = new float[16];
1108dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala
1118dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
1124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
11521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void setupPorts() {
11621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        // Add input port
11721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        addOutputPort("video", ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
11821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                                                  FrameFormat.TARGET_GPU));
1194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1204a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
12121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    private void createFormats() {
12221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        mOutputFormat = ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
12321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                                           FrameFormat.TARGET_GPU);
1244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
1274a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    protected void prepare(FilterContext context) {
1288dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Preparing MediaSource");
1294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mFrameExtractor = new ShaderProgram(mFrameShader);
1314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // SurfaceTexture defines (0,0) to be bottom-left. The filter framework
1324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // defines (0,0) as top-left, so do the flip here.
1334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mFrameExtractor.setSourceRect(0, 1, 1, -1);
1344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
13521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        createFormats();
13621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn
137edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala        mMediaFrame = (GLFrame)context.getFrameManager().newBoundFrame(mOutputFormat,
138edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala                                                                       GLFrame.EXTERNAL_TEXTURE,
139edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala                                                                       0);
1404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mSurfaceTexture = new SurfaceTexture(mMediaFrame.getTextureId());
1412dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen
1424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
14521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void open(FilterContext context) {
1468dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Opening MediaSource");
1472dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        if (mLogVerbose) {
1482dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          if (mSelectedIsUrl) {
1492dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            Log.v(TAG, "Current URL is " + mSourceUrl);
1502dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          } else {
1512dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            Log.v(TAG, "Current source is Asset!");
1522dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          }
1532dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        }
1542dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        if (!setupMediaPlayer(mSelectedIsUrl)) {
1552dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen          throw new RuntimeException("Error setting up MediaPlayer!");
15621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        }
1574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
1584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
16021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void process(FilterContext context) {
1616aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        // Note: process is synchronized by its caller in the Filter base class
1628dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Processing new frame");
1634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaPlayer == null) {
1654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            // Something went wrong in initialization or parameter updates
16621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn            throw new NullPointerException("Unexpected null media player!");
1674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
1684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (!mPlaying) {
1706aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            int waitCount = 0;
1716aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            while (!mGotSize || !mPrepared) {
1726aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                try {
17321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                        this.wait(100);
1746aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                } catch (InterruptedException e) {
1756aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                    // ignoring
1766aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                }
1776aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                waitCount++;
1786aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                if (waitCount == 50) {
1796aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                    mMediaPlayer.release();
18021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                    throw new RuntimeException("MediaPlayer timed out while preparing!");
1814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                }
1824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
1834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.start();
1844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
1854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1861df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        // Use last frame if paused, unless just starting playback, in which case
1871df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        // we want at least one valid frame before pausing
1881df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        if (!mPaused || !mPlaying) {
1891df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            if (mWaitForNewFrame) {
1901df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                boolean gotNewFrame;
1911df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                gotNewFrame = mNewFrameAvailable.block(1000);
1921df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                if (!gotNewFrame) {
19321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                    throw new RuntimeException("Timeout waiting for new frame!");
1941df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                }
1951df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala                mNewFrameAvailable.close();
1964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
1974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
1981df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            mSurfaceTexture.updateTexImage();
1994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2001df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            mSurfaceTexture.getTransformMatrix(mFrameTransform);
2011df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala            mFrameExtractor.setHostValue("frame_transform", mFrameTransform);
2021df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        }
2034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        Frame output = context.getFrameManager().newFrame(mOutputFormat);
2054a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mFrameExtractor.process(mMediaFrame, output);
2064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2078dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        long timestamp = mSurfaceTexture.getTimestamp();
2088dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Timestamp: " + (timestamp / 1000000000.0) + " s");
2098dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        output.setTimestamp(timestamp);
2108dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala
21121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        pushOutput("video", output);
2124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        output.release();
2134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2141df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        mPlaying = true;
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;
2248dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) 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
2342dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    // When updating the port values of the filter, users can update sourceIsUrl to switch
2352dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    //   between using URL objects or Assets.
2362dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    // If updating only sourceUrl/sourceAsset, MediaPlayer gets reset if the current player
2372dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    //   uses Url objects/Asset.
2382dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    // Otherwise the new sourceUrl/sourceAsset is stored and will be used when users switch
2392dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    //   sourceIsUrl next time.
2404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    @Override
24121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void fieldPortValueUpdated(String name, FilterContext context) {
2422dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        if (name.equals("sourceUrl")) {
2432dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen           if (isOpen()) {
2448dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala                if (mLogVerbose) Log.v(TAG, "Opening new source URL");
2452dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (mSelectedIsUrl) {
2462dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    setupMediaPlayer(mSelectedIsUrl);
2472dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                }
2484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
24921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        } else if (name.equals("sourceAsset") ) {
2504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            if (isOpen()) {
2512dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (mLogVerbose) Log.v(TAG, "Opening new source FD");
2522dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (!mSelectedIsUrl) {
2532dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    setupMediaPlayer(mSelectedIsUrl);
2544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                }
2554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
25621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        } else if (name.equals("loop")) {
2574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            if (isOpen()) {
25821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                mMediaPlayer.setLooping(mLooping);
2594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
2602dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen        } else if (name.equals("sourceIsUrl")) {
2612dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (isOpen()){
2622dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                if (mSelectedIsUrl){
2632dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    if (mLogVerbose) Log.v(TAG, "Opening new source URL");
2642dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                } else {
2652dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                    if (mLogVerbose) Log.v(TAG, "Opening new source Asset");
2662dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                }
2672dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen                setupMediaPlayer(mSelectedIsUrl);
2682dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            }
2694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
2704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
2714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2721df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala    synchronized public void pauseVideo(boolean pauseState) {
2736aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        if (isOpen()) {
2746aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            if (pauseState && !mPaused) {
2756aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                mMediaPlayer.pause();
2766aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            } else if (!pauseState && mPaused) {
2776aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala                mMediaPlayer.start();
2786aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala            }
2796aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        }
2801df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala        mPaused = pauseState;
2811df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala    }
2821df612099dde7e43249468d46e5b8064d8c33b77Eino-Ville Talvala
2834a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    /** Creates a media player, sets it up, and calls prepare */
2842dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen    synchronized private boolean setupMediaPlayer(boolean useUrl) {
2854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mPrepared = false;
2864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mGotSize = false;
2874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mPlaying = false;
2886aa4072be405da80b7abcc732befe819cfa932eaEino-Ville Talvala        mPaused = false;
2894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2904a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaPlayer != null) {
2914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            // Clean up existing media player
2924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.reset();
2934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        } else {
2944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            // Create new media player
2954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer = new MediaPlayer();
2964a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
2974a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
2984a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        if (mMediaPlayer == null) {
2994a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            Log.e(TAG, "Unable to create a media player!");
30021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn            return false;
3014a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3024a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3034a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Set up data sources, etc
3044a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        try {
3052dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (useUrl) {
3064a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mMediaPlayer.setDataSource(mSourceUrl);
3074a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
3084a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength());
3094a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3104a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        } catch(IOException e) {
3112dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (useUrl) {
3124a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e);
3134a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
3144a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e);
3154a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3164a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.release();
3174a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer = null;
31821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn            return false;
3194a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        } catch(IllegalArgumentException e) {
3202dfe9bbf05b260944ef5fa42aa5dfd2fd312aba1Christine Chen            if (useUrl) {
3214a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                Log.e(TAG, "Unable to set media player source to " + mSourceUrl + ". Exception: " + e);
3224a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
3234a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                Log.e(TAG, "Unable to set media player source to " + mSourceAsset + ". Exception: " + e);
3244a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3254a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer.release();
3264a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mMediaPlayer = null;
32721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn            return false;
3284a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3294a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3304a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setLooping(mLooping);
3314a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3324a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Bind it to our media frame
3334a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setTexture(mSurfaceTexture);
3344a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3354a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Connect Media Player to callbacks
3364a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3374a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
3384a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setOnPreparedListener(onPreparedListener);
3394a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.setOnCompletionListener(onCompletionListener);
3404a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3414a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        // Connect SurfaceTexture to callback
3424a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mSurfaceTexture.setOnFrameAvailableListener(onMediaFrameAvailableListener);
3434a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3444a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        mMediaPlayer.prepareAsync();
3454a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3468dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "MediaPlayer now preparing.");
34721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        return true;
3484a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    }
3494a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3504a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener =
3514a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new MediaPlayer.OnVideoSizeChangedListener() {
3524a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
3538dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "MediaPlayer sent dimensions: " + width + " x " + height);
3544a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            if (!mGotSize) {
3554a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mOutputFormat.setDimensions(width, height);
3564a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            } else {
3574a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                if (mOutputFormat.getWidth() != width ||
3584a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                    mOutputFormat.getHeight() != height) {
3594a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                    Log.e(TAG, "Multiple video size change events received!");
3604a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                }
3614a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3624a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            synchronized(this) {
3634a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mGotSize = true;
3644a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                this.notify();
3654a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3664a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3674a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
3684a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3694a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer.OnPreparedListener onPreparedListener =
3704a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new MediaPlayer.OnPreparedListener() {
3714a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onPrepared(MediaPlayer mp) {
3728dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "MediaPlayer is prepared");
3734a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            synchronized(this) {
3744a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                mPrepared = true;
3754a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala                this.notify();
3764a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            }
3774a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3784a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
3794a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3804a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private MediaPlayer.OnCompletionListener onCompletionListener =
3814a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new MediaPlayer.OnCompletionListener() {
3824a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onCompletion(MediaPlayer mp) {
3838dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "MediaPlayer has completed playback");
3844a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3854a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
3864a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3874a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    private SurfaceTexture.OnFrameAvailableListener onMediaFrameAvailableListener =
3884a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            new SurfaceTexture.OnFrameAvailableListener() {
3894a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        public void onFrameAvailable(SurfaceTexture surfaceTexture) {
3908dd704358d808382465666354fc891af59b21e18Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "New frame from media player");
3914a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala            mNewFrameAvailable.open();
3924a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala        }
3934a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala    };
3944a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala
3954a0c538853d7858d59cbc7f4dc7ece5d942e0b7cEino-Ville Talvala}
396