diff --git a/.gradle/2.14.1/taskArtifacts/cache.properties b/.gradle/2.14.1/taskArtifacts/cache.properties deleted file mode 100644 index a2f0313..0000000 --- a/.gradle/2.14.1/taskArtifacts/cache.properties +++ /dev/null @@ -1 +0,0 @@ -#Fri Sep 29 14:50:34 CST 2017 diff --git a/.gradle/2.14.1/taskArtifacts/cache.properties.lock b/.gradle/2.14.1/taskArtifacts/cache.properties.lock deleted file mode 100644 index 3089714..0000000 Binary files a/.gradle/2.14.1/taskArtifacts/cache.properties.lock and /dev/null differ diff --git a/.gradle/2.14.1/taskArtifacts/fileHashes.bin b/.gradle/2.14.1/taskArtifacts/fileHashes.bin deleted file mode 100644 index e07f308..0000000 Binary files a/.gradle/2.14.1/taskArtifacts/fileHashes.bin and /dev/null differ diff --git a/.gradle/2.14.1/taskArtifacts/fileSnapshots.bin b/.gradle/2.14.1/taskArtifacts/fileSnapshots.bin deleted file mode 100644 index 65ed922..0000000 Binary files a/.gradle/2.14.1/taskArtifacts/fileSnapshots.bin and /dev/null differ diff --git a/.gradle/2.14.1/taskArtifacts/fileSnapshotsToTreeSnapshotsIndex.bin b/.gradle/2.14.1/taskArtifacts/fileSnapshotsToTreeSnapshotsIndex.bin deleted file mode 100644 index 0c7e314..0000000 Binary files a/.gradle/2.14.1/taskArtifacts/fileSnapshotsToTreeSnapshotsIndex.bin and /dev/null differ diff --git a/.gradle/2.14.1/taskArtifacts/taskArtifacts.bin b/.gradle/2.14.1/taskArtifacts/taskArtifacts.bin deleted file mode 100644 index 59c5caa..0000000 Binary files a/.gradle/2.14.1/taskArtifacts/taskArtifacts.bin and /dev/null differ diff --git a/.gradle/3.3/taskArtifacts/fileHashes.bin b/.gradle/3.3/taskArtifacts/fileHashes.bin deleted file mode 100644 index 5d8313c..0000000 Binary files a/.gradle/3.3/taskArtifacts/fileHashes.bin and /dev/null differ diff --git a/.gradle/3.3/taskArtifacts/fileSnapshots.bin b/.gradle/3.3/taskArtifacts/fileSnapshots.bin deleted file mode 100644 index e2423d1..0000000 Binary files a/.gradle/3.3/taskArtifacts/fileSnapshots.bin and /dev/null differ diff --git a/.gradle/3.3/taskArtifacts/taskArtifacts.bin b/.gradle/3.3/taskArtifacts/taskArtifacts.bin deleted file mode 100644 index dddbbf3..0000000 Binary files a/.gradle/3.3/taskArtifacts/taskArtifacts.bin and /dev/null differ diff --git a/.gradle/3.3/taskArtifacts/taskArtifacts.lock b/.gradle/3.3/taskArtifacts/taskArtifacts.lock deleted file mode 100644 index d0e5495..0000000 Binary files a/.gradle/3.3/taskArtifacts/taskArtifacts.lock and /dev/null differ diff --git a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin b/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin deleted file mode 100644 index 403d55d..0000000 Binary files a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin and /dev/null differ diff --git a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock b/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock deleted file mode 100644 index 0a198dd..0000000 Binary files a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock and /dev/null differ diff --git a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin b/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin deleted file mode 100644 index c1c2b17..0000000 Binary files a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin and /dev/null differ diff --git a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock b/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock deleted file mode 100644 index 9650bd3..0000000 Binary files a/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock and /dev/null differ diff --git a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin b/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin deleted file mode 100644 index c294965..0000000 Binary files a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin and /dev/null differ diff --git a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock b/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock deleted file mode 100644 index 0e49511..0000000 Binary files a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock and /dev/null differ diff --git a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin b/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin deleted file mode 100644 index 435081e..0000000 Binary files a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin and /dev/null differ diff --git a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock b/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock deleted file mode 100644 index 33e1f5c..0000000 Binary files a/.gradle/3.3/tasks/_libusbcamera_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock and /dev/null differ diff --git a/app/app.iml b/app/app.iml index f71eb2e..31b5f8c 100644 --- a/app/app.iml +++ b/app/app.iml @@ -27,21 +27,20 @@ - + - + - @@ -49,13 +48,6 @@ - - - - - - - @@ -88,10 +80,13 @@ + + + @@ -102,33 +97,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java b/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java index 16587da..c6ba68f 100644 --- a/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java +++ b/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java @@ -241,14 +241,15 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog showShortMsg("sorry,camera open failed"); return super.onOptionsItemSelected(item); } - if (!mCameraHelper.isRecording()) { + if (!mCameraHelper.isPushing()) { String videoPath = UVCCameraHelper.ROOT_PATH + System.currentTimeMillis(); FileUtils.createfile(FileUtils.ROOT_PATH + "test666.h264"); + // if you want to record,please create RecordParams like this RecordParams params = new RecordParams(); params.setRecordPath(videoPath); params.setRecordDuration(0); // 设置为0,不分割保存 params.setVoiceClose(mSwitchVoice.isChecked()); // is close voice - mCameraHelper.startRecording(params, new AbstractUVCCameraHandler.OnEncodeResultListener() { + mCameraHelper.startPusher(params, new AbstractUVCCameraHandler.OnEncodeResultListener() { @Override public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) { // type = 1,h264 video stream @@ -266,11 +267,13 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog Log.i(TAG,"videoPath = "+videoPath); } }); + // if you only want to push stream,please call like this + // mCameraHelper.startPusher(listener); showShortMsg("start record..."); mSwitchVoice.setEnabled(false); } else { FileUtils.releaseFile(); - mCameraHelper.stopRecording(); + mCameraHelper.stopPusher(); showShortMsg("stop record..."); mSwitchVoice.setEnabled(true); } diff --git a/libusbcamera/libusbcamera.iml b/libusbcamera/libusbcamera.iml index c3d9305..a90ce6d 100644 --- a/libusbcamera/libusbcamera.iml +++ b/libusbcamera/libusbcamera.iml @@ -28,21 +28,20 @@ - + - + - @@ -57,13 +56,6 @@ - - - - - - - @@ -85,16 +77,20 @@ + + + + @@ -104,30 +100,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java b/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java index d03d6ab..efe105a 100644 --- a/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java +++ b/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java @@ -247,19 +247,25 @@ public class UVCCameraHelper { } } - public void startRecording(RecordParams params, AbstractUVCCameraHandler.OnEncodeResultListener listener) { - if (mCameraHandler != null && !isRecording()) { + public void startPusher(AbstractUVCCameraHandler.OnEncodeResultListener listener) { + if (mCameraHandler != null && !isPushing()) { + mCameraHandler.startRecording(null, listener); + } + } + + public void startPusher(RecordParams params, AbstractUVCCameraHandler.OnEncodeResultListener listener) { + if (mCameraHandler != null && !isPushing()) { mCameraHandler.startRecording(params, listener); } } - public void stopRecording() { - if (mCameraHandler != null && isRecording()) { + public void stopPusher() { + if (mCameraHandler != null && isPushing()) { mCameraHandler.stopRecording(); } } - public boolean isRecording() { + public boolean isPushing() { if (mCameraHandler != null) { return mCameraHandler.isRecording(); } diff --git a/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java b/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java index fd7f7f9..a3ecb6a 100644 --- a/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java +++ b/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java @@ -51,201 +51,207 @@ import java.util.concurrent.CopyOnWriteArraySet; /** * Camera业务处理抽象类 - * - * */ -public abstract class AbstractUVCCameraHandler extends Handler { - - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "AbsUVCCameraHandler"; - - - // 对外回调接口 - public interface CameraCallback { - public void onOpen(); - public void onClose(); - public void onStartPreview(); - public void onStopPreview(); - public void onStartRecording(); - public void onStopRecording(); - public void onError(final Exception e); - } - - public static OnEncodeResultListener mListener; - public static OnPreViewResultListener mPreviewListener; - public static OnCaptureListener mCaptureListener; - - public interface OnEncodeResultListener{ - void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type); - void onRecordResult(String videoPath); - } - - public interface OnPreViewResultListener{ - void onPreviewResult(byte[] data); - } - - public interface OnCaptureListener { - void onCaptureResult(String picPath); - } - - private static final int MSG_OPEN = 0; - private static final int MSG_CLOSE = 1; - private static final int MSG_PREVIEW_START = 2; - private static final int MSG_PREVIEW_STOP = 3; - private static final int MSG_CAPTURE_STILL = 4; - private static final int MSG_CAPTURE_START = 5; - private static final int MSG_CAPTURE_STOP = 6; - private static final int MSG_MEDIA_UPDATE = 7; - private static final int MSG_RELEASE = 9; - private static final int MSG_CAMERA_FOUCS = 10; - // 音频线程 + */ +public abstract class AbstractUVCCameraHandler extends Handler { + + private static final boolean DEBUG = true; // TODO set false on release + private static final String TAG = "AbsUVCCameraHandler"; + + + // 对外回调接口 + public interface CameraCallback { + public void onOpen(); + + public void onClose(); + + public void onStartPreview(); + + public void onStopPreview(); + + public void onStartRecording(); + + public void onStopRecording(); + + public void onError(final Exception e); + } + + public static OnEncodeResultListener mListener; + public static OnPreViewResultListener mPreviewListener; + public static OnCaptureListener mCaptureListener; + + public interface OnEncodeResultListener { + void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type); + + void onRecordResult(String videoPath); + } + + public interface OnPreViewResultListener { + void onPreviewResult(byte[] data); + } + + public interface OnCaptureListener { + void onCaptureResult(String picPath); + } + + private static final int MSG_OPEN = 0; + private static final int MSG_CLOSE = 1; + private static final int MSG_PREVIEW_START = 2; + private static final int MSG_PREVIEW_STOP = 3; + private static final int MSG_CAPTURE_STILL = 4; + private static final int MSG_CAPTURE_START = 5; + private static final int MSG_CAPTURE_STOP = 6; + private static final int MSG_MEDIA_UPDATE = 7; + private static final int MSG_RELEASE = 9; + private static final int MSG_CAMERA_FOUCS = 10; + // 音频线程 // private static final int MSG_AUDIO_START = 10; // private static final int MSG_AUDIO_STOP = 11; - private final WeakReference mWeakThread; - private volatile boolean mReleased; - protected static boolean isCaptureStill; + private final WeakReference mWeakThread; + private volatile boolean mReleased; + protected static boolean isCaptureStill; - protected AbstractUVCCameraHandler(final CameraThread thread) { - mWeakThread = new WeakReference(thread); - } + protected AbstractUVCCameraHandler(final CameraThread thread) { + mWeakThread = new WeakReference(thread); + } - public int getWidth() { - final CameraThread thread = mWeakThread.get(); - return thread != null ? thread.getWidth() : 0; - } + public int getWidth() { + final CameraThread thread = mWeakThread.get(); + return thread != null ? thread.getWidth() : 0; + } - public int getHeight() { - final CameraThread thread = mWeakThread.get(); - return thread != null ? thread.getHeight() : 0; - } + public int getHeight() { + final CameraThread thread = mWeakThread.get(); + return thread != null ? thread.getHeight() : 0; + } - public boolean isOpened() { - final CameraThread thread = mWeakThread.get(); - return thread != null && thread.isCameraOpened(); - } + public boolean isOpened() { + final CameraThread thread = mWeakThread.get(); + return thread != null && thread.isCameraOpened(); + } - public boolean isPreviewing() { - final CameraThread thread = mWeakThread.get(); - return thread != null && thread.isPreviewing(); - } + public boolean isPreviewing() { + final CameraThread thread = mWeakThread.get(); + return thread != null && thread.isPreviewing(); + } - public boolean isRecording() { - final CameraThread thread = mWeakThread.get(); - return thread != null && thread.isRecording(); - } + public boolean isRecording() { + final CameraThread thread = mWeakThread.get(); + return thread != null && thread.isRecording(); + } // public boolean isAudioThreadStart() { // final CameraThread thread = mWeakThread.get(); // return thread != null && thread.isAudioRecording(); // } - public boolean isEqual(final UsbDevice device) { - final CameraThread thread = mWeakThread.get(); - return (thread != null) && thread.isEqual(device); - } - - protected boolean isCameraThread() { - final CameraThread thread = mWeakThread.get(); - return thread != null && (thread.getId() == Thread.currentThread().getId()); - } - - protected boolean isReleased() { - final CameraThread thread = mWeakThread.get(); - return mReleased || (thread == null); - } - - protected void checkReleased() { - if (isReleased()) { - throw new IllegalStateException("already released"); - } - } - - public void open(final USBMonitor.UsbControlBlock ctrlBlock) { - checkReleased(); - sendMessage(obtainMessage(MSG_OPEN, ctrlBlock)); - } - - public void close() { - if (DEBUG) Log.v(TAG, "close:"); - if (isOpened()) { - stopPreview(); - sendEmptyMessage(MSG_CLOSE); - } - if (DEBUG) Log.v(TAG, "close:finished"); - } - - // 切换分辨率 - public void resize(final int width, final int height) { - checkReleased(); - throw new UnsupportedOperationException("does not support now"); - } - - // 开启Camera预览 - public void startPreview(final Object surface) { - checkReleased(); - if (!((surface instanceof SurfaceHolder) || (surface instanceof Surface) || (surface instanceof SurfaceTexture))) { - throw new IllegalArgumentException("surface should be one of SurfaceHolder, Surface or SurfaceTexture: "+surface); - } - - sendMessage(obtainMessage(MSG_PREVIEW_START, surface)); - } - - public void setOnPreViewResultListener(OnPreViewResultListener listener) { - AbstractUVCCameraHandler.mPreviewListener = listener; - } - - // 关闭Camera预览 - public void stopPreview() { - if (DEBUG) Log.v(TAG, "stopPreview:"); - removeMessages(MSG_PREVIEW_START); - if(isRecording()) { - stopRecording(); - } - if (isPreviewing()) { - final CameraThread thread = mWeakThread.get(); - if (thread == null) return; - synchronized (thread.mSync) { - sendEmptyMessage(MSG_PREVIEW_STOP); - if (!isCameraThread()) { - // wait for actually preview stopped to avoid releasing Surface/SurfaceTexture - // while preview is still running. - // therefore this method will take a time to execute - try { - thread.mSync.wait(); - } catch (final InterruptedException e) { - } - } - } - } - if (DEBUG) Log.v(TAG, "stopPreview:finished"); - } - - public void captureStill(final String path,AbstractUVCCameraHandler.OnCaptureListener listener) { - AbstractUVCCameraHandler.mCaptureListener = listener; - checkReleased(); - sendMessage(obtainMessage(MSG_CAPTURE_STILL, path)); - isCaptureStill = true; - } - - // 开始录制 - public void startRecording(final RecordParams params, OnEncodeResultListener listener) { - AbstractUVCCameraHandler.mListener = listener; - checkReleased(); - sendMessage(obtainMessage(MSG_CAPTURE_START, params)); - } - - // 停止录制 - public void stopRecording() { - sendEmptyMessage(MSG_CAPTURE_STOP); - } - - public void startCameraFoucs(){ - sendEmptyMessage(MSG_CAMERA_FOUCS); - } - - public List getSupportedPreviewSizes(){ - return mWeakThread.get().getSupportedSizes(); - } + public boolean isEqual(final UsbDevice device) { + final CameraThread thread = mWeakThread.get(); + return (thread != null) && thread.isEqual(device); + } + + protected boolean isCameraThread() { + final CameraThread thread = mWeakThread.get(); + return thread != null && (thread.getId() == Thread.currentThread().getId()); + } + + protected boolean isReleased() { + final CameraThread thread = mWeakThread.get(); + return mReleased || (thread == null); + } + + protected void checkReleased() { + if (isReleased()) { + throw new IllegalStateException("already released"); + } + } + + public void open(final USBMonitor.UsbControlBlock ctrlBlock) { + checkReleased(); + sendMessage(obtainMessage(MSG_OPEN, ctrlBlock)); + } + + public void close() { + if (DEBUG) Log.v(TAG, "close:"); + if (isOpened()) { + stopPreview(); + sendEmptyMessage(MSG_CLOSE); + } + if (DEBUG) Log.v(TAG, "close:finished"); + } + + // 切换分辨率 + public void resize(final int width, final int height) { + checkReleased(); + throw new UnsupportedOperationException("does not support now"); + } + + // 开启Camera预览 + public void startPreview(final Object surface) { + checkReleased(); + if (!((surface instanceof SurfaceHolder) || (surface instanceof Surface) || (surface instanceof SurfaceTexture))) { + throw new IllegalArgumentException("surface should be one of SurfaceHolder, Surface or SurfaceTexture: " + surface); + } + + sendMessage(obtainMessage(MSG_PREVIEW_START, surface)); + } + + public void setOnPreViewResultListener(OnPreViewResultListener listener) { + AbstractUVCCameraHandler.mPreviewListener = listener; + } + + // 关闭Camera预览 + public void stopPreview() { + if (DEBUG) Log.v(TAG, "stopPreview:"); + removeMessages(MSG_PREVIEW_START); + if (isRecording()) { + stopRecording(); + } + if (isPreviewing()) { + final CameraThread thread = mWeakThread.get(); + if (thread == null) return; + synchronized (thread.mSync) { + sendEmptyMessage(MSG_PREVIEW_STOP); + if (!isCameraThread()) { + // wait for actually preview stopped to avoid releasing Surface/SurfaceTexture + // while preview is still running. + // therefore this method will take a time to execute + try { + thread.mSync.wait(); + } catch (final InterruptedException e) { + } + } + } + } + if (DEBUG) Log.v(TAG, "stopPreview:finished"); + } + + public void captureStill(final String path, AbstractUVCCameraHandler.OnCaptureListener listener) { + AbstractUVCCameraHandler.mCaptureListener = listener; + checkReleased(); + sendMessage(obtainMessage(MSG_CAPTURE_STILL, path)); + isCaptureStill = true; + } + + // 开始录制 + public void startRecording(final RecordParams params, OnEncodeResultListener listener) { + AbstractUVCCameraHandler.mListener = listener; + checkReleased(); + sendMessage(obtainMessage(MSG_CAPTURE_START, params)); + } + + // 停止录制 + public void stopRecording() { + sendEmptyMessage(MSG_CAPTURE_STOP); + } + + public void startCameraFoucs() { + sendEmptyMessage(MSG_CAMERA_FOUCS); + } + + public List getSupportedPreviewSizes() { + return mWeakThread.get().getSupportedSizes(); + } // // 启动音频线程 // public void startAudioThread(){ @@ -257,232 +263,234 @@ public abstract class AbstractUVCCameraHandler extends Handler { // sendEmptyMessage(MSG_AUDIO_STOP); // } - public void release() { - mReleased = true; - close(); - sendEmptyMessage(MSG_RELEASE); - } - - // 对外注册监听事件 - public void addCallback(final CameraCallback callback) { - checkReleased(); - if (!mReleased && (callback != null)) { - final CameraThread thread = mWeakThread.get(); - if (thread != null) { - thread.mCallbacks.add(callback); - } - } - } - - public void removeCallback(final CameraCallback callback) { - if (callback != null) { - final CameraThread thread = mWeakThread.get(); - if (thread != null) { - thread.mCallbacks.remove(callback); - } - } - } - - protected void updateMedia(final String path) { - sendMessage(obtainMessage(MSG_MEDIA_UPDATE, path)); - } - - public boolean checkSupportFlag(final long flag) { - checkReleased(); - final CameraThread thread = mWeakThread.get(); - return thread != null && thread.mUVCCamera != null && thread.mUVCCamera.checkSupportFlag(flag); - } - - public int getValue(final int flag) { - checkReleased(); - final CameraThread thread = mWeakThread.get(); - final UVCCamera camera = thread != null ? thread.mUVCCamera : null; - if (camera != null) { - if (flag == UVCCamera.PU_BRIGHTNESS) { - return camera.getBrightness(); - } else if (flag == UVCCamera.PU_CONTRAST) { - return camera.getContrast(); - } - } - throw new IllegalStateException(); - } - - public int setValue(final int flag, final int value) { - checkReleased(); - final CameraThread thread = mWeakThread.get(); - final UVCCamera camera = thread != null ? thread.mUVCCamera : null; - if (camera != null) { - if (flag == UVCCamera.PU_BRIGHTNESS) { - camera.setBrightness(value); - return camera.getBrightness(); - } else if (flag == UVCCamera.PU_CONTRAST) { - camera.setContrast(value); - return camera.getContrast(); - } - } - throw new IllegalStateException(); - } - - public int resetValue(final int flag) { - checkReleased(); - final CameraThread thread = mWeakThread.get(); - final UVCCamera camera = thread != null ? thread.mUVCCamera : null; - if (camera != null) { - if (flag == UVCCamera.PU_BRIGHTNESS) { - camera.resetBrightness(); - return camera.getBrightness(); - } else if (flag == UVCCamera.PU_CONTRAST) { - camera.resetContrast(); - return camera.getContrast(); - } - } - throw new IllegalStateException(); - } - - @Override - public void handleMessage(final Message msg) { - final CameraThread thread = mWeakThread.get(); - if (thread == null) return; - switch (msg.what) { - case MSG_OPEN: - thread.handleOpen((USBMonitor.UsbControlBlock)msg.obj); - break; - case MSG_CLOSE: - thread.handleClose(); - break; - case MSG_PREVIEW_START: - thread.handleStartPreview(msg.obj); - break; - case MSG_PREVIEW_STOP: - thread.handleStopPreview(); - break; - case MSG_CAPTURE_STILL: + public void release() { + mReleased = true; + close(); + sendEmptyMessage(MSG_RELEASE); + } + + // 对外注册监听事件 + public void addCallback(final CameraCallback callback) { + checkReleased(); + if (!mReleased && (callback != null)) { + final CameraThread thread = mWeakThread.get(); + if (thread != null) { + thread.mCallbacks.add(callback); + } + } + } + + public void removeCallback(final CameraCallback callback) { + if (callback != null) { + final CameraThread thread = mWeakThread.get(); + if (thread != null) { + thread.mCallbacks.remove(callback); + } + } + } + + protected void updateMedia(final String path) { + sendMessage(obtainMessage(MSG_MEDIA_UPDATE, path)); + } + + public boolean checkSupportFlag(final long flag) { + checkReleased(); + final CameraThread thread = mWeakThread.get(); + return thread != null && thread.mUVCCamera != null && thread.mUVCCamera.checkSupportFlag(flag); + } + + public int getValue(final int flag) { + checkReleased(); + final CameraThread thread = mWeakThread.get(); + final UVCCamera camera = thread != null ? thread.mUVCCamera : null; + if (camera != null) { + if (flag == UVCCamera.PU_BRIGHTNESS) { + return camera.getBrightness(); + } else if (flag == UVCCamera.PU_CONTRAST) { + return camera.getContrast(); + } + } + throw new IllegalStateException(); + } + + public int setValue(final int flag, final int value) { + checkReleased(); + final CameraThread thread = mWeakThread.get(); + final UVCCamera camera = thread != null ? thread.mUVCCamera : null; + if (camera != null) { + if (flag == UVCCamera.PU_BRIGHTNESS) { + camera.setBrightness(value); + return camera.getBrightness(); + } else if (flag == UVCCamera.PU_CONTRAST) { + camera.setContrast(value); + return camera.getContrast(); + } + } + throw new IllegalStateException(); + } + + public int resetValue(final int flag) { + checkReleased(); + final CameraThread thread = mWeakThread.get(); + final UVCCamera camera = thread != null ? thread.mUVCCamera : null; + if (camera != null) { + if (flag == UVCCamera.PU_BRIGHTNESS) { + camera.resetBrightness(); + return camera.getBrightness(); + } else if (flag == UVCCamera.PU_CONTRAST) { + camera.resetContrast(); + return camera.getContrast(); + } + } + throw new IllegalStateException(); + } + + @Override + public void handleMessage(final Message msg) { + final CameraThread thread = mWeakThread.get(); + if (thread == null) return; + switch (msg.what) { + case MSG_OPEN: + thread.handleOpen((USBMonitor.UsbControlBlock) msg.obj); + break; + case MSG_CLOSE: + thread.handleClose(); + break; + case MSG_PREVIEW_START: + thread.handleStartPreview(msg.obj); + break; + case MSG_PREVIEW_STOP: + thread.handleStopPreview(); + break; + case MSG_CAPTURE_STILL: // thread.handleCaptureStill((String)msg.obj); - thread.handleStillPicture((String)msg.obj); - break; - case MSG_CAPTURE_START: + thread.handleStillPicture((String) msg.obj); + break; + case MSG_CAPTURE_START: // thread.handleStartRecording((String)msg.obj); - thread.handleStartRecording((RecordParams)msg.obj); - break; - case MSG_CAPTURE_STOP: - thread.handleStopRecording(); - break; - case MSG_MEDIA_UPDATE: - thread.handleUpdateMedia((String)msg.obj); - break; - case MSG_RELEASE: - thread.handleRelease(); - break; - // 自动对焦 - case MSG_CAMERA_FOUCS: - thread.handleCameraFoucs(); - break; - default: - throw new RuntimeException("unsupported message:what=" + msg.what); - } - } - - public static final class CameraThread extends Thread { - private static final String TAG_THREAD = "CameraThread"; - private final Object mSync = new Object(); - private final Class mHandlerClass; - private final WeakReference mWeakParent; - private final WeakReference mWeakCameraView; - private final int mEncoderType; - private final Set mCallbacks = new CopyOnWriteArraySet(); - private int mWidth, mHeight, mPreviewMode; - private float mBandwidthFactor; - private boolean mIsPreviewing; - private boolean mIsRecording; - - // 播放声音 + thread.handleStartPusher((RecordParams) msg.obj); + break; + case MSG_CAPTURE_STOP: + thread.handleStopPusher(); + break; + case MSG_MEDIA_UPDATE: + thread.handleUpdateMedia((String) msg.obj); + break; + case MSG_RELEASE: + thread.handleRelease(); + break; + // 自动对焦 + case MSG_CAMERA_FOUCS: + thread.handleCameraFoucs(); + break; + default: + throw new RuntimeException("unsupported message:what=" + msg.what); + } + } + + public static final class CameraThread extends Thread { + private static final String TAG_THREAD = "CameraThread"; + private final Object mSync = new Object(); + private final Class mHandlerClass; + private final WeakReference mWeakParent; + private final WeakReference mWeakCameraView; + private final int mEncoderType; + private final Set mCallbacks = new CopyOnWriteArraySet(); + private int mWidth, mHeight, mPreviewMode; + private float mBandwidthFactor; + private boolean mIsPreviewing; + private boolean mIsRecording; + + // 播放声音 // private SoundPool mSoundPool; // private int mSoundId; - private AbstractUVCCameraHandler mHandler; - // 处理与Camera相关的逻辑,比如获取byte数据流等 - private UVCCamera mUVCCamera; - -// private MediaMuxerWrapper mMuxer; - private MediaVideoBufferEncoder mVideoEncoder; - private Mp4MediaMuxer mMuxer; - private String videoPath; + private AbstractUVCCameraHandler mHandler; + // 处理与Camera相关的逻辑,比如获取byte数据流等 + private UVCCamera mUVCCamera; + + // private MediaMuxerWrapper mMuxer; + private MediaVideoBufferEncoder mVideoEncoder; + private Mp4MediaMuxer mMuxer; + private boolean isPushing; + private String videoPath; // private boolean isAudioThreadStart; - /** 构造方法 - * - * clazz 继承于AbstractUVCCameraHandler - * parent Activity子类 - * cameraView 用于捕获静止图像 - * encoderType 0表示使用MediaSurfaceEncoder;1表示使用MediaVideoEncoder, 2表示使用MediaVideoBufferEncoder - * width 分辨率的宽 - * height 分辨率的高 - * format 颜色格式,0为FRAME_FORMAT_YUYV;1为FRAME_FORMAT_MJPEG - * bandwidthFactor - */ - CameraThread(final Class clazz, - final Activity parent, final CameraViewInterface cameraView, - final int encoderType, final int width, final int height, final int format, - final float bandwidthFactor) { - - super("CameraThread"); - mHandlerClass = clazz; - mEncoderType = encoderType; - mWidth = width; - mHeight = height; - mPreviewMode = format; - mBandwidthFactor = bandwidthFactor; - mWeakParent = new WeakReference<>(parent); - mWeakCameraView = new WeakReference<>(cameraView); + /** + * 构造方法 + *

+ * clazz 继承于AbstractUVCCameraHandler + * parent Activity子类 + * cameraView 用于捕获静止图像 + * encoderType 0表示使用MediaSurfaceEncoder;1表示使用MediaVideoEncoder, 2表示使用MediaVideoBufferEncoder + * width 分辨率的宽 + * height 分辨率的高 + * format 颜色格式,0为FRAME_FORMAT_YUYV;1为FRAME_FORMAT_MJPEG + * bandwidthFactor + */ + CameraThread(final Class clazz, + final Activity parent, final CameraViewInterface cameraView, + final int encoderType, final int width, final int height, final int format, + final float bandwidthFactor) { + + super("CameraThread"); + mHandlerClass = clazz; + mEncoderType = encoderType; + mWidth = width; + mHeight = height; + mPreviewMode = format; + mBandwidthFactor = bandwidthFactor; + mWeakParent = new WeakReference<>(parent); + mWeakCameraView = new WeakReference<>(cameraView); // loadShutterSound(parent); - } - - @Override - protected void finalize() throws Throwable { - Log.i(TAG, "CameraThread#finalize"); - super.finalize(); - } - - public AbstractUVCCameraHandler getHandler() { - if (DEBUG) Log.v(TAG_THREAD, "getHandler:"); - synchronized (mSync) { - if (mHandler == null) - try { - mSync.wait(); - } catch (final InterruptedException e) { - } - } - return mHandler; - } - - public int getWidth() { - synchronized (mSync) { - return mWidth; - } - } - - public int getHeight() { - synchronized (mSync) { - return mHeight; - } - } - - public boolean isCameraOpened() { - synchronized (mSync) { - return mUVCCamera != null; - } - } - - public boolean isPreviewing() { - synchronized (mSync) { - return mUVCCamera != null && mIsPreviewing; - } - } - - public boolean isRecording() { - synchronized (mSync) { - return (mUVCCamera != null) && (mMuxer != null); - } - } + } + + @Override + protected void finalize() throws Throwable { + Log.i(TAG, "CameraThread#finalize"); + super.finalize(); + } + + public AbstractUVCCameraHandler getHandler() { + if (DEBUG) Log.v(TAG_THREAD, "getHandler:"); + synchronized (mSync) { + if (mHandler == null) + try { + mSync.wait(); + } catch (final InterruptedException e) { + } + } + return mHandler; + } + + public int getWidth() { + synchronized (mSync) { + return mWidth; + } + } + + public int getHeight() { + synchronized (mSync) { + return mHeight; + } + } + + public boolean isCameraOpened() { + synchronized (mSync) { + return mUVCCamera != null; + } + } + + public boolean isPreviewing() { + synchronized (mSync) { + return mUVCCamera != null && mIsPreviewing; + } + } + + public boolean isRecording() { + synchronized (mSync) { + return (mUVCCamera != null) && (mH264Consumer != null); + } + } // public boolean isAudioRecording(){ // synchronized (mSync){ @@ -490,124 +498,126 @@ public abstract class AbstractUVCCameraHandler extends Handler { // } // } - public boolean isEqual(final UsbDevice device) { - return (mUVCCamera != null) && (mUVCCamera.getDevice() != null) && mUVCCamera.getDevice().equals(device); - } - - public void handleOpen(final USBMonitor.UsbControlBlock ctrlBlock) { - if (DEBUG) Log.v(TAG_THREAD, "handleOpen:"); - handleClose(); - try { - final UVCCamera camera = new UVCCamera(); - camera.open(ctrlBlock); - synchronized (mSync) { - mUVCCamera = camera; - } - callOnOpen(); - } catch (final Exception e) { - callOnError(e); - } - if (DEBUG) Log.i(TAG, "supportedSize:" + (mUVCCamera != null ? mUVCCamera.getSupportedSize() : null)); - } - - public void handleClose() { - if (DEBUG) Log.v(TAG_THREAD, "handleClose:"); - handleStopRecording(); - final UVCCamera camera; - synchronized (mSync) { - camera = mUVCCamera; - mUVCCamera = null; - } - if (camera != null) { - camera.stopPreview(); - camera.destroy(); - callOnClose(); - } - } - - public void handleStartPreview(final Object surface) { - if (DEBUG) Log.v(TAG_THREAD, "handleStartPreview:"); - if ((mUVCCamera == null) || mIsPreviewing) return; - try { - mUVCCamera.setPreviewSize(mWidth, mHeight, 1, 31, mPreviewMode, mBandwidthFactor); - // 获取USB Camera预览数据,使用NV21颜色会失真 - // 无论使用YUV还是MPEG,setFrameCallback的设置效果一致 + public boolean isEqual(final UsbDevice device) { + return (mUVCCamera != null) && (mUVCCamera.getDevice() != null) && mUVCCamera.getDevice().equals(device); + } + + public void handleOpen(final USBMonitor.UsbControlBlock ctrlBlock) { + if (DEBUG) Log.v(TAG_THREAD, "handleOpen:"); + handleClose(); + try { + final UVCCamera camera = new UVCCamera(); + camera.open(ctrlBlock); + synchronized (mSync) { + mUVCCamera = camera; + } + callOnOpen(); + } catch (final Exception e) { + callOnError(e); + } + if (DEBUG) + Log.i(TAG, "supportedSize:" + (mUVCCamera != null ? mUVCCamera.getSupportedSize() : null)); + } + + public void handleClose() { + if (DEBUG) Log.v(TAG_THREAD, "handleClose:"); + handleStopPusher(); + final UVCCamera camera; + synchronized (mSync) { + camera = mUVCCamera; + mUVCCamera = null; + } + if (camera != null) { + camera.stopPreview(); + camera.destroy(); + callOnClose(); + } + } + + public void handleStartPreview(final Object surface) { + if (DEBUG) Log.v(TAG_THREAD, "handleStartPreview:"); + if ((mUVCCamera == null) || mIsPreviewing) return; + try { + mUVCCamera.setPreviewSize(mWidth, mHeight, 1, 31, mPreviewMode, mBandwidthFactor); + // 获取USB Camera预览数据,使用NV21颜色会失真 + // 无论使用YUV还是MPEG,setFrameCallback的设置效果一致 // mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21); - mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_YUV420SP); - } catch (final IllegalArgumentException e) { - try { - // fallback to YUV mode - mUVCCamera.setPreviewSize(mWidth, mHeight, 1, 31, UVCCamera.DEFAULT_PREVIEW_MODE, mBandwidthFactor); - } catch (final IllegalArgumentException e1) { - callOnError(e1); - return; - } - } - if (surface instanceof SurfaceHolder) { - mUVCCamera.setPreviewDisplay((SurfaceHolder)surface); - } if (surface instanceof Surface) { - mUVCCamera.setPreviewDisplay((Surface)surface); - } else { - mUVCCamera.setPreviewTexture((SurfaceTexture)surface); - } - mUVCCamera.startPreview(); - mUVCCamera.updateCameraParams(); - synchronized (mSync) { - mIsPreviewing = true; - } - callOnStartPreview(); - } - - public void handleStopPreview() { - if (DEBUG) Log.v(TAG_THREAD, "handleStopPreview:"); - if (mIsPreviewing) { - if (mUVCCamera != null) { - mUVCCamera.stopPreview(); - mUVCCamera.setFrameCallback(null, 0); - } - synchronized (mSync) { - mIsPreviewing = false; - mSync.notifyAll(); - } - callOnStopPreview(); - } - if (DEBUG) Log.v(TAG_THREAD, "handleStopPreview:finished"); - } - - // 捕获静态图片 - public void handleCaptureStill(final String path) { - if (DEBUG) Log.v(TAG_THREAD, "handleCaptureStill:"); - final Activity parent = mWeakParent.get(); - if (parent == null) return; + mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_YUV420SP); + } catch (final IllegalArgumentException e) { + try { + // fallback to YUV mode + mUVCCamera.setPreviewSize(mWidth, mHeight, 1, 31, UVCCamera.DEFAULT_PREVIEW_MODE, mBandwidthFactor); + } catch (final IllegalArgumentException e1) { + callOnError(e1); + return; + } + } + if (surface instanceof SurfaceHolder) { + mUVCCamera.setPreviewDisplay((SurfaceHolder) surface); + } + if (surface instanceof Surface) { + mUVCCamera.setPreviewDisplay((Surface) surface); + } else { + mUVCCamera.setPreviewTexture((SurfaceTexture) surface); + } + mUVCCamera.startPreview(); + mUVCCamera.updateCameraParams(); + synchronized (mSync) { + mIsPreviewing = true; + } + callOnStartPreview(); + } + + public void handleStopPreview() { + if (DEBUG) Log.v(TAG_THREAD, "handleStopPreview:"); + if (mIsPreviewing) { + if (mUVCCamera != null) { + mUVCCamera.stopPreview(); + mUVCCamera.setFrameCallback(null, 0); + } + synchronized (mSync) { + mIsPreviewing = false; + mSync.notifyAll(); + } + callOnStopPreview(); + } + if (DEBUG) Log.v(TAG_THREAD, "handleStopPreview:finished"); + } + + // 捕获静态图片 + public void handleCaptureStill(final String path) { + if (DEBUG) Log.v(TAG_THREAD, "handleCaptureStill:"); + final Activity parent = mWeakParent.get(); + if (parent == null) return; // mSoundPool.play(mSoundId, 0.2f, 0.2f, 0, 0, 1.0f); // play shutter sound - try { - final Bitmap bitmap = mWeakCameraView.get().captureStillImage(mWidth,mHeight); - // get buffered output stream for saving a captured still image as a file on external storage. - // the file name is came from current time. - // You should use extension name as same as CompressFormat when calling Bitmap#compress. - final File outputFile = TextUtils.isEmpty(path) - ? MediaMuxerWrapper.getCaptureFile(Environment.DIRECTORY_DCIM, ".jpg") - : new File(path); - final BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile)); - try { - try { - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os); - os.flush(); - mHandler.sendMessage(mHandler.obtainMessage(MSG_MEDIA_UPDATE, outputFile.getPath())); - } catch (final IOException e) { - } - } finally { - os.close(); - } - if(mCaptureListener != null) { - mCaptureListener.onCaptureResult(path); - } - } catch (final Exception e) { - callOnError(e); - } - } - - // 开始录制视频 + try { + final Bitmap bitmap = mWeakCameraView.get().captureStillImage(mWidth, mHeight); + // get buffered output stream for saving a captured still image as a file on external storage. + // the file name is came from current time. + // You should use extension name as same as CompressFormat when calling Bitmap#compress. + final File outputFile = TextUtils.isEmpty(path) + ? MediaMuxerWrapper.getCaptureFile(Environment.DIRECTORY_DCIM, ".jpg") + : new File(path); + final BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile)); + try { + try { + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os); + os.flush(); + mHandler.sendMessage(mHandler.obtainMessage(MSG_MEDIA_UPDATE, outputFile.getPath())); + } catch (final IOException e) { + } + } finally { + os.close(); + } + if (mCaptureListener != null) { + mCaptureListener.onCaptureResult(path); + } + } catch (final Exception e) { + callOnError(e); + } + } + + // 开始录制视频 // public void handleStartRecording2(String path) { // if (DEBUG) Log.v(TAG_THREAD, "handleStartRecording:"); // try { @@ -649,133 +659,136 @@ public abstract class AbstractUVCCameraHandler extends Handler { // } // } - private AACEncodeConsumer mAacConsumer; - private H264EncodeConsumer mH264Consumer; + private AACEncodeConsumer mAacConsumer; + private H264EncodeConsumer mH264Consumer; - public void handleStartRecording(RecordParams params){ - if ((mUVCCamera == null) || (mMuxer != null)) - return; - if (params == null) - throw new NullPointerException("RecordParams can not be null!"); + public void handleStartPusher(RecordParams params) { + if ((mUVCCamera == null) || (mH264Consumer != null)) + return; // // 获取USB Camera预览数据 // mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21); - // 初始化混合器 - videoPath = params.getRecordPath(); - mMuxer = new Mp4MediaMuxer(params.getRecordPath(), - params.getRecordDuration() * 60 * 1000,params.isVoiceClose()); - - // 启动视频编码线程 - startVideoRecord(); - // 启动音频编码线程 - if(! params.isVoiceClose()) { - startAudioRecord(); - } - callOnStartRecording(); - } - - - public void handleStopRecording(){ - // 停止混合器 - if (mMuxer != null){ - mMuxer.release(); - mMuxer = null; - Log.i(TAG,TAG+"---->停止本地录制"); - } - // 停止音视频编码线程 - stopAudioRecord(); - stopVideoRecord(); + // 初始化混合器 + if (params != null) { + videoPath = params.getRecordPath(); + mMuxer = new Mp4MediaMuxer(params.getRecordPath(), + params.getRecordDuration() * 60 * 1000, params.isVoiceClose()); + } + // 启动视频编码线程 + startVideoRecord(); + // 启动音频编码线程 + if (!params.isVoiceClose()) { + startAudioRecord(); + } + callOnStartRecording(); + } + + + public void handleStopPusher() { + // 停止混合器 + if (mMuxer != null) { + mMuxer.release(); + mMuxer = null; + Log.i(TAG, TAG + "---->停止本地录制"); + } + // 停止音视频编码线程 + stopAudioRecord(); + stopVideoRecord(); // // 停止捕获视频数据 // if (mUVCCamera != null) { // mUVCCamera.stopCapture(); // } - mWeakCameraView.get().setVideoEncoder(null); - // you should not wait here - callOnStopRecording(); - // 返回路径 - if(mListener != null) { - mListener.onRecordResult(videoPath+".mp4"); - } - } - - private void startVideoRecord() { - mH264Consumer = new H264EncodeConsumer(getWidth(),getHeight()); - mH264Consumer.setOnH264EncodeResultListener(new H264EncodeConsumer.OnH264EncodeResultListener() { - @Override - public void onEncodeResult(byte[] data, int offset, int length, long timestamp) { - if(mListener != null){ - mListener.onEncodeResult(data,offset,length,timestamp,1); - } - } - }); - mH264Consumer.start(); - // 添加混合器 - if(mH264Consumer != null){ - mH264Consumer.setTmpuMuxer(mMuxer); - } - } - - private void stopVideoRecord(){ - if(mH264Consumer != null){ - mH264Consumer.exit(); - mH264Consumer.setTmpuMuxer(null); - try { - Thread t2 = mH264Consumer; - mH264Consumer = null; - if(t2 != null){ - t2.interrupt(); - t2.join(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - private void startAudioRecord(){ - mAacConsumer = new AACEncodeConsumer(); - mAacConsumer.setOnAACEncodeResultListener(new AACEncodeConsumer.OnAACEncodeResultListener() { - @Override - public void onEncodeResult(byte[] data, int offset, int length, long timestamp) { - if(mListener != null){ - mListener.onEncodeResult(data,offset,length,timestamp,0); - } - } - }); - mAacConsumer.start(); - // 添加混合器 - if(mAacConsumer != null){ - mAacConsumer.setTmpuMuxer(mMuxer); - } - } - - private void stopAudioRecord(){ - if(mAacConsumer != null){ - mAacConsumer.exit(); - mAacConsumer.setTmpuMuxer(null); - try { - Thread t1 = mAacConsumer; - mAacConsumer = null; - if(t1 != null){ - t1.interrupt(); - t1.join(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + mWeakCameraView.get().setVideoEncoder(null); + // you should not wait here + callOnStopRecording(); + // 返回路径 + if (mListener != null) { + mListener.onRecordResult(videoPath + ".mp4"); + } + } + + private void startVideoRecord() { + mH264Consumer = new H264EncodeConsumer(getWidth(), getHeight()); + mH264Consumer.setOnH264EncodeResultListener(new H264EncodeConsumer.OnH264EncodeResultListener() { + @Override + public void onEncodeResult(byte[] data, int offset, int length, long timestamp) { + if (mListener != null) { + mListener.onEncodeResult(data, offset, length, timestamp, 1); + } + } + }); + mH264Consumer.start(); + // 添加混合器 + if (mMuxer != null) { + if (mH264Consumer != null) { + mH264Consumer.setTmpuMuxer(mMuxer); + } + } + } + + private void stopVideoRecord() { + if (mH264Consumer != null) { + mH264Consumer.exit(); + mH264Consumer.setTmpuMuxer(null); + try { + Thread t2 = mH264Consumer; + mH264Consumer = null; + if (t2 != null) { + t2.interrupt(); + t2.join(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void startAudioRecord() { + mAacConsumer = new AACEncodeConsumer(); + mAacConsumer.setOnAACEncodeResultListener(new AACEncodeConsumer.OnAACEncodeResultListener() { + @Override + public void onEncodeResult(byte[] data, int offset, int length, long timestamp) { + if (mListener != null) { + mListener.onEncodeResult(data, offset, length, timestamp, 0); + } + } + }); + mAacConsumer.start(); + // 添加混合器 + if (mMuxer != null) { + if (mAacConsumer != null) { + mAacConsumer.setTmpuMuxer(mMuxer); + } + } + } + + private void stopAudioRecord() { + if (mAacConsumer != null) { + mAacConsumer.exit(); + mAacConsumer.setTmpuMuxer(null); + try { + Thread t1 = mAacConsumer; + mAacConsumer = null; + if (t1 != null) { + t1.interrupt(); + t1.join(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } // isAudioThreadStart = false; - } + } - private String picPath = null; + private String picPath = null; - public void handleStillPicture(String picPath) { - this.picPath = picPath; - } + public void handleStillPicture(String picPath) { + this.picPath = picPath; + } - private final IFrameCallback mIFrameCallback = new IFrameCallback() { - @Override - public void onFrame(final ByteBuffer frame) { + private final IFrameCallback mIFrameCallback = new IFrameCallback() { + @Override + public void onFrame(final ByteBuffer frame) { // final MediaVideoBufferEncoder videoEncoder; // synchronized (mSync) { // videoEncoder = mVideoEncoder; @@ -784,172 +797,172 @@ public abstract class AbstractUVCCameraHandler extends Handler { // videoEncoder.frameAvailableSoon(); // videoEncoder.encode(frame); // } - int len = frame.capacity(); - final byte[] yuv = new byte[len]; - frame.get(yuv); - // nv21 yuv data callback - if(mPreviewListener != null) { - mPreviewListener.onPreviewResult(yuv); - } - // 捕获图片 - if(isCaptureStill && ! TextUtils.isEmpty(picPath)) { - isCaptureStill = false; - new Thread(new Runnable() { - @Override - public void run() { - saveYuv2Jpeg(picPath,yuv); - } - }).start(); - - isCaptureStill = false; - } - // 视频 - if(mH264Consumer != null){ - // 修改分辨率参数 - mH264Consumer.setRawYuv(yuv,mWidth,mHeight); - } - } - }; - - private void saveYuv2Jpeg(String path,byte[] data){ - YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, mWidth, mHeight, null); - ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length); - boolean result = yuvImage.compressToJpeg(new Rect(0, 0, mWidth, mHeight), 100, bos); - if(result){ - byte[] buffer = bos.toByteArray(); - Bitmap bmp = BitmapFactory.decodeByteArray(buffer, 0, buffer.length); - - File file = new File(path); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos); - try { - fos.flush(); - fos.close(); - bmp.recycle(); - if(mCaptureListener != null) { - mCaptureListener.onCaptureResult(path); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - try { - bos.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) - public void handleUpdateMedia(final String path) { - if (DEBUG) Log.v(TAG_THREAD, "handleUpdateMedia:path=" + path); - final Activity parent = mWeakParent.get(); - final boolean released = (mHandler == null) || mHandler.mReleased; - if (parent != null && parent.getApplicationContext() != null) { - try { - if (DEBUG) Log.i(TAG, "MediaScannerConnection#scanFile"); - MediaScannerConnection.scanFile(parent.getApplicationContext(), new String[]{ path }, null, null); - } catch (final Exception e) { - Log.e(TAG, "handleUpdateMedia:", e); - } - if (released || parent.isDestroyed()) - handleRelease(); - } else { - Log.w(TAG, "MainActivity already destroyed"); - // give up to add this movie to MediaStore now. - // Seeing this movie on Gallery app etc. will take a lot of time. - handleRelease(); - } - } - - public void handleRelease() { - if (DEBUG) Log.v(TAG_THREAD, "handleRelease:mIsRecording=" + mIsRecording); - handleClose(); - mCallbacks.clear(); - if (!mIsRecording) { - mHandler.mReleased = true; - Looper.myLooper().quit(); - } - if (DEBUG) Log.v(TAG_THREAD, "handleRelease:finished"); - } - - // 自动对焦 - public void handleCameraFoucs() { - if (DEBUG) Log.v(TAG_THREAD, "handleStartPreview:"); - if ((mUVCCamera == null) || !mIsPreviewing) - return; - mUVCCamera.setAutoFocus(true); - } - - // 获取支持的分辨率 - public List getSupportedSizes() { - if ((mUVCCamera == null) || !mIsPreviewing) - return null; - return mUVCCamera.getSupportedSizeList(); - } - - private final MediaEncoder.MediaEncoderListener mMediaEncoderListener = new MediaEncoder.MediaEncoderListener() { - @Override - public void onPrepared(final MediaEncoder encoder) { - if (DEBUG) Log.v(TAG, "onPrepared:encoder=" + encoder); - mIsRecording = true; - if (encoder instanceof MediaVideoEncoder) - try { - mWeakCameraView.get().setVideoEncoder((MediaVideoEncoder)encoder); - } catch (final Exception e) { - Log.e(TAG, "onPrepared:", e); - } - if (encoder instanceof MediaSurfaceEncoder) - try { - mWeakCameraView.get().setVideoEncoder((MediaSurfaceEncoder)encoder); - mUVCCamera.startCapture(((MediaSurfaceEncoder)encoder).getInputSurface()); - } catch (final Exception e) { - Log.e(TAG, "onPrepared:", e); - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) - @Override - public void onStopped(final MediaEncoder encoder) { - if (DEBUG) Log.v(TAG_THREAD, "onStopped:encoder=" + encoder); - if ((encoder instanceof MediaVideoEncoder) - || (encoder instanceof MediaSurfaceEncoder)) - try { - mIsRecording = false; - final Activity parent = mWeakParent.get(); - mWeakCameraView.get().setVideoEncoder(null); - synchronized (mSync) { - if (mUVCCamera != null) { - mUVCCamera.stopCapture(); - } - } - final String path = encoder.getOutputPath(); - if (!TextUtils.isEmpty(path)) { - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_MEDIA_UPDATE, path), 1000); - } else { - final boolean released = (mHandler == null) || mHandler.mReleased; - if (released || parent == null || parent.isDestroyed()) { - handleRelease(); - } - } - } catch (final Exception e) { - Log.e(TAG, "onPrepared:", e); - } - } - - @Override - public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) { - if(mListener != null){ - mListener.onEncodeResult(data, offset, length, timestamp, type); - } - } - - }; + int len = frame.capacity(); + final byte[] yuv = new byte[len]; + frame.get(yuv); + // nv21 yuv data callback + if (mPreviewListener != null) { + mPreviewListener.onPreviewResult(yuv); + } + // 捕获图片 + if (isCaptureStill && !TextUtils.isEmpty(picPath)) { + isCaptureStill = false; + new Thread(new Runnable() { + @Override + public void run() { + saveYuv2Jpeg(picPath, yuv); + } + }).start(); + + isCaptureStill = false; + } + // 视频 + if (mH264Consumer != null) { + // 修改分辨率参数 + mH264Consumer.setRawYuv(yuv, mWidth, mHeight); + } + } + }; + + private void saveYuv2Jpeg(String path, byte[] data) { + YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, mWidth, mHeight, null); + ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length); + boolean result = yuvImage.compressToJpeg(new Rect(0, 0, mWidth, mHeight), 100, bos); + if (result) { + byte[] buffer = bos.toByteArray(); + Bitmap bmp = BitmapFactory.decodeByteArray(buffer, 0, buffer.length); + + File file = new File(path); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos); + try { + fos.flush(); + fos.close(); + bmp.recycle(); + if (mCaptureListener != null) { + mCaptureListener.onCaptureResult(path); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + bos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + public void handleUpdateMedia(final String path) { + if (DEBUG) Log.v(TAG_THREAD, "handleUpdateMedia:path=" + path); + final Activity parent = mWeakParent.get(); + final boolean released = (mHandler == null) || mHandler.mReleased; + if (parent != null && parent.getApplicationContext() != null) { + try { + if (DEBUG) Log.i(TAG, "MediaScannerConnection#scanFile"); + MediaScannerConnection.scanFile(parent.getApplicationContext(), new String[]{path}, null, null); + } catch (final Exception e) { + Log.e(TAG, "handleUpdateMedia:", e); + } + if (released || parent.isDestroyed()) + handleRelease(); + } else { + Log.w(TAG, "MainActivity already destroyed"); + // give up to add this movie to MediaStore now. + // Seeing this movie on Gallery app etc. will take a lot of time. + handleRelease(); + } + } + + public void handleRelease() { + if (DEBUG) Log.v(TAG_THREAD, "handleRelease:mIsRecording=" + mIsRecording); + handleClose(); + mCallbacks.clear(); + if (!mIsRecording) { + mHandler.mReleased = true; + Looper.myLooper().quit(); + } + if (DEBUG) Log.v(TAG_THREAD, "handleRelease:finished"); + } + + // 自动对焦 + public void handleCameraFoucs() { + if (DEBUG) Log.v(TAG_THREAD, "handleStartPreview:"); + if ((mUVCCamera == null) || !mIsPreviewing) + return; + mUVCCamera.setAutoFocus(true); + } + + // 获取支持的分辨率 + public List getSupportedSizes() { + if ((mUVCCamera == null) || !mIsPreviewing) + return null; + return mUVCCamera.getSupportedSizeList(); + } + + private final MediaEncoder.MediaEncoderListener mMediaEncoderListener = new MediaEncoder.MediaEncoderListener() { + @Override + public void onPrepared(final MediaEncoder encoder) { + if (DEBUG) Log.v(TAG, "onPrepared:encoder=" + encoder); + mIsRecording = true; + if (encoder instanceof MediaVideoEncoder) + try { + mWeakCameraView.get().setVideoEncoder((MediaVideoEncoder) encoder); + } catch (final Exception e) { + Log.e(TAG, "onPrepared:", e); + } + if (encoder instanceof MediaSurfaceEncoder) + try { + mWeakCameraView.get().setVideoEncoder((MediaSurfaceEncoder) encoder); + mUVCCamera.startCapture(((MediaSurfaceEncoder) encoder).getInputSurface()); + } catch (final Exception e) { + Log.e(TAG, "onPrepared:", e); + } + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + @Override + public void onStopped(final MediaEncoder encoder) { + if (DEBUG) Log.v(TAG_THREAD, "onStopped:encoder=" + encoder); + if ((encoder instanceof MediaVideoEncoder) + || (encoder instanceof MediaSurfaceEncoder)) + try { + mIsRecording = false; + final Activity parent = mWeakParent.get(); + mWeakCameraView.get().setVideoEncoder(null); + synchronized (mSync) { + if (mUVCCamera != null) { + mUVCCamera.stopCapture(); + } + } + final String path = encoder.getOutputPath(); + if (!TextUtils.isEmpty(path)) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_MEDIA_UPDATE, path), 1000); + } else { + final boolean released = (mHandler == null) || mHandler.mReleased; + if (released || parent == null || parent.isDestroyed()) { + handleRelease(); + } + } + } catch (final Exception e) { + Log.e(TAG, "onPrepared:", e); + } + } + + @Override + public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) { + if (mListener != null) { + mListener.onEncodeResult(data, offset, length, timestamp, type); + } + } + + }; // private void loadShutterSound(final Context context) { // // get system stream type using reflection @@ -973,10 +986,10 @@ public abstract class AbstractUVCCameraHandler extends Handler { // mSoundId = mSoundPool.load(context, R.raw.camera_click, 1); // } - /** - * prepare and load shutter sound for still image capturing - */ - @SuppressWarnings("deprecation") + /** + * prepare and load shutter sound for still image capturing + */ + @SuppressWarnings("deprecation") // private void loadShutterSound(final Context context) { // // get system stream type using reflection // int streamType; @@ -999,118 +1012,118 @@ public abstract class AbstractUVCCameraHandler extends Handler { // mSoundId = mSoundPool.load(context, R.raw.camera_click, 1); // } - @Override - public void run() { - Looper.prepare(); - AbstractUVCCameraHandler handler = null; - try { - final Constructor constructor = mHandlerClass.getDeclaredConstructor(CameraThread.class); - handler = constructor.newInstance(this); - } catch (final NoSuchMethodException e) { - Log.w(TAG, e); - } catch (final IllegalAccessException e) { - Log.w(TAG, e); - } catch (final InstantiationException e) { - Log.w(TAG, e); - } catch (final InvocationTargetException e) { - Log.w(TAG, e); - } - if (handler != null) { - synchronized (mSync) { - mHandler = handler; - mSync.notifyAll(); - } - Looper.loop(); + @Override + public void run() { + Looper.prepare(); + AbstractUVCCameraHandler handler = null; + try { + final Constructor constructor = mHandlerClass.getDeclaredConstructor(CameraThread.class); + handler = constructor.newInstance(this); + } catch (final NoSuchMethodException e) { + Log.w(TAG, e); + } catch (final IllegalAccessException e) { + Log.w(TAG, e); + } catch (final InstantiationException e) { + Log.w(TAG, e); + } catch (final InvocationTargetException e) { + Log.w(TAG, e); + } + if (handler != null) { + synchronized (mSync) { + mHandler = handler; + mSync.notifyAll(); + } + Looper.loop(); // if (mSoundPool != null) { // mSoundPool.release(); // mSoundPool = null; // } - if (mHandler != null) { - mHandler.mReleased = true; - } - } - mCallbacks.clear(); - synchronized (mSync) { - mHandler = null; - mSync.notifyAll(); - } - } - - private void callOnOpen() { - for (final CameraCallback callback: mCallbacks) { - try { - callback.onOpen(); - } catch (final Exception e) { - mCallbacks.remove(callback); - Log.w(TAG, e); - } - } - } - - private void callOnClose() { - for (final CameraCallback callback: mCallbacks) { - try { - callback.onClose(); - } catch (final Exception e) { - mCallbacks.remove(callback); - Log.w(TAG, e); - } - } - } - - private void callOnStartPreview() { - for (final CameraCallback callback: mCallbacks) { - try { - callback.onStartPreview(); - } catch (final Exception e) { - mCallbacks.remove(callback); - Log.w(TAG, e); - } - } - } - - private void callOnStopPreview() { - for (final CameraCallback callback: mCallbacks) { - try { - callback.onStopPreview(); - } catch (final Exception e) { - mCallbacks.remove(callback); - Log.w(TAG, e); - } - } - } - - private void callOnStartRecording() { - for (final CameraCallback callback: mCallbacks) { - try { - callback.onStartRecording(); - } catch (final Exception e) { - mCallbacks.remove(callback); - Log.w(TAG, e); - } - } - } - - private void callOnStopRecording() { - for (final CameraCallback callback: mCallbacks) { - try { - callback.onStopRecording(); - } catch (final Exception e) { - mCallbacks.remove(callback); - Log.w(TAG, e); - } - } - } - - private void callOnError(final Exception e) { - for (final CameraCallback callback: mCallbacks) { - try { - callback.onError(e); - } catch (final Exception e1) { - mCallbacks.remove(callback); - Log.w(TAG, e); - } - } - } - } + if (mHandler != null) { + mHandler.mReleased = true; + } + } + mCallbacks.clear(); + synchronized (mSync) { + mHandler = null; + mSync.notifyAll(); + } + } + + private void callOnOpen() { + for (final CameraCallback callback : mCallbacks) { + try { + callback.onOpen(); + } catch (final Exception e) { + mCallbacks.remove(callback); + Log.w(TAG, e); + } + } + } + + private void callOnClose() { + for (final CameraCallback callback : mCallbacks) { + try { + callback.onClose(); + } catch (final Exception e) { + mCallbacks.remove(callback); + Log.w(TAG, e); + } + } + } + + private void callOnStartPreview() { + for (final CameraCallback callback : mCallbacks) { + try { + callback.onStartPreview(); + } catch (final Exception e) { + mCallbacks.remove(callback); + Log.w(TAG, e); + } + } + } + + private void callOnStopPreview() { + for (final CameraCallback callback : mCallbacks) { + try { + callback.onStopPreview(); + } catch (final Exception e) { + mCallbacks.remove(callback); + Log.w(TAG, e); + } + } + } + + private void callOnStartRecording() { + for (final CameraCallback callback : mCallbacks) { + try { + callback.onStartRecording(); + } catch (final Exception e) { + mCallbacks.remove(callback); + Log.w(TAG, e); + } + } + } + + private void callOnStopRecording() { + for (final CameraCallback callback : mCallbacks) { + try { + callback.onStopRecording(); + } catch (final Exception e) { + mCallbacks.remove(callback); + Log.w(TAG, e); + } + } + } + + private void callOnError(final Exception e) { + for (final CameraCallback callback : mCallbacks) { + try { + callback.onError(e); + } catch (final Exception e1) { + mCallbacks.remove(callback); + Log.w(TAG, e); + } + } + } + } }