Android Open Source - spydroid-ipcamera Video Stream






From Project

Back to project page spydroid-ipcamera.

License

The source code is released under:

GNU General Public License

If you think the Android project spydroid-ipcamera listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com
 * /*w w  w  . j a  va 2 s.  c  o  m*/
 * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
 * 
 * Spydroid is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This source code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this source code; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package net.majorkernelpanic.streaming.video;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import net.majorkernelpanic.streaming.MediaStream;
import net.majorkernelpanic.streaming.Stream;
import net.majorkernelpanic.streaming.exceptions.CameraInUseException;
import net.majorkernelpanic.streaming.exceptions.ConfNotSupportedException;
import net.majorkernelpanic.streaming.exceptions.InvalidSurfaceException;
import net.majorkernelpanic.streaming.gl.SurfaceView;
import net.majorkernelpanic.streaming.hw.EncoderDebugger;
import net.majorkernelpanic.streaming.hw.NV21Convertor;
import net.majorkernelpanic.streaming.rtp.MediaCodecInputStream;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.os.Looper;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;

/** 
 * Don't use this class directly.
 */
public abstract class VideoStream extends MediaStream {

  protected final static String TAG = "VideoStream";

  protected VideoQuality mRequestedQuality = VideoQuality.DEFAULT_VIDEO_QUALITY.clone();
  protected VideoQuality mQuality = mRequestedQuality.clone(); 
  protected SurfaceHolder.Callback mSurfaceHolderCallback = null;
  protected SurfaceView mSurfaceView = null;
  protected SharedPreferences mSettings = null;
  protected int mVideoEncoder, mCameraId = 0;
  protected int mRequestedOrientation = 0, mOrientation = 0;
  protected Camera mCamera;
  protected Thread mCameraThread;
  protected Looper mCameraLooper;

  protected boolean mCameraOpenedManually = true;
  protected boolean mFlashEnabled = false;
  protected boolean mSurfaceReady = false;
  protected boolean mUnlocked = false;
  protected boolean mPreviewStarted = false;

  protected String mMimeType;
  protected String mEncoderName;
  protected int mEncoderColorFormat;
  protected int mCameraImageFormat;
  protected int mMaxFps = 0;  

  /** 
   * Don't use this class directly.
   * Uses CAMERA_FACING_BACK by default.
   */
  public VideoStream() {
    this(CameraInfo.CAMERA_FACING_BACK);
  }  

  /** 
   * Don't use this class directly
   * @param camera Can be either CameraInfo.CAMERA_FACING_BACK or CameraInfo.CAMERA_FACING_FRONT
   */
  @SuppressLint("InlinedApi")
  public VideoStream(int camera) {
    super();
    setCamera(camera);
  }

  /**
   * Sets the camera that will be used to capture video.
   * You can call this method at any time and changes will take effect next time you start the stream.
   * @param camera Can be either CameraInfo.CAMERA_FACING_BACK or CameraInfo.CAMERA_FACING_FRONT
   */
  public void setCamera(int camera) {
    CameraInfo cameraInfo = new CameraInfo();
    int numberOfCameras = Camera.getNumberOfCameras();
    for (int i=0;i<numberOfCameras;i++) {
      Camera.getCameraInfo(i, cameraInfo);
      if (cameraInfo.facing == camera) {
        mCameraId = i;
        break;
      }
    }
  }

  /**  Switch between the front facing and the back facing camera of the phone. 
   * If {@link #startPreview()} has been called, the preview will be  briefly interrupted. 
   * If {@link #start()} has been called, the stream will be  briefly interrupted.
   * You should not call this method from the main thread if you are already streaming. 
   * @throws IOException 
   * @throws RuntimeException 
   **/
  public void switchCamera() throws RuntimeException, IOException {
    if (Camera.getNumberOfCameras() == 1) throw new IllegalStateException("Phone only has one camera !");
    boolean streaming = mStreaming;
    boolean previewing = mCamera!=null && mCameraOpenedManually; 
    mCameraId = (mCameraId == CameraInfo.CAMERA_FACING_BACK) ? CameraInfo.CAMERA_FACING_FRONT : CameraInfo.CAMERA_FACING_BACK; 
    setCamera(mCameraId);
    stopPreview();
    mFlashEnabled = false;
    if (previewing) startPreview();
    if (streaming) start(); 
  }

  public int getCamera() {
    return mCameraId;
  }

  /**
   * Sets a Surface to show a preview of recorded media (video). 
   * You can call this method at any time and changes will take effect next time you call {@link #start()}.
   */
  public synchronized void setSurfaceView(SurfaceView view) {
    mSurfaceView = view;
    if (mSurfaceHolderCallback != null && mSurfaceView != null && mSurfaceView.getHolder() != null) {
      mSurfaceView.getHolder().removeCallback(mSurfaceHolderCallback);
    }
    if (mSurfaceView.getHolder() != null) {
      mSurfaceHolderCallback = new Callback() {
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
          mSurfaceReady = false;
          stopPreview();
          Log.d(TAG,"Surface destroyed !");
        }
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
          mSurfaceReady = true;
        }
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
          Log.d(TAG,"Surface Changed !");
        }
      };
      mSurfaceView.getHolder().addCallback(mSurfaceHolderCallback);
      mSurfaceReady = true;
    }
  }

  /** Turns the LED on or off if phone has one. */
  public synchronized void setFlashState(boolean state) {
    // If the camera has already been opened, we apply the change immediately
    if (mCamera != null) {

      if (mStreaming && mMode == MODE_MEDIARECORDER_API) {
        lockCamera();
      }

      Parameters parameters = mCamera.getParameters();

      // We test if the phone has a flash
      if (parameters.getFlashMode()==null) {
        // The phone has no flash or the choosen camera can not toggle the flash
        throw new RuntimeException("Can't turn the flash on !");
      } else {
        parameters.setFlashMode(state?Parameters.FLASH_MODE_TORCH:Parameters.FLASH_MODE_OFF);
        try {
          mCamera.setParameters(parameters);
          mFlashEnabled = state;
        } catch (RuntimeException e) {
          mFlashEnabled = false;
          throw new RuntimeException("Can't turn the flash on !");
        } finally {
          if (mStreaming && mMode == MODE_MEDIARECORDER_API) {
            unlockCamera();
          }
        }
      }
    } else {
      mFlashEnabled = state;
    }
  }

  /** Toggle the LED of the phone if it has one. */
  public synchronized void toggleFlash() {
    setFlashState(!mFlashEnabled);
  }

  /** Indicates whether or not the flash of the phone is on. */
  public boolean getFlashState() {
    return mFlashEnabled;
  }

  /** 
   * Sets the orientation of the preview.
   * @param orientation The orientation of the preview
   */
  public void setPreviewOrientation(int orientation) {
    mRequestedOrientation = orientation;
  }
  
  
  /** 
   * Sets the configuration of the stream. You can call this method at any time 
   * and changes will take effect next time you call {@link #configure()}.
   * @param videoQuality Quality of the stream
   */
  public void setVideoQuality(VideoQuality videoQuality) {
    mRequestedQuality = videoQuality.clone();
  }

  /** 
   * Returns the quality of the stream.  
   */
  public VideoQuality getVideoQuality() {
    return mRequestedQuality;
  }

  /**
   * Some data (SPS and PPS params) needs to be stored when {@link #getSessionDescription()} is called 
   * @param prefs The SharedPreferences that will be used to save SPS and PPS parameters
   */
  public void setPreferences(SharedPreferences prefs) {
    mSettings = prefs;
  }

  /**
   * Configures the stream. You need to call this before calling {@link #getSessionDescription()} 
   * to apply your configuration of the stream.
   */
  public synchronized void configure() throws IllegalStateException, IOException {
    super.configure();
    mOrientation = mRequestedOrientation;
  }  
  
  /**
   * Starts the stream.
   * This will also open the camera and dispay the preview 
   * if {@link #startPreview()} has not aready been called.
   */
  public synchronized void start() throws IllegalStateException, IOException {
    if (!mPreviewStarted) mCameraOpenedManually = false;
    super.start();
    Log.d(TAG,"Stream configuration: FPS: "+mQuality.framerate+" Width: "+mQuality.resX+" Height: "+mQuality.resY);
  }

  /** Stops the stream. */
  public synchronized void stop() {
    if (mCamera != null) {
      if (mMode == MODE_MEDIACODEC_API) {
        mCamera.setPreviewCallbackWithBuffer(null);
      }
      if (mMode == MODE_MEDIACODEC_API_2) {
        ((SurfaceView)mSurfaceView).removeMediaCodecSurface();
      }
      super.stop();
      // We need to restart the preview
      if (!mCameraOpenedManually) {
        destroyCamera();
      } else {
        try {
          startPreview();
        } catch (RuntimeException e) {
          e.printStackTrace();
        }
      }
    }
  }

  public synchronized void startPreview() 
      throws CameraInUseException, 
      InvalidSurfaceException, 
      ConfNotSupportedException, 
      RuntimeException {
    
    mCameraOpenedManually = true;
    if (!mPreviewStarted) {
      createCamera();
      updateCamera();
      try {
        mCamera.startPreview();
        mPreviewStarted = true;
      } catch (RuntimeException e) {
        destroyCamera();
        throw e;
      }
    }
  }

  /**
   * Stops the preview.
   */
  public synchronized void stopPreview() {
    mCameraOpenedManually = false;
    stop();
  }

  /**
   * Video encoding is done by a MediaRecorder.
   */
  protected void encodeWithMediaRecorder() throws IOException {

    Log.d(TAG,"Video encoded using the MediaRecorder API");

    // We need a local socket to forward data output by the camera to the packetizer
    createSockets();

    // Reopens the camera if needed
    destroyCamera();
    createCamera();

    // The camera must be unlocked before the MediaRecorder can use it
    unlockCamera();

    try {
      mMediaRecorder = new MediaRecorder();
      mMediaRecorder.setCamera(mCamera);
      mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
      mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
      mMediaRecorder.setVideoEncoder(mVideoEncoder);
      mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());
      mMediaRecorder.setVideoSize(mRequestedQuality.resX,mRequestedQuality.resY);
      mMediaRecorder.setVideoFrameRate(mRequestedQuality.framerate);

      // The bandwidth actually consumed is often above what was requested 
      mMediaRecorder.setVideoEncodingBitRate((int)(mRequestedQuality.bitrate*0.8));

      // We write the ouput of the camera in a local socket instead of a file !      
      // This one little trick makes streaming feasible quiet simply: data from the camera
      // can then be manipulated at the other end of the socket
      mMediaRecorder.setOutputFile(mSender.getFileDescriptor());

      mMediaRecorder.prepare();
      mMediaRecorder.start();

    } catch (Exception e) {
      throw new ConfNotSupportedException(e.getMessage());
    }

    // This will skip the MPEG4 header if this step fails we can't stream anything :(
    InputStream is = mReceiver.getInputStream();
    try {
      byte buffer[] = new byte[4];
      // Skip all atoms preceding mdat atom
      while (!Thread.interrupted()) {
        while (is.read() != 'm');
        is.read(buffer,0,3);
        if (buffer[0] == 'd' && buffer[1] == 'a' && buffer[2] == 't') break;
      }
    } catch (IOException e) {
      Log.e(TAG,"Couldn't skip mp4 header :/");
      stop();
      throw e;
    }

    // The packetizer encapsulates the bit stream in an RTP stream and send it over the network
    mPacketizer.setDestination(mDestination, mRtpPort, mRtcpPort);
    mPacketizer.setInputStream(mReceiver.getInputStream());
    mPacketizer.start();

    mStreaming = true;

  }


  /**
   * Video encoding is done by a MediaCodec.
   */
  protected void encodeWithMediaCodec() throws RuntimeException, IOException {
    if (mMode == MODE_MEDIACODEC_API_2) {
      // Uses the method MediaCodec.createInputSurface to feed the encoder
      encodeWithMediaCodecMethod2();
    } else {
      // Uses dequeueInputBuffer to feed the encoder
      encodeWithMediaCodecMethod1();
    }
  }  

  /**
   * Video encoding is done by a MediaCodec.
   */
  @SuppressLint("NewApi")
  protected void encodeWithMediaCodecMethod1() throws RuntimeException, IOException {

    Log.d(TAG,"Video encoded using the MediaCodec API with a buffer");

    // Updates the parameters of the camera if needed
    createCamera();
    updateCamera();

    // Estimates the framerate of the camera
    measureFramerate();

    // Starts the preview if needed
    if (!mPreviewStarted) {
      try {
        mCamera.startPreview();
        mPreviewStarted = true;
      } catch (RuntimeException e) {
        destroyCamera();
        throw e;
      }
    }

    EncoderDebugger debugger = EncoderDebugger.debug(mSettings, mQuality.resX, mQuality.resY);
    final NV21Convertor convertor = debugger.getNV21Convertor();

    mMediaCodec = MediaCodec.createByCodecName(debugger.getEncoderName());
    MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", mQuality.resX, mQuality.resY);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, mQuality.bitrate);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mQuality.framerate);  
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,debugger.getEncoderColorFormat());
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
    mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mMediaCodec.start();

    Camera.PreviewCallback callback = new Camera.PreviewCallback() {
      long now = System.nanoTime()/1000, oldnow = now, i=0;
      ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();
      @Override
      public void onPreviewFrame(byte[] data, Camera camera) {
        oldnow = now;
        now = System.nanoTime()/1000;
        if (i++>3) {
          i = 0;
          //Log.d(TAG,"Measured: "+1000000L/(now-oldnow)+" fps.");
        }
        try {
          int bufferIndex = mMediaCodec.dequeueInputBuffer(500000);
          if (bufferIndex>=0) {
            inputBuffers[bufferIndex].clear();
            convertor.convert(data, inputBuffers[bufferIndex]);
            mMediaCodec.queueInputBuffer(bufferIndex, 0, inputBuffers[bufferIndex].position(), now, 0);
          } else {
            Log.e(TAG,"No buffer available !");
          }
        } finally {
          mCamera.addCallbackBuffer(data);
        }        
      }
    };

    for (int i=0;i<10;i++) mCamera.addCallbackBuffer(new byte[convertor.getBufferSize()]);
    mCamera.setPreviewCallbackWithBuffer(callback);

    // The packetizer encapsulates the bit stream in an RTP stream and send it over the network
    mPacketizer.setDestination(mDestination, mRtpPort, mRtcpPort);
    mPacketizer.setInputStream(new MediaCodecInputStream(mMediaCodec));
    mPacketizer.start();

    mStreaming = true;

  }

  /**
   * Video encoding is done by a MediaCodec.
   * But here we will use the buffer-to-surface methode
   */
  @SuppressLint({ "InlinedApi", "NewApi" })  
  protected void encodeWithMediaCodecMethod2() throws RuntimeException, IOException {

    Log.d(TAG,"Video encoded using the MediaCodec API with a surface");

    // Updates the parameters of the camera if needed
    createCamera();
    updateCamera();

    // Estimates the framerate of the camera
    measureFramerate();

    EncoderDebugger debugger = EncoderDebugger.debug(mSettings, mQuality.resX, mQuality.resY);

    mMediaCodec = MediaCodec.createByCodecName(debugger.getEncoderName());
    MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", mQuality.resX, mQuality.resY);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, mQuality.bitrate);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mQuality.framerate);  
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
    mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    Surface surface = mMediaCodec.createInputSurface();
    ((SurfaceView)mSurfaceView).addMediaCodecSurface(surface);
    mMediaCodec.start();

    // The packetizer encapsulates the bit stream in an RTP stream and send it over the network
    mPacketizer.setDestination(mDestination, mRtpPort, mRtcpPort);
    mPacketizer.setInputStream(new MediaCodecInputStream(mMediaCodec));
    mPacketizer.start();

    mStreaming = true;

  }

  /**
   * Returns a description of the stream using SDP. 
   * This method can only be called after {@link Stream#configure()}.
   * @throws IllegalStateException Thrown when {@link Stream#configure()} wa not called.
   */  
  public abstract String getSessionDescription() throws IllegalStateException;

  /**
   * Opens the camera in a new Looper thread so that the preview callback is not called from the main thread
   * If an exception is thrown in this Looper thread, we bring it back into the main thread.
   * @throws RuntimeException Might happen if another app is already using the camera.
   */
  private void openCamera() throws RuntimeException {
    final Semaphore lock = new Semaphore(0);
    final RuntimeException[] exception = new RuntimeException[1];
    mCameraThread = new Thread(new Runnable() {
      @Override
      public void run() {
        Looper.prepare();
        mCameraLooper = Looper.myLooper();
        try {
          mCamera = Camera.open(mCameraId);
        } catch (RuntimeException e) {
          exception[0] = e;
        } finally {
          lock.release();
          Looper.loop();
        }
      }
    });
    mCameraThread.start();
    lock.acquireUninterruptibly();
    if (exception[0] != null) throw new CameraInUseException(exception[0].getMessage());
  }

  protected synchronized void createCamera() throws RuntimeException {
    if (mSurfaceView == null)
      throw new InvalidSurfaceException("Invalid surface !");
    if (mSurfaceView.getHolder() == null || !mSurfaceReady) 
      throw new InvalidSurfaceException("Invalid surface !");

    if (mCamera == null) {
      openCamera();
      mUnlocked = false;
      mCamera.setErrorCallback(new Camera.ErrorCallback() {
        @Override
        public void onError(int error, Camera camera) {
          // On some phones when trying to use the camera facing front the media server will die
          // Whether or not this callback may be called really depends on the phone
          if (error == Camera.CAMERA_ERROR_SERVER_DIED) {
            // In this case the application must release the camera and instantiate a new one
            Log.e(TAG,"Media server died !");
            // We don't know in what thread we are so stop needs to be synchronized
            mCameraOpenedManually = false;
            stop();
          } else {
            Log.e(TAG,"Error unknown with the camera: "+error);
          }  
        }
      });

      try {

        // If the phone has a flash, we turn it on/off according to mFlashEnabled
        // setRecordingHint(true) is a very nice optimisation if you plane to only use the Camera for recording
        Parameters parameters = mCamera.getParameters();
        if (parameters.getFlashMode()!=null) {
          parameters.setFlashMode(mFlashEnabled?Parameters.FLASH_MODE_TORCH:Parameters.FLASH_MODE_OFF);
        }
        parameters.setRecordingHint(true);
        mCamera.setParameters(parameters);
        mCamera.setDisplayOrientation(mOrientation);

        try {
          if (mMode == MODE_MEDIACODEC_API_2) {
            mSurfaceView.startGLThread();
            mCamera.setPreviewTexture(mSurfaceView.getSurfaceTexture());
          } else {
            mCamera.setPreviewDisplay(mSurfaceView.getHolder());
          }
        } catch (IOException e) {
          throw new InvalidSurfaceException("Invalid surface !");
        }

      } catch (RuntimeException e) {
        destroyCamera();
        throw e;
      }

    }
  }

  protected synchronized void destroyCamera() {
    if (mCamera != null) {
      if (mStreaming) super.stop();
      lockCamera();
      mCamera.stopPreview();
      try {
        mCamera.release();
      } catch (Exception e) {
        Log.e(TAG,e.getMessage()!=null?e.getMessage():"unknown error");
      }
      mCamera = null;
      mCameraLooper.quit();
      mUnlocked = false;
      mPreviewStarted = false;
    }  
  }

  protected synchronized void updateCamera() throws RuntimeException {
    if (mPreviewStarted) {
      mPreviewStarted = false;
      mCamera.stopPreview();
    }

    Parameters parameters = mCamera.getParameters();
    mQuality = VideoQuality.determineClosestSupportedResolution(parameters, mQuality);
    int[] max = VideoQuality.determineMaximumSupportedFramerate(parameters);
    parameters.setPreviewFormat(mCameraImageFormat);
    parameters.setPreviewSize(mQuality.resX, mQuality.resY);
    parameters.setPreviewFpsRange(max[0], max[1]);

    try {
      mCamera.setParameters(parameters);
      mCamera.setDisplayOrientation(mOrientation);
      mCamera.startPreview();
      mPreviewStarted = true;
    } catch (RuntimeException e) {
      destroyCamera();
      throw e;
    }
  }

  protected void lockCamera() {
    if (mUnlocked) {
      Log.d(TAG,"Locking camera");
      try {
        mCamera.reconnect();
      } catch (Exception e) {
        Log.e(TAG,e.getMessage());
      }
      mUnlocked = false;
    }
  }

  protected void unlockCamera() {
    if (!mUnlocked) {
      Log.d(TAG,"Unlocking camera");
      try {  
        mCamera.unlock();
      } catch (Exception e) {
        Log.e(TAG,e.getMessage());
      }
      mUnlocked = true;
    }
  }


  /**
   * Computes the average frame rate at which the preview callback is called.
   * We will then use this average framerate with the MediaCodec.  
   * Blocks the thread in which this function is called.
   */
  private void measureFramerate() {
    final Semaphore lock = new Semaphore(0);

    final Camera.PreviewCallback callback = new Camera.PreviewCallback() {
      int i = 0, t = 0;
      long now, oldnow, count = 0;
      @Override
      public void onPreviewFrame(byte[] data, Camera camera) {
        i++;
        now = System.nanoTime()/1000;
        if (i>3) {
          t += now - oldnow;
          count++;
        }
        if (i>20) {
          mQuality.framerate = (int) (1000000/(t/count)+1);
          lock.release();
        }
        oldnow = now;
      }
    };

    mCamera.setPreviewCallback(callback);

    try {
      lock.tryAcquire(2,TimeUnit.SECONDS);
      Log.d(TAG,"Actual framerate: "+mQuality.framerate);
      if (mSettings != null) {
        Editor editor = mSettings.edit();
        editor.putInt(PREF_PREFIX+"fps"+mRequestedQuality.framerate+","+mCameraImageFormat+","+mRequestedQuality.resX+mRequestedQuality.resY, mQuality.framerate);
        editor.commit();
      }
    } catch (InterruptedException e) {}

    mCamera.setPreviewCallback(null);

  }  

}




Java Source Code List

net.majorkernelpanic.http.ModAssetServer.java
net.majorkernelpanic.http.ModInternationalization.java
net.majorkernelpanic.http.ModSSL.java
net.majorkernelpanic.http.TinyHttpServer.java
net.majorkernelpanic.spydroid.SpydroidApplication.java
net.majorkernelpanic.spydroid.Utilities.java
net.majorkernelpanic.spydroid.api.CustomHttpServer.java
net.majorkernelpanic.spydroid.api.CustomRtspServer.java
net.majorkernelpanic.spydroid.api.RequestHandler.java
net.majorkernelpanic.spydroid.ui.AboutFragment.java
net.majorkernelpanic.spydroid.ui.HandsetFragment.java
net.majorkernelpanic.spydroid.ui.OptionsActivity.java
net.majorkernelpanic.spydroid.ui.PreviewFragment.java
net.majorkernelpanic.spydroid.ui.SpydroidActivity.java
net.majorkernelpanic.spydroid.ui.TabletFragment.java
net.majorkernelpanic.streaming.MediaStream.java
net.majorkernelpanic.streaming.SessionBuilder.java
net.majorkernelpanic.streaming.Session.java
net.majorkernelpanic.streaming.Stream.java
net.majorkernelpanic.streaming.audio.AACStream.java
net.majorkernelpanic.streaming.audio.AMRNBStream.java
net.majorkernelpanic.streaming.audio.AudioQuality.java
net.majorkernelpanic.streaming.audio.AudioStream.java
net.majorkernelpanic.streaming.exceptions.CameraInUseException.java
net.majorkernelpanic.streaming.exceptions.ConfNotSupportedException.java
net.majorkernelpanic.streaming.exceptions.InvalidSurfaceException.java
net.majorkernelpanic.streaming.exceptions.StorageUnavailableException.java
net.majorkernelpanic.streaming.gl.SurfaceManager.java
net.majorkernelpanic.streaming.gl.SurfaceView.java
net.majorkernelpanic.streaming.gl.TextureManager.java
net.majorkernelpanic.streaming.hw.CodecManager.java
net.majorkernelpanic.streaming.hw.EncoderDebugger.java
net.majorkernelpanic.streaming.hw.NV21Convertor.java
net.majorkernelpanic.streaming.mp4.MP4Config.java
net.majorkernelpanic.streaming.mp4.MP4Parser.java
net.majorkernelpanic.streaming.rtcp.SenderReport.java
net.majorkernelpanic.streaming.rtp.AACADTSPacketizer.java
net.majorkernelpanic.streaming.rtp.AACLATMPacketizer.java
net.majorkernelpanic.streaming.rtp.AMRNBPacketizer.java
net.majorkernelpanic.streaming.rtp.AbstractPacketizer.java
net.majorkernelpanic.streaming.rtp.H263Packetizer.java
net.majorkernelpanic.streaming.rtp.H264Packetizer.java
net.majorkernelpanic.streaming.rtp.MediaCodecInputStream.java
net.majorkernelpanic.streaming.rtp.RtpSocket.java
net.majorkernelpanic.streaming.rtsp.RtspClient.java
net.majorkernelpanic.streaming.rtsp.RtspServer.java
net.majorkernelpanic.streaming.rtsp.UriParser.java
net.majorkernelpanic.streaming.video.CodecManager.java
net.majorkernelpanic.streaming.video.H263Stream.java
net.majorkernelpanic.streaming.video.H264Stream.java
net.majorkernelpanic.streaming.video.VideoQuality.java
net.majorkernelpanic.streaming.video.VideoStream.java