From f8fb13b9804d9b4b6fb227fbd07b80de9b092b55 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Thu, 17 May 2018 10:51:41 +0800 Subject: [PATCH] pushing and previewing work when switch background/foreground --- app/src/main/AndroidManifest.xml | 1 + .../main/java/ai/suanzi/rtmpclient/CameraView.java | 27 +++ .../java/ai/suanzi/rtmpclient/MainActivity.java | 223 +++++++-------------- .../main/java/ai/suanzi/rtmpclient/MyService.java | 129 +++++++++++- .../main/java/ai/suanzi/rtmpclient/UVCCamera.java | 2 +- 5 files changed, 228 insertions(+), 154 deletions(-) create mode 100644 app/src/main/java/ai/suanzi/rtmpclient/CameraView.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8902a18..4baf398 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -31,4 +31,5 @@ + \ No newline at end of file diff --git a/app/src/main/java/ai/suanzi/rtmpclient/CameraView.java b/app/src/main/java/ai/suanzi/rtmpclient/CameraView.java new file mode 100644 index 0000000..ab3e145 --- /dev/null +++ b/app/src/main/java/ai/suanzi/rtmpclient/CameraView.java @@ -0,0 +1,27 @@ +package ai.suanzi.rtmpclient; + +import android.os.Parcelable; +import android.view.SurfaceView; +import android.os.Parcel; +import android.content.Context; +import android.view.SurfaceHolder; + + +public class CameraView extends SurfaceView implements Parcelable { + + private SurfaceHolder mHolder; + + public CameraView(Context context) { + super(context); + mHolder = getHolder(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + } +} diff --git a/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java b/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java index 5c2e2f9..6531b9f 100644 --- a/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java +++ b/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java @@ -42,6 +42,11 @@ import org.apache.log4j.Level; import org.apache.log4j.Logger; import android.net.wifi.WifiManager; import android.net.wifi.WifiInfo; +import android.content.ServiceConnection; +import android.content.ComponentName; + +import ai.suanzi.rtmpclient.MyService.LocalBinder; +import android.os.IBinder; //"rtmp://gpussh.suanzi.ai:1935/myapp/suanzi_ac83f34ead90_cameraid"; @@ -53,7 +58,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal private StreamTask mStreamTask; private SurfaceHolder mHolder; private SurfaceView mSufaceView; - private UVCCamera uvcCamera; + //private UVCCamera uvcCamera; ExecutorService mExecutor = Executors.newSingleThreadExecutor(); //Intent it = new Intent(getApplicationContext(), MyService.class); Intent intent = new Intent(); @@ -68,6 +73,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal private TextInputEditText mTextUser; private TextInputEditText mTextCamera; private String mMacAddr = ""; + private CameraView mCameraView; private void configLog(){ try { @@ -92,7 +98,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal this.mMacAddr = getMacAddr(); ffmpeg = Ffmpeg.getInstance(); - uvcCamera = new UVCCamera(); + //uvcCamera = new UVCCamera(); mBtnStart = findViewById(R.id.button); mTextServer = findViewById(R.id.textServer); @@ -110,16 +116,51 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal mHolder.addCallback(this); // camera - mCamera = getCameraInstance(); - configCamera(mCamera); + //mCamera = getCameraInstance(); + //configCamera(mCamera); + } + boolean mBounded; + MyService mServer; + ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName name) { + Toast.makeText(MainActivity.this, "Service is disconnected", 1000).show(); + gLogger.error("onServiceDisconnected"); + + mBounded = false; + mServer = null; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Toast.makeText(MainActivity.this, "Service is connected", 1000).show(); + gLogger.error("onServiceConnected"); + mBounded = true; + LocalBinder mLocalBinder = (LocalBinder)service; + mServer = mLocalBinder.getServiceInstance(); + mServer.onChange(mHolder); + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); + //mCameraView = new CameraView(this); + //intent.putExtra("url", "xxxxxxxxxxxxxxxxxx"); + //intent.putExtra("view", mCameraView); + + //startService(intent); + Intent mIntent = new Intent(this, MyService.class); + bindService(mIntent, mConnection, BIND_AUTO_CREATE); + + + + mBtnStart.setOnClickListener(new View.OnClickListener(){ @Override @@ -129,149 +170,10 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal intent.putExtra("url", url); startService(intent); saveConfig(); - //changePermission(); - } - }); - - /*btn2.post(new Runnable(){ - @Override - public void run() { - btn2.performClick(); - } }); - - switchToBackground();*/ - - /* - usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); - HashMap deviceList = usbManager.getDeviceList(); - Log.e(TAG, "device list size : " + deviceList.size()); - Iterator deviceIterator = deviceList.values().iterator(); - PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); - - IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED); - registerReceiver(mUsbReceiver, filter); - filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED); - registerReceiver(mUsbReceiver, filter); - filter = new IntentFilter(ACTION_USB_PERMISSION); - registerReceiver(mUsbReceiver, filter); - - while(deviceIterator.hasNext()){ - UsbDevice device = deviceIterator.next(); - Log.e(TAG, device.toString()); - Log.e(TAG, device.getDeviceName() + " manufacture name: " + device.getManufacturerName() + " " + device.getSerialNumber() + " " + device.getDeviceId()); - - if (device.getVendorId() == 6257){ - usbManager.requestPermission(device, mPermissionIntent); - Log.e(TAG,"XXXXXXXXXXXXXXXXXXXXXXXXXXX"); - Log.e(TAG, device.getVendorId() + "\n" + device.getProductId() + "\n" + device.getProductName() + "\n" + - device.getManufacturerName() + "\n" + device.getDeviceId() + "\n" + device.getSerialNumber() + "\n" + - device.getDeviceName()); - - final String name = device.getDeviceName(); - final String[] v = name.split("/"); - int busnum = 0; - int devnum = 0; - if (v != null) { - busnum = Integer.parseInt(v[v.length-2]); - devnum = Integer.parseInt(v[v.length-1]); - } - //mBusNum = busnum; - //mDevNum = devnum; - uData.vid = device.getVendorId(); - uData.pid = device.getProductId(); - uData.busNum = busnum; - uData.devNum = devnum; - - String result = null; - final String[] vv = name.split("/"); - if ((vv != null) && (vv.length > 2)) { - final StringBuilder sb = new StringBuilder(vv[0]); - for (int i = 1; i < vv.length - 2; i++) - sb.append("/").append(vv[i]); - result = sb.toString(); - } - uData.usbFsName = result; - - - uData.print(); - - usbCamera = device; - } - - //Log.e(TAG, device.) - //device.getInterface() - }*/ } - /*private UsbData uData = new UsbData(); - - private class UsbData { - public int vid; - public int pid; - public int fd; - public int busNum; - public int devNum; - public String usbFsName; - public void print(){ - Log.e(TAG, "vid=" + vid + ". pid=" + pid + ". fd=" + fd + ". busnum=" + busNum + ". devNum=" + devNum + ". usbFsName=" + usbFsName); - } - }*/ - - //SurfaceTexture st = new SurfaceTexture(0); - - /*private static final String ACTION_USB_PERMISSION = - "com.android.example.USB_PERMISSION"; - private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (ACTION_USB_PERMISSION.equals(action)) { - synchronized (this) { - UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - - if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true)) { - if(device != null){ - Log.e(TAG, "extra permission granted"); - //call method to set up device communication - - - new Thread(new Runnable() { - @Override - public void run() { - Log.e("device","MyThread3");//bhw - UsbDeviceConnection connection = usbManager.openDevice(usbCamera); - int fd = connection.getFileDescriptor();//获取文件描述符 - uData.fd = fd; - //ffmpeg.test(fd); - int ret = uvcCamera.open(uData.vid, uData.pid, uData.fd, uData.busNum, uData.devNum, uData.usbFsName); - Log.e(TAG, "uvcCamera open return code:" + ret); - - Log.e("device","MyThread3 "+fd); - } - }).start(); - - } - } - else { - Log.e(TAG, "permission denied for device. " + device); - } - } - } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)){ - UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - if (device != null){ - Log.e(TAG, "==== device out"); - } - } else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { - Log.e(TAG, "==== device in ====="); - } - } - };*/ - - - - @Override protected void onPause(){ super.onPause(); @@ -340,6 +242,34 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal @Override public void surfaceChanged(SurfaceHolder holder, int format, int widht, int height){ gLogger.error("surfaceChanged"); + mHolder = holder; + + if (mServer != null) { + mServer.onChange(holder); + } + + /* final SurfaceHolder hh = holder; + Thread tr = new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(3000); + } catch (Exception e){ + e.printStackTrace(); + } + if (mServer != null) { + gLogger.error("onChange"); + mServer.onChange(hh); + }else { + gLogger.error("service XXXXXXXXXXXXXXX"); + } + + } + }); + tr.run();*/ + + + /* try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); @@ -347,6 +277,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal gLogger.error("Error starting camera previewe: " + e.getMessage()); Toast.makeText(this, "Camera Error: " + e.getMessage(), Toast.LENGTH_LONG).show(); } + */ } @Override @@ -357,7 +288,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal @Override public void onPreviewFrame(final byte[] data, Camera camera){ gLogger.error("onPreviewFrame"); - if (null != mStreamTask){ + /*if (null != mStreamTask){ switch (mStreamTask.getStatus()){ case RUNNING: Log.e(TAG, "onPreviewFrame Running"); @@ -370,7 +301,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal } mStreamTask = new StreamTask(data); mStreamTask.execute((Void)null); - +*/ // ong endTime = System.currentTimeMillis(); // mExecutor.execute(new Runnable() { @@ -424,7 +355,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal } catch (IOException e){ e.printStackTrace(); } - camera.setPreviewCallback(this); + //camera.setPreviewCallback(this); } private void switchToBackground(){ diff --git a/app/src/main/java/ai/suanzi/rtmpclient/MyService.java b/app/src/main/java/ai/suanzi/rtmpclient/MyService.java index 9053b35..1d9dc60 100644 --- a/app/src/main/java/ai/suanzi/rtmpclient/MyService.java +++ b/app/src/main/java/ai/suanzi/rtmpclient/MyService.java @@ -2,11 +2,16 @@ 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; @@ -14,30 +19,69 @@ 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 { +public class MyService extends Service implements Camera.PreviewCallback { private Logger gLogger = Logger.getLogger("MyService"); private Ffmpeg ffmpeg = Ffmpeg.getInstance(); private Boolean isRunning = false; private FfmpegRunnable runnable; + private Camera mCamera = null; + IBinder mBinder = new LocalBinder(); + private WindowManager mWindowManager; + private SurfaceView mOutComeVideoView; + + + public class LocalBinder extends Binder { + public MyService getServiceInstance(){ + return MyService.this; + } + } private class FfmpegRunnable implements Runnable { private String url; - public FfmpegRunnable(String _url){ + private Camera.PreviewCallback cb; + public FfmpegRunnable(String _url, Camera.PreviewCallback _cb){ this.url = _url; + this.cb = _cb; } @Override public void run(){ gLogger.error("Run Ffmpeg url: " + url); isRunning = true; - ffmpeg.push(null, this.url); + //ffmpeg.push(null, this.url); + if (mCamera == null) { + gLogger.error("open camea"); + try { + mCamera = Camera.open(1); + }catch (Exception e){ + e.printStackTrace(); + } + } + /* + SurfaceTexture st = new SurfaceTexture(0); + try { + mCamera.setPreviewTexture(st); + }catch (Exception e){ + e.printStackTrace(); + }*/ + gLogger.error("start preview"); + mCamera.setPreviewCallback(this.cb); + mCamera.startPreview(); + } } private static final int NOTIFICATION_DOWNLOAD_PROGRESS_ID = 0x0001; //id不可设置为0,否则不能设置为前台service - public void createNotification(){ + private void createNotification(){ gLogger.error("createNotification"); NotificationCompat.Builder builder=new NotificationCompat.Builder(this); //使用兼容版本 builder.setSmallIcon(R.mipmap.ic_launcher); //设置状态栏的通知图标 @@ -52,13 +96,33 @@ public class MyService extends Service { @Override public IBinder onBind(Intent intent) { - return null; + return mBinder; } @Override public void onCreate() { super.onCreate(); gLogger.error("onCreate"); + + +// mWindowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE); +// mOutComeVideoView = new SurfaceView(this); +// +// +// WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(1, 1, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, +// WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT); +// layoutParams.gravity = Gravity.LEFT | Gravity.TOP; +// mWindowManager.addView(mOutComeVideoView, layoutParams); +// mOutComeVideoView.getHolder().addCallback(this); +// +// + createNotification(); + runnable = new FfmpegRunnable("xxxxxx", this); + new Thread(runnable).start(); + + + + } @Override @@ -79,9 +143,11 @@ public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - String url = intent.getExtras().getString("url"); + String url = "hahahahhah"; //intent.getExtras().getString("url"); + + gLogger.error("onStartCommand: url is:" + url + ". isRunning: " + isRunning); - runnable = new FfmpegRunnable(url); + runnable = new FfmpegRunnable(url, this); if (!isRunning) { createNotification(); Toast.makeText(this, "Video stream pushed to " + url, Toast.LENGTH_LONG).show(); @@ -95,4 +161,53 @@ public class MyService extends Service { super.onLowMemory(); gLogger.error("onLowMemory"); } + + // Camera.PreviewCallback + @Override + public void onPreviewFrame(final byte[] data, Camera camera){ + gLogger.error("onPreviewFrame"); + ffmpeg.process(data); + } + + public void onChange (SurfaceHolder holder){ + gLogger.error("onChange"); + try { + if (holder == null){ + gLogger.error("xxxx holder is null xxxxxx"); + } + if (mCamera == null) { + gLogger.error("xxxx camera is null xxxx"); + } + + mCamera.setPreviewDisplay(holder); + mCamera.startPreview(); + } catch (Exception e){ + e.printStackTrace(); + } + } + + + +// // SurfaceHolder.Callback implementation +// @Override +// public void surfaceCreated(final SurfaceHolder holder){ +// gLogger.error("SurfacedCreated"); +// } +// +// @Override +// public void surfaceChanged(SurfaceHolder holder, int format, int widht, int height){ +// gLogger.error("surfaceChanged"); +// try { +// mCamera.setPreviewDisplay(holder); +// } catch (Exception e){ +// e.printStackTrace(); +// } +// mCamera.startPreview(); +// +// } +// +// @Override +// public void surfaceDestroyed(SurfaceHolder holder){ +// gLogger.error("surfaceDestroyed"); +// } } diff --git a/app/src/main/java/ai/suanzi/rtmpclient/UVCCamera.java b/app/src/main/java/ai/suanzi/rtmpclient/UVCCamera.java index 354cf97..4b22cf4 100644 --- a/app/src/main/java/ai/suanzi/rtmpclient/UVCCamera.java +++ b/app/src/main/java/ai/suanzi/rtmpclient/UVCCamera.java @@ -13,7 +13,7 @@ public class UVCCamera { public UVCCamera(){ Log.e("UVC", " uvc camera"); - init(); + //init(); } public native int open(int venderId, int prodId, int fd, int busNum, int devNum, String usbFsName); -- 2.11.0