MediaEncoderFilter.java revision f283a907a88fc348b770186562c7a1046a8b7367
184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi/*
284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * Copyright (C) 2011 The Android Open Source Project
384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi *
484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * Licensed under the Apache License, Version 2.0 (the "License");
584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * you may not use this file except in compliance with the License.
684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * You may obtain a copy of the License at
784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi *
884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi *      http://www.apache.org/licenses/LICENSE-2.0
984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi *
1084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * Unless required by applicable law or agreed to in writing, software
1184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * distributed under the License is distributed on an "AS IS" BASIS,
1284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * See the License for the specific language governing permissions and
1484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi * limitations under the License.
1584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi */
1684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
1784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
1884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketipackage android.filterpacks.videosink;
1984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
2084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.content.Context;
2184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.Filter;
2284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.FilterContext;
2384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.Frame;
2484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.FrameFormat;
2584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.FrameManager;
2684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.GenerateFieldPort;
2784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.GenerateFinalPort;
2884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.GLFrame;
2984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.KeyValueMap;
3084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.MutableFrameFormat;
3184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.NativeFrame;
3284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.Program;
3384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.ShaderProgram;
3484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.format.ImageFormat;
3584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.os.ConditionVariable;
3684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.media.MediaRecorder;
3784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.filterfw.core.GLEnvironment;
3884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
3984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport java.io.IOException;
4084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport java.util.List;
4184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport java.util.Set;
4284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
4384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiimport android.util.Log;
4484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
4584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi/** @hide */
4684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketipublic class MediaEncoderFilter extends Filter {
4784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
4884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    /** User-visible parameters */
4984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
5084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    /** Frame width to be encoded.
5184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi     * Actual received frame size has to match this */
5284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @GenerateFieldPort(name = "width", hasDefault = false)
5384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private int mWidth;
5484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
5584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    /** Frame height to to be encoded.
5684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi     * Actual received frame size has to match */
5784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @GenerateFieldPort(name = "height", hasDefault = false)
5884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private int mHeight;
5984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
6084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    /** Stream framerate to encode the frames at.
6184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi     * By default, frames are encoded at 30 FPS*/
6284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @GenerateFieldPort(name = "framerate", hasDefault = true)
6384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private int mFps = 30;
6484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
6584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
6684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    /** Filename to save the output. */
6784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @GenerateFieldPort(name = "outputFile", hasDefault = true)
68f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi    private String mOutputFile = new String("/sdcard/MediaEncoderOut.mp4");
6984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
7084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    /** The output format to encode the frames in.
7184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi     * Choose an output format from the options in
7284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi     * android.media.MediaRecorder.OutputFormat */
7384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @GenerateFieldPort(name = "outputFormat", hasDefault = true)
74f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi    private int mOutputFormat = MediaRecorder.OutputFormat.MPEG_4;
7584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
7684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    /** The videoencoder to encode the frames with.
7784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi     * Choose a videoencoder from the options in
7884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi     * android.media.MediaRecorder.VideoEncoder */
7984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @GenerateFieldPort(name = "videoEncoder", hasDefault = true)
8084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private int mVideoEncoder = MediaRecorder.VideoEncoder.H264;
8184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
8284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // End of user visible parameters
8384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
8484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private int mSurfaceId;
8584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private ShaderProgram mProgram;
8684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private GLFrame mScreen;
8784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
8884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private boolean mLogVerbose;
8984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private static final String TAG = "MediaEncoderFilter";
9084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
9184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // Our hook to the encoder
9284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private MediaRecorder mMediaRecorder = new MediaRecorder();
9384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
9484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public MediaEncoderFilter(String name) {
9584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        super(name);
9684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
9784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
9884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
9984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @Override
10084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public void setupPorts() {
10184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Add input port- will accept RGBA GLFrames
10284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        addMaskedInputPort("videoframe", ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
10384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                                      FrameFormat.TARGET_GPU));
10484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
10584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
10684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @Override
10784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public void fieldPortValueUpdated(String name, FilterContext context) {
10884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        if (isOpen()) {
10984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi            throw new RuntimeException("Cannot change filter parameter"
11084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                    + "values when the filter is open!");
11184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        }
11284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        updateMediaRecorderParams();
11384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
11484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
11584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // update the MediaRecorderParams based on the variables.
11684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // These have to be in certain order as per the MediaRecorder
11784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // documentation
11884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    private void updateMediaRecorderParams() {
11984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        final int GRALLOC_BUFFER = 2;
12084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.setVideoSource(GRALLOC_BUFFER);
12184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.setOutputFormat(mOutputFormat);
12284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.setVideoEncoder(mVideoEncoder);
12384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.setOutputFile(mOutputFile);
12484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.setVideoSize(mWidth, mHeight);
12584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.setVideoFrameRate(mFps);
12684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
12784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
12884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @Override
12984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public void prepare(FilterContext context) {
13084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        if (mLogVerbose) Log.v(TAG, "Preparing");
13184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Setup the MediaRecorder correctly
13284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        updateMediaRecorderParams();
13384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
13484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Create identity shader to render, and make sure to render upside-down, as textures
13584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // are stored internally bottom-to-top.
13684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mProgram = ShaderProgram.createIdentity(context);
13784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mProgram.setSourceRect(0, 1, 1, -1);
13884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
13984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Create a frame representing the screen
14084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        MutableFrameFormat screenFormat = new MutableFrameFormat(
14184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                              FrameFormat.TYPE_BYTE, FrameFormat.TARGET_GPU);
14284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        screenFormat.setBytesPerSample(4);
14384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        screenFormat.setDimensions(mWidth, mHeight);
14484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mScreen = (GLFrame)context.getFrameManager().newBoundFrame(
14584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                           screenFormat, GLFrame.EXISTING_FBO_BINDING, 0);
14684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
14784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
14884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @Override
14984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public void open(FilterContext context) {
15084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        if (mLogVerbose) Log.v(TAG, "Opening");
15184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        try {
15284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi            mMediaRecorder.prepare();
15384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        } catch (IllegalStateException e) {
15484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi            throw e;
15584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        } catch (IOException e) {
15684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi            throw new RuntimeException("IOException in"
15784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                    + "MediaRecorder.prepare()!", e);
15884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        } catch (Exception e) {
15984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi            throw new RuntimeException("Unknown Exception in"
16084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                    + "MediaRecorder.prepare()!", e);
16184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        }
16284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Make sure start() is called before trying to
16384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // register the surface. The native window handle needed to create
16484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // the surface is initiated in start()
16584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.start();
166f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        Log.v(TAG, "ME Filter: Open: registering surface from Mediarecorder");
16784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mSurfaceId = context.getGLEnvironment().
168f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi                 registerSurfaceFromMediaRecorder(mMediaRecorder);
16984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
17084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
17184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @Override
17284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public void process(FilterContext context) {
17384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        if (mLogVerbose) Log.v(TAG, "Starting frame processing");
17484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
17584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        GLEnvironment glEnv = context.getGLEnvironment();
17684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Get input frame
17784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        Frame input = pullInput("videoframe");
17884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
17984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Activate our surface
18084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        glEnv.activateSurfaceWithId(mSurfaceId);
18184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
18284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Process
18384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mProgram.process(input, mScreen);
18484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
18584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // And swap buffers
18684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        glEnv.swapBuffers();
18784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
18884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
18984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @Override
19084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public void close(FilterContext context) {
19184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        if (mLogVerbose) Log.v(TAG, "Closing");
192f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        GLEnvironment glEnv = context.getGLEnvironment();
193f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        glEnv.disconnectSurfaceMediaSource(mMediaRecorder);
19484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        mMediaRecorder.stop();
19584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        context.getGLEnvironment().unregisterSurfaceId(mSurfaceId);
19684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
19784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
19884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    @Override
19984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    public void tearDown(FilterContext context) {
20084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // Release all the resources associated with the MediaRecorder
20184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        // and GLFrame members
20284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        if (mMediaRecorder != null) {
20384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi            mMediaRecorder.release();
20484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        }
20584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        if (mScreen != null) {
20684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi            mScreen.release();
20784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        }
20884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
20984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
21084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi}
211