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(){
mThread.openCamera();
}
}
- if (mCamera == null){
- gLogger.error("getCameraInstance, camera is null");
- }
return mCamera;
}
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());
}
}
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
@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;
}
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);
}
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);
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;
+ }
}