Add UsbMonitor
[rtmpclient.git] / app / src / main / java / ai / suanzi / rtmpclient / MyService.java
index 0d0136d..cba2c42 100644 (file)
@@ -2,43 +2,37 @@ package ai.suanzi.rtmpclient;
 
 import android.app.Service;
 import android.content.Intent;
-import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.Looper;
-import android.util.Log;
 import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.WindowManager;
 import android.widget.Toast;
 import android.support.v4.app.NotificationCompat;
 import android.graphics.BitmapFactory;
 import android.app.Notification;
-import android.os.Message;
-import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
-import android.hardware.Camera.PreviewCallback;
-import android.os.IBinder;
 import android.os.Binder;
-import android.content.Context;
-import android.graphics.PixelFormat;
-import java.io.IOException;
-import android.view.Gravity;
 
-public class MyService extends Service  implements Camera.PreviewCallback {
 
-    private static Logger gLogger = Logger.getLogger("MyService");
-    private static String TAG = "MyService";
 
-    private Ffmpeg ffmpeg = Ffmpeg.getInstance();
-    private  Boolean isRunning = false;
+public class MyService extends Service  implements Camera.PreviewCallback, Camera.ErrorCallback {
+
+    private static Logger gLogger = Logger.getLogger("MyService");
     private Camera mCamera = null;
     IBinder mBinder = new LocalBinder();
     private String rtmpUrl;
     private long frameCount = 0;
 
+    // Preferred picture Size of the camera;
+    private int width = 0;
+    private int height = 0;
+
+
+    private MyServiceEventListener mListener;
+    public void setServiceEventListener(MyServiceEventListener listener){
+        mListener = listener;
+    }
 
     public class LocalBinder extends Binder {
         public MyService getServiceInstance(){
@@ -53,9 +47,6 @@ public class MyService extends Service  implements Camera.PreviewCallback {
                 mThread.openCamera();
             }
         }
-        if (mCamera == null){
-            gLogger.error("getCameraInstance, camera is null");
-        }
         return mCamera;
     }
 
@@ -65,6 +56,7 @@ public class MyService extends Service  implements Camera.PreviewCallback {
             mCamera = Camera.open(1);
         } catch (Exception e) {
             gLogger.error("camera is not available. error: " + e.getMessage());
+            if(mListener != null) mListener.onCameraError("openCamera - error: " + e.getMessage());
         }
     }
 
@@ -122,9 +114,13 @@ public class MyService extends Service  implements Camera.PreviewCallback {
         super.onCreate();
         gLogger.error("onCreate ---> ");
         createNotification();
-        Toast.makeText(this, "Video stream pushed to " + this.rtmpUrl, Toast.LENGTH_LONG).show();
+        //Toast.makeText(this, "Started to Publish!", Toast.LENGTH_LONG).show();
         mCamera = getCameraInstance();
-        configCamera(mCamera);
+        if(mCamera != null){
+            configCamera(mCamera);
+            mCamera.setErrorCallback(this);
+        }
+
     }
 
     @Override
@@ -143,8 +139,6 @@ public class MyService extends Service  implements Camera.PreviewCallback {
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         gLogger.error("onStartCommand");
-        //nrunnable = new FfmpegRunnable("xxx", this);
-        //new Thread(runnable).start();
         return START_STICKY;
     }
 
@@ -159,46 +153,49 @@ public class MyService extends Service  implements Camera.PreviewCallback {
     public void  onPreviewFrame(final byte[] data, Camera camera){
         if(frameCount % (15 * 60) == 0) {
             gLogger.error("onPreviewFrame");
+            if(mListener != null) mListener.onIsPreviewing("onPreviewFrame ");
         }
         frameCount++;
-        ffmpeg.process(data);
+        if(FfmpegHelper.processFrame(data) != 0){
+            gLogger.error("FfmpegHelper.processFrame error, close");
+            FfmpegHelper.close();
+            if(mListener != null) mListener.onEncoderError("processFrame");
+        }
     }
 
     public void startPreview (SurfaceHolder holder){
         gLogger.error("startPreview");
-        if (mCamera == null){
-            gLogger.error("startPreview - error: camera is null");
-            return;
-        }
         try {
             mCamera.setPreviewDisplay(holder);
             mCamera.startPreview();
         } catch (Exception e){
             gLogger.error("startPreview - error: " + e.getMessage());
             e.printStackTrace();
+            if(mListener != null) mListener.onCameraError("setPreviewDisplay - " + e.getMessage());
         }
     }
 
     public boolean setRtmpUrl (String url){
         this.rtmpUrl = url;
-        Camera.Parameters param = mCamera.getParameters();
-        int width = param.getPictureSize().width;
-        int height = param.getPictureSize().height;
+        if(mCamera == null) return false;
         gLogger.error("setRtmpUrl - size: " +  width + "x" + height + ". url: " + url);
-        int ret = ffmpeg.initnew(width, height, url);
+        int ret = FfmpegHelper.initEncoder(width, height, url);
         return ret == 0 ? true : false;
     }
 
     private void configCamera(Camera camera){
-        if(mCamera == null){
-            gLogger.error("configCamera - camera is null");
+        Camera.Parameters paras = null;
+        try {
+            paras = camera.getParameters();
+        } catch (RuntimeException e){
+            gLogger.error("configCamera - " + e.getMessage());
+            if(mListener != null) mListener.onCameraError("getParameters - " + e.getMessage());
             return;
         }
-        Camera.Parameters paras = camera.getParameters();
         gLogger.error("Supported Picture Sizes:");
         Camera.Size preferredSize = paras.getSupportedPictureSizes().get(0);
         for (Camera.Size cc : paras.getSupportedPictureSizes()){
-            if (cc.width == 640)
+            if (cc.width == 640) // chose 640 x 480 if exists
                 preferredSize = cc;
             gLogger.error(cc.width + "x" + cc.height);
         }
@@ -206,6 +203,8 @@ public class MyService extends Service  implements Camera.PreviewCallback {
         for(int[] i : paras.getSupportedPreviewFpsRange()){
             gLogger.error("[" + i[0] + "," + i[1] + "]");
         }
+        width = preferredSize.width;
+        height = preferredSize.height;
         paras.setPictureSize(preferredSize.width, preferredSize.height); // use 640x480 preferred
         camera.setParameters(paras);
         camera.setDisplayOrientation(0);
@@ -213,4 +212,20 @@ public class MyService extends Service  implements Camera.PreviewCallback {
         gLogger.error("Picture Format: " + paras.getPictureFormat() + ". Size: " + paras.getPictureSize().width + "x" + paras.getPictureSize().height);
         camera.setPreviewCallback(this);
     }
+
+    // Camaer.onError callback
+    @Override
+    public void onError(int error, Camera camera){
+        //if(error == CAMERA_ERROR_SERVER_DIED)
+        gLogger.error("onError, " + error);
+        if(mListener != null) mListener.onCameraError("OnError, " + error);
+    }
+
+
+    public interface MyServiceEventListener {
+        void onCameraError(String err);
+        void onEncoderError(String msg);
+        void onIsPreviewing(String msg); // notify mainActivity if preview is running well
+//        void onIsPublishing(String msg); // notify main activity if encoder is running well;
+    }
 }