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