1 package ai.suanzi.rtmpclient;
3 import android.app.Service;
4 import android.content.Intent;
5 import android.graphics.SurfaceTexture;
6 import android.hardware.Camera;
7 import android.os.Handler;
8 import android.os.HandlerThread;
9 import android.os.IBinder;
10 import android.os.Looper;
11 import android.util.Log;
12 import android.view.SurfaceHolder;
13 import android.view.SurfaceView;
14 import android.view.WindowManager;
15 import android.widget.Toast;
16 import android.support.v4.app.NotificationCompat;
17 import android.graphics.BitmapFactory;
18 import android.app.Notification;
19 import android.os.Message;
20 import org.apache.log4j.Level;
21 import org.apache.log4j.Logger;
22 import android.hardware.Camera.PreviewCallback;
23 import android.os.IBinder;
24 import android.os.Binder;
25 import android.content.Context;
26 import android.graphics.PixelFormat;
27 import java.io.IOException;
28 import android.view.Gravity;
30 public class MyService extends Service implements Camera.PreviewCallback {
32 private static Logger gLogger = Logger.getLogger("MyService");
33 private static String TAG = "MyService";
35 private Ffmpeg ffmpeg = Ffmpeg.getInstance();
36 private Boolean isRunning = false;
37 //private FfmpegRunnable runnable;
38 private Camera mCamera = null;
39 IBinder mBinder = new LocalBinder();
40 private String rtmpUrl;
41 //private WindowManager mWindowManager;
42 //private SurfaceView mOutComeVideoView;
43 private long frameCount = 0;
46 public class LocalBinder extends Binder {
47 public MyService getServiceInstance(){
48 return MyService.this;
52 public Camera getCameraInstance() {
53 if (mCamera == null) {
54 CameraHandlerThread mThread = new CameraHandlerThread("camera thread");
55 synchronized (mThread) {
60 gLogger.error("getCameraInstance, camera is null");
65 private void openCameraOriginal() {
67 gLogger.error("openCameraOriginal");
68 mCamera = Camera.open(1);
69 } catch (Exception e) {
70 gLogger.error("camera is not available. error: " + e.getMessage());
74 private class CameraHandlerThread extends HandlerThread {
77 public CameraHandlerThread(String name) {
79 gLogger.error("CameraHandlerThread: " + name);
81 mHandler = new Handler(getLooper());
84 synchronized void notifyCameraOpened() {
89 mHandler.post(new Runnable() {
98 } catch (InterruptedException e) {
99 gLogger.error("wait was interrupted");
104 private static final int NOTIFICATION_DOWNLOAD_PROGRESS_ID = 0x0001; //id不可设置为0,否则不能设置为前台service
105 private void createNotification(){
106 gLogger.debug("createNotification");
107 NotificationCompat.Builder builder=new NotificationCompat.Builder(this); //使用兼容版本
108 builder.setSmallIcon(R.mipmap.ic_launcher); //设置状态栏的通知图标
109 builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background)); //设置通知栏横条的图标
110 builder.setAutoCancel(false); //禁止用户点击删除按钮删除
111 builder.setOngoing(true); //禁止滑动删除
112 builder.setShowWhen(true); //右上角的时间显示
113 builder.setContentTitle("Rtmp Foreground Service!!!"); //设置通知栏的标题内容
114 Notification notification = builder.build(); //创建通知
115 startForeground(NOTIFICATION_DOWNLOAD_PROGRESS_ID,notification); //设置为前台服务
119 public IBinder onBind(Intent intent) {
124 public void onCreate() {
126 gLogger.error("onCreate ---> ");
127 createNotification();
128 Toast.makeText(this, "Video stream pushed to " + this.rtmpUrl, Toast.LENGTH_LONG).show();
129 mCamera = getCameraInstance();
130 configCamera(mCamera);
134 public void onDestroy() {
135 stopForeground(true);
137 gLogger.error( "onDestroy --------->");
138 Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
140 mCamera.stopPreview();
147 public int onStartCommand(Intent intent, int flags, int startId) {
148 gLogger.error("onStartCommand");
149 //nrunnable = new FfmpegRunnable("xxx", this);
150 //new Thread(runnable).start();
155 public void onLowMemory(){
157 gLogger.error("onLowMemory");
160 // Camera.PreviewCallback
162 public void onPreviewFrame(final byte[] data, Camera camera){
163 if(frameCount % (15 * 60) == 0) {
164 gLogger.error("onPreviewFrame");
167 ffmpeg.process(data);
170 public void startPreview (SurfaceHolder holder){
171 gLogger.error("startPreview");
172 if (mCamera == null){
173 gLogger.error("startPreview - error: camera is null");
177 mCamera.setPreviewDisplay(holder);
178 mCamera.startPreview();
179 } catch (Exception e){
180 gLogger.error("startPreview - error: " + e.getMessage());
185 public boolean setRtmpUrl (String url){
187 Camera.Parameters param = mCamera.getParameters();
188 int width = param.getPictureSize().width;
189 int height = param.getPictureSize().height;
190 gLogger.error("setRtmpUrl - size: " + width + "x" + height + ". url: " + url);
191 int ret = ffmpeg.initnew(width, height, url);
192 return ret == 0 ? true : false;
195 private void configCamera(Camera camera){
197 gLogger.error("configCamera - camera is null");
200 Camera.Parameters paras = camera.getParameters();
201 gLogger.error("Supported Picture Sizes:");
202 Camera.Size preferredSize = paras.getSupportedPictureSizes().get(0);
203 for (Camera.Size cc : paras.getSupportedPictureSizes()){
206 gLogger.error(cc.width + "x" + cc.height);
208 gLogger.error("Supported Preview fps range:");
209 for(int[] i : paras.getSupportedPreviewFpsRange()){
210 gLogger.error("[" + i[0] + "," + i[1] + "]");
212 paras.setPictureSize(preferredSize.width, preferredSize.height); // use 640x480 preferred
213 camera.setParameters(paras);
214 camera.setDisplayOrientation(0);
215 gLogger.error("Preview Format: " + paras.getPreviewFormat() + ". Size: " + paras.getPreviewSize().width + "x" + paras.getPreviewSize().height);
216 gLogger.error("Picture Format: " + paras.getPictureFormat() + ". Size: " + paras.getPictureSize().width + "x" + paras.getPictureSize().height);
217 camera.setPreviewCallback(this);
218 //camera.startPreview();
222 // private class FfmpegRunnable implements Runnable {
223 // private String url;
224 // private Camera.PreviewCallback cb;
225 // public FfmpegRunnable(String _url, Camera.PreviewCallback _cb){
230 // public void run(){
231 // gLogger.error("Run Ffmpeg url: " + url);
233 // gLogger.error("Open camera");
234 // mCamera = getCameraInstance();
235 // if(mCamera == null) {
236 // gLogger.error("Open camera, camera is null");
238 // configCamera(mCamera);
239 // mCamera.setPreviewCallback(this.cb);