|
|
@ -51,8 +51,7 @@ import java.util.concurrent.CopyOnWriteArraySet; |
|
|
|
|
|
|
|
/** |
|
|
|
* Camera业务处理抽象类 |
|
|
|
* |
|
|
|
* */ |
|
|
|
*/ |
|
|
|
public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
|
|
|
|
private static final boolean DEBUG = true; // TODO set false on release
|
|
|
@ -62,11 +61,17 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
// 对外回调接口
|
|
|
|
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); |
|
|
|
} |
|
|
|
|
|
|
@ -74,12 +79,13 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
public static OnPreViewResultListener mPreviewListener; |
|
|
|
public static OnCaptureListener mCaptureListener; |
|
|
|
|
|
|
|
public interface OnEncodeResultListener{ |
|
|
|
public interface OnEncodeResultListener { |
|
|
|
void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type); |
|
|
|
|
|
|
|
void onRecordResult(String videoPath); |
|
|
|
} |
|
|
|
|
|
|
|
public interface OnPreViewResultListener{ |
|
|
|
public interface OnPreViewResultListener { |
|
|
|
void onPreviewResult(byte[] data); |
|
|
|
} |
|
|
|
|
|
|
@ -184,7 +190,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
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); |
|
|
|
throw new IllegalArgumentException("surface should be one of SurfaceHolder, Surface or SurfaceTexture: " + surface); |
|
|
|
} |
|
|
|
|
|
|
|
sendMessage(obtainMessage(MSG_PREVIEW_START, surface)); |
|
|
@ -198,7 +204,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
public void stopPreview() { |
|
|
|
if (DEBUG) Log.v(TAG, "stopPreview:"); |
|
|
|
removeMessages(MSG_PREVIEW_START); |
|
|
|
if(isRecording()) { |
|
|
|
if (isRecording()) { |
|
|
|
stopRecording(); |
|
|
|
} |
|
|
|
if (isPreviewing()) { |
|
|
@ -220,7 +226,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
if (DEBUG) Log.v(TAG, "stopPreview:finished"); |
|
|
|
} |
|
|
|
|
|
|
|
public void captureStill(final String path,AbstractUVCCameraHandler.OnCaptureListener listener) { |
|
|
|
public void captureStill(final String path, AbstractUVCCameraHandler.OnCaptureListener listener) { |
|
|
|
AbstractUVCCameraHandler.mCaptureListener = listener; |
|
|
|
checkReleased(); |
|
|
|
sendMessage(obtainMessage(MSG_CAPTURE_STILL, path)); |
|
|
@ -239,11 +245,11 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
sendEmptyMessage(MSG_CAPTURE_STOP); |
|
|
|
} |
|
|
|
|
|
|
|
public void startCameraFoucs(){ |
|
|
|
public void startCameraFoucs() { |
|
|
|
sendEmptyMessage(MSG_CAMERA_FOUCS); |
|
|
|
} |
|
|
|
|
|
|
|
public List<Size> getSupportedPreviewSizes(){ |
|
|
|
public List<Size> getSupportedPreviewSizes() { |
|
|
|
return mWeakThread.get().getSupportedSizes(); |
|
|
|
} |
|
|
|
|
|
|
@ -345,7 +351,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
if (thread == null) return; |
|
|
|
switch (msg.what) { |
|
|
|
case MSG_OPEN: |
|
|
|
thread.handleOpen((USBMonitor.UsbControlBlock)msg.obj); |
|
|
|
thread.handleOpen((USBMonitor.UsbControlBlock) msg.obj); |
|
|
|
break; |
|
|
|
case MSG_CLOSE: |
|
|
|
thread.handleClose(); |
|
|
@ -358,17 +364,17 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
break; |
|
|
|
case MSG_CAPTURE_STILL: |
|
|
|
// thread.handleCaptureStill((String)msg.obj);
|
|
|
|
thread.handleStillPicture((String)msg.obj); |
|
|
|
thread.handleStillPicture((String) msg.obj); |
|
|
|
break; |
|
|
|
case MSG_CAPTURE_START: |
|
|
|
// thread.handleStartRecording((String)msg.obj);
|
|
|
|
thread.handleStartRecording((RecordParams)msg.obj); |
|
|
|
thread.handleStartPusher((RecordParams) msg.obj); |
|
|
|
break; |
|
|
|
case MSG_CAPTURE_STOP: |
|
|
|
thread.handleStopRecording(); |
|
|
|
thread.handleStopPusher(); |
|
|
|
break; |
|
|
|
case MSG_MEDIA_UPDATE: |
|
|
|
thread.handleUpdateMedia((String)msg.obj); |
|
|
|
thread.handleUpdateMedia((String) msg.obj); |
|
|
|
break; |
|
|
|
case MSG_RELEASE: |
|
|
|
thread.handleRelease(); |
|
|
@ -402,14 +408,16 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
// 处理与Camera相关的逻辑,比如获取byte数据流等
|
|
|
|
private UVCCamera mUVCCamera; |
|
|
|
|
|
|
|
// private MediaMuxerWrapper mMuxer;
|
|
|
|
// private MediaMuxerWrapper mMuxer;
|
|
|
|
private MediaVideoBufferEncoder mVideoEncoder; |
|
|
|
private Mp4MediaMuxer mMuxer; |
|
|
|
private boolean isPushing; |
|
|
|
private String videoPath; |
|
|
|
// private boolean isAudioThreadStart;
|
|
|
|
|
|
|
|
/** 构造方法 |
|
|
|
* |
|
|
|
/** |
|
|
|
* 构造方法 |
|
|
|
* <p> |
|
|
|
* clazz 继承于AbstractUVCCameraHandler |
|
|
|
* parent Activity子类 |
|
|
|
* cameraView 用于捕获静止图像 |
|
|
@ -480,7 +488,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
|
|
|
|
public boolean isRecording() { |
|
|
|
synchronized (mSync) { |
|
|
|
return (mUVCCamera != null) && (mMuxer != null); |
|
|
|
return (mUVCCamera != null) && (mH264Consumer != null); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -507,12 +515,13 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} catch (final Exception e) { |
|
|
|
callOnError(e); |
|
|
|
} |
|
|
|
if (DEBUG) Log.i(TAG, "supportedSize:" + (mUVCCamera != null ? mUVCCamera.getSupportedSize() : null)); |
|
|
|
if (DEBUG) |
|
|
|
Log.i(TAG, "supportedSize:" + (mUVCCamera != null ? mUVCCamera.getSupportedSize() : null)); |
|
|
|
} |
|
|
|
|
|
|
|
public void handleClose() { |
|
|
|
if (DEBUG) Log.v(TAG_THREAD, "handleClose:"); |
|
|
|
handleStopRecording(); |
|
|
|
handleStopPusher(); |
|
|
|
final UVCCamera camera; |
|
|
|
synchronized (mSync) { |
|
|
|
camera = mUVCCamera; |
|
|
@ -544,11 +553,12 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
} |
|
|
|
if (surface instanceof SurfaceHolder) { |
|
|
|
mUVCCamera.setPreviewDisplay((SurfaceHolder)surface); |
|
|
|
} if (surface instanceof Surface) { |
|
|
|
mUVCCamera.setPreviewDisplay((Surface)surface); |
|
|
|
mUVCCamera.setPreviewDisplay((SurfaceHolder) surface); |
|
|
|
} |
|
|
|
if (surface instanceof Surface) { |
|
|
|
mUVCCamera.setPreviewDisplay((Surface) surface); |
|
|
|
} else { |
|
|
|
mUVCCamera.setPreviewTexture((SurfaceTexture)surface); |
|
|
|
mUVCCamera.setPreviewTexture((SurfaceTexture) surface); |
|
|
|
} |
|
|
|
mUVCCamera.startPreview(); |
|
|
|
mUVCCamera.updateCameraParams(); |
|
|
@ -581,7 +591,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
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); |
|
|
|
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.
|
|
|
@ -599,7 +609,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} finally { |
|
|
|
os.close(); |
|
|
|
} |
|
|
|
if(mCaptureListener != null) { |
|
|
|
if (mCaptureListener != null) { |
|
|
|
mCaptureListener.onCaptureResult(path); |
|
|
|
} |
|
|
|
} catch (final Exception e) { |
|
|
@ -652,34 +662,33 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
private AACEncodeConsumer mAacConsumer; |
|
|
|
private H264EncodeConsumer mH264Consumer; |
|
|
|
|
|
|
|
public void handleStartRecording(RecordParams params){ |
|
|
|
if ((mUVCCamera == null) || (mMuxer != null)) |
|
|
|
public void handleStartPusher(RecordParams params) { |
|
|
|
if ((mUVCCamera == null) || (mH264Consumer != null)) |
|
|
|
return; |
|
|
|
if (params == null) |
|
|
|
throw new NullPointerException("RecordParams can not be null!"); |
|
|
|
// // 获取USB Camera预览数据
|
|
|
|
// mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21);
|
|
|
|
// 初始化混合器
|
|
|
|
if (params != null) { |
|
|
|
videoPath = params.getRecordPath(); |
|
|
|
mMuxer = new Mp4MediaMuxer(params.getRecordPath(), |
|
|
|
params.getRecordDuration() * 60 * 1000,params.isVoiceClose()); |
|
|
|
|
|
|
|
params.getRecordDuration() * 60 * 1000, params.isVoiceClose()); |
|
|
|
} |
|
|
|
// 启动视频编码线程
|
|
|
|
startVideoRecord(); |
|
|
|
// 启动音频编码线程
|
|
|
|
if(! params.isVoiceClose()) { |
|
|
|
if (!params.isVoiceClose()) { |
|
|
|
startAudioRecord(); |
|
|
|
} |
|
|
|
callOnStartRecording(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void handleStopRecording(){ |
|
|
|
public void handleStopPusher() { |
|
|
|
// 停止混合器
|
|
|
|
if (mMuxer != null){ |
|
|
|
if (mMuxer != null) { |
|
|
|
mMuxer.release(); |
|
|
|
mMuxer = null; |
|
|
|
Log.i(TAG,TAG+"---->停止本地录制"); |
|
|
|
Log.i(TAG, TAG + "---->停止本地录制"); |
|
|
|
} |
|
|
|
// 停止音视频编码线程
|
|
|
|
stopAudioRecord(); |
|
|
@ -692,36 +701,38 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
// you should not wait here
|
|
|
|
callOnStopRecording(); |
|
|
|
// 返回路径
|
|
|
|
if(mListener != null) { |
|
|
|
mListener.onRecordResult(videoPath+".mp4"); |
|
|
|
if (mListener != null) { |
|
|
|
mListener.onRecordResult(videoPath + ".mp4"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void startVideoRecord() { |
|
|
|
mH264Consumer = new H264EncodeConsumer(getWidth(),getHeight()); |
|
|
|
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); |
|
|
|
if (mListener != null) { |
|
|
|
mListener.onEncodeResult(data, offset, length, timestamp, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
mH264Consumer.start(); |
|
|
|
// 添加混合器
|
|
|
|
if(mH264Consumer != null){ |
|
|
|
if (mMuxer != null) { |
|
|
|
if (mH264Consumer != null) { |
|
|
|
mH264Consumer.setTmpuMuxer(mMuxer); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void stopVideoRecord(){ |
|
|
|
if(mH264Consumer != null){ |
|
|
|
private void stopVideoRecord() { |
|
|
|
if (mH264Consumer != null) { |
|
|
|
mH264Consumer.exit(); |
|
|
|
mH264Consumer.setTmpuMuxer(null); |
|
|
|
try { |
|
|
|
Thread t2 = mH264Consumer; |
|
|
|
mH264Consumer = null; |
|
|
|
if(t2 != null){ |
|
|
|
if (t2 != null) { |
|
|
|
t2.interrupt(); |
|
|
|
t2.join(); |
|
|
|
} |
|
|
@ -731,31 +742,33 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void startAudioRecord(){ |
|
|
|
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); |
|
|
|
if (mListener != null) { |
|
|
|
mListener.onEncodeResult(data, offset, length, timestamp, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
mAacConsumer.start(); |
|
|
|
// 添加混合器
|
|
|
|
if(mAacConsumer != null){ |
|
|
|
if (mMuxer != null) { |
|
|
|
if (mAacConsumer != null) { |
|
|
|
mAacConsumer.setTmpuMuxer(mMuxer); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void stopAudioRecord(){ |
|
|
|
if(mAacConsumer != null){ |
|
|
|
private void stopAudioRecord() { |
|
|
|
if (mAacConsumer != null) { |
|
|
|
mAacConsumer.exit(); |
|
|
|
mAacConsumer.setTmpuMuxer(null); |
|
|
|
try { |
|
|
|
Thread t1 = mAacConsumer; |
|
|
|
mAacConsumer = null; |
|
|
|
if(t1 != null){ |
|
|
|
if (t1 != null) { |
|
|
|
t1.interrupt(); |
|
|
|
t1.join(); |
|
|
|
} |
|
|
@ -788,34 +801,34 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
final byte[] yuv = new byte[len]; |
|
|
|
frame.get(yuv); |
|
|
|
// nv21 yuv data callback
|
|
|
|
if(mPreviewListener != null) { |
|
|
|
if (mPreviewListener != null) { |
|
|
|
mPreviewListener.onPreviewResult(yuv); |
|
|
|
} |
|
|
|
// 捕获图片
|
|
|
|
if(isCaptureStill && ! TextUtils.isEmpty(picPath)) { |
|
|
|
if (isCaptureStill && !TextUtils.isEmpty(picPath)) { |
|
|
|
isCaptureStill = false; |
|
|
|
new Thread(new Runnable() { |
|
|
|
@Override |
|
|
|
public void run() { |
|
|
|
saveYuv2Jpeg(picPath,yuv); |
|
|
|
saveYuv2Jpeg(picPath, yuv); |
|
|
|
} |
|
|
|
}).start(); |
|
|
|
|
|
|
|
isCaptureStill = false; |
|
|
|
} |
|
|
|
// 视频
|
|
|
|
if(mH264Consumer != null){ |
|
|
|
if (mH264Consumer != null) { |
|
|
|
// 修改分辨率参数
|
|
|
|
mH264Consumer.setRawYuv(yuv,mWidth,mHeight); |
|
|
|
mH264Consumer.setRawYuv(yuv, mWidth, mHeight); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
private void saveYuv2Jpeg(String path,byte[] data){ |
|
|
|
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){ |
|
|
|
if (result) { |
|
|
|
byte[] buffer = bos.toByteArray(); |
|
|
|
Bitmap bmp = BitmapFactory.decodeByteArray(buffer, 0, buffer.length); |
|
|
|
|
|
|
@ -831,7 +844,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
fos.flush(); |
|
|
|
fos.close(); |
|
|
|
bmp.recycle(); |
|
|
|
if(mCaptureListener != null) { |
|
|
|
if (mCaptureListener != null) { |
|
|
|
mCaptureListener.onCaptureResult(path); |
|
|
|
} |
|
|
|
} catch (IOException e) { |
|
|
@ -853,7 +866,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
if (parent != null && parent.getApplicationContext() != null) { |
|
|
|
try { |
|
|
|
if (DEBUG) Log.i(TAG, "MediaScannerConnection#scanFile"); |
|
|
|
MediaScannerConnection.scanFile(parent.getApplicationContext(), new String[]{ path }, null, null); |
|
|
|
MediaScannerConnection.scanFile(parent.getApplicationContext(), new String[]{path}, null, null); |
|
|
|
} catch (final Exception e) { |
|
|
|
Log.e(TAG, "handleUpdateMedia:", e); |
|
|
|
} |
|
|
@ -900,14 +913,14 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
mIsRecording = true; |
|
|
|
if (encoder instanceof MediaVideoEncoder) |
|
|
|
try { |
|
|
|
mWeakCameraView.get().setVideoEncoder((MediaVideoEncoder)encoder); |
|
|
|
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()); |
|
|
|
mWeakCameraView.get().setVideoEncoder((MediaSurfaceEncoder) encoder); |
|
|
|
mUVCCamera.startCapture(((MediaSurfaceEncoder) encoder).getInputSurface()); |
|
|
|
} catch (final Exception e) { |
|
|
|
Log.e(TAG, "onPrepared:", e); |
|
|
|
} |
|
|
@ -944,7 +957,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) { |
|
|
|
if(mListener != null){ |
|
|
|
if (mListener != null) { |
|
|
|
mListener.onEncodeResult(data, offset, length, timestamp, type); |
|
|
|
} |
|
|
|
} |
|
|
@ -1037,7 +1050,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
|
|
|
|
private void callOnOpen() { |
|
|
|
for (final CameraCallback callback: mCallbacks) { |
|
|
|
for (final CameraCallback callback : mCallbacks) { |
|
|
|
try { |
|
|
|
callback.onOpen(); |
|
|
|
} catch (final Exception e) { |
|
|
@ -1048,7 +1061,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
|
|
|
|
private void callOnClose() { |
|
|
|
for (final CameraCallback callback: mCallbacks) { |
|
|
|
for (final CameraCallback callback : mCallbacks) { |
|
|
|
try { |
|
|
|
callback.onClose(); |
|
|
|
} catch (final Exception e) { |
|
|
@ -1059,7 +1072,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
|
|
|
|
private void callOnStartPreview() { |
|
|
|
for (final CameraCallback callback: mCallbacks) { |
|
|
|
for (final CameraCallback callback : mCallbacks) { |
|
|
|
try { |
|
|
|
callback.onStartPreview(); |
|
|
|
} catch (final Exception e) { |
|
|
@ -1070,7 +1083,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
|
|
|
|
private void callOnStopPreview() { |
|
|
|
for (final CameraCallback callback: mCallbacks) { |
|
|
|
for (final CameraCallback callback : mCallbacks) { |
|
|
|
try { |
|
|
|
callback.onStopPreview(); |
|
|
|
} catch (final Exception e) { |
|
|
@ -1081,7 +1094,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
|
|
|
|
private void callOnStartRecording() { |
|
|
|
for (final CameraCallback callback: mCallbacks) { |
|
|
|
for (final CameraCallback callback : mCallbacks) { |
|
|
|
try { |
|
|
|
callback.onStartRecording(); |
|
|
|
} catch (final Exception e) { |
|
|
@ -1092,7 +1105,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
|
|
|
|
private void callOnStopRecording() { |
|
|
|
for (final CameraCallback callback: mCallbacks) { |
|
|
|
for (final CameraCallback callback : mCallbacks) { |
|
|
|
try { |
|
|
|
callback.onStopRecording(); |
|
|
|
} catch (final Exception e) { |
|
|
@ -1103,7 +1116,7 @@ public abstract class AbstractUVCCameraHandler extends Handler { |
|
|
|
} |
|
|
|
|
|
|
|
private void callOnError(final Exception e) { |
|
|
|
for (final CameraCallback callback: mCallbacks) { |
|
|
|
for (final CameraCallback callback : mCallbacks) { |
|
|
|
try { |
|
|
|
callback.onError(e); |
|
|
|
} catch (final Exception e1) { |
|
|
|