package io.myweb.camera; import android.content.Context; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.util.Log; import java.io.FileDescriptor; import java.io.IOException; import io.myweb.LocalService; public class StreamingService extends LocalService<Streaming> implements Streaming, MediaRecorder.OnErrorListener { private static final String LOG_TAG = CaptureCamera.class.getSimpleName(); public static final int BUFFER_SIZE = 32 * 1024; public static final int SO_TIMEOUT = 5000; private static final int HIDDEN_MPEG_TS = 8; private MediaRecorder mediaRecorder; private Camera camera; private LocalSocket receiverSocket; private LocalSocket senderSocket; private LocalServerSocket serverSocket; private volatile InputStreamListener inputListener; private volatile boolean streaming; public StreamingService() { streaming = false; } public static Connection<Streaming> connection(Context ctx) { return new Connection<Streaming>(ctx, StreamingService.class); } @Override public void startStreaming(Camera cam) { Log.d(LOG_TAG, "Starting streaming"); if (inputListener != null && cam != null) try { camera = cam; createLocalSockets(); startMediaRecorder(senderSocket.getFileDescriptor()); streaming = true; inputListener.onInputStreamReady(receiverSocket.getInputStream()); Log.d(LOG_TAG, "Streaming started."); } catch (Exception e) { e.printStackTrace(); stopStreaming(); } } @Override public void stopStreaming() { Log.d(LOG_TAG, "Stopping streaming"); stopMediaRecorder(); destroyLocalSockets(); streaming = false; } @Override public boolean isStreaming() { return streaming; } @Override public void setInputStreamListener(InputStreamListener listener) { inputListener = listener; } protected String localName() { return getClass().getName()+"-"+this.hashCode(); } protected void createLocalSockets() throws IOException { Log.d(LOG_TAG, "Binding to " + localName()); serverSocket = new LocalServerSocket(localName()); receiverSocket = new LocalSocket(); receiverSocket.connect(new LocalSocketAddress(localName())); receiverSocket.setReceiveBufferSize(BUFFER_SIZE); receiverSocket.setSoTimeout(SO_TIMEOUT); senderSocket = serverSocket.accept(); senderSocket.setSendBufferSize(BUFFER_SIZE); } protected void destroyLocalSockets() { try { if (receiverSocket!=null) receiverSocket.close(); } catch (Exception e) { e.printStackTrace(); } try { if(senderSocket!=null) senderSocket.close(); } catch (Exception e) { e.printStackTrace(); } try { if(serverSocket!=null) serverSocket.close(); } catch (Exception e) { e.printStackTrace(); } receiverSocket = null; senderSocket = null; serverSocket = null; } // private static String dump(Object obj) { // StringBuilder sb = new StringBuilder(); // for(Field f: obj.getClass().getDeclaredFields()) { // try { // sb.append(f.getName()+":\t"+f.get(obj).toString()+"\n"); // } catch (IllegalAccessException e) { //// e.printStackTrace(); // } // } // return sb.toString(); // } private void startMediaRecorder(FileDescriptor fd) throws IllegalStateException, IOException { mediaRecorder = new MediaRecorder(); // Step 1: Unlock and set camera to MediaRecorder camera.stopPreview(); camera.unlock(); mediaRecorder.setCamera(camera); // Step 2: Set source mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P); // profile.videoFrameRate = 25; // Log.d(LOG_TAG, "Profile: "+dump(profile)); profile.fileFormat = HIDDEN_MPEG_TS; mediaRecorder.setProfile(profile); // Step 4: Set output file mediaRecorder.setOutputFile(fd); mediaRecorder.setOnErrorListener(this); // mediaRecorder.setPreviewDisplay(); // Step 5: Prepare configured MediaRecorder mediaRecorder.prepare(); // it takes some time to prepare try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // Step 6: Start the recording mediaRecorder.start(); } private void stopMediaRecorder() { if (camera!=null) { camera.lock(); camera = null; } if (mediaRecorder != null) { try { mediaRecorder.stop(); } catch (Exception e) { Log.e(LOG_TAG, e.getMessage(), e); } mediaRecorder.reset(); // clear recorder configuration mediaRecorder.release(); // release the recorder object mediaRecorder = null; } } @Override public void onError(MediaRecorder mediaRecorder, int width, int height) { stopStreaming(); } }