Browse Source

重构视频录制、拍摄图片模块

main
jiangdongguo 7 years ago
parent
commit
0993e849f0
  1. 68
      app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java
  2. 14
      app/src/main/res/layout/activity_usbcamera.xml
  3. 41
      libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java
  4. 6
      libusbcamera/src/main/java/com/jiangdg/usbcamera/utils/FileUtils.java
  5. 6
      libusbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java
  6. 84
      libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
  7. 4
      libusbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java
  8. 4
      libusbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java

68
app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java

@ -9,6 +9,7 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@ -16,9 +17,11 @@ import android.view.Surface;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SimpleAdapter;
import android.widget.Switch;
import android.widget.Toast;
import com.jiangdg.usbcamera.R;
@ -44,6 +47,7 @@ import butterknife.ButterKnife;
*/
public class USBCameraActivity extends AppCompatActivity implements CameraDialog.CameraDialogParent, CameraViewInterface.Callback {
private static final String TAG = "Debug";
@BindView(R.id.camera_view)
public View mTextureView;
@BindView(R.id.toolbar)
@ -52,6 +56,8 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
public SeekBar mSeekBrightness;
@BindView(R.id.seekbar_contrast)
public SeekBar mSeekContrast;
@BindView(R.id.switch_rec_voice)
public Switch mSwitchVoice;
private UVCCameraHelper mCameraHelper;
private CameraViewInterface mUVCCameraView;
@ -126,19 +132,24 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
setContentView(R.layout.activity_usbcamera);
ButterKnife.bind(this);
initView();
// step.1 initialize UVCCameraHelper
mUVCCameraView = (CameraViewInterface) mTextureView;
mUVCCameraView.setCallback(this);
mCameraHelper = UVCCameraHelper.getInstance();
mCameraHelper.initUSBMonitor(this, mUVCCameraView, listener);
mCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(byte[] nv21Yuv) {
}
});
}
private void initView() {
setSupportActionBar(mToolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
mSeekBrightness.setMax(100);
mSeekBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
@ -225,43 +236,53 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
showShortMsg("sorry,camera open failed");
return super.onOptionsItemSelected(item);
}
if (!mCameraHelper.isRecording()) {
String videoPath = UVCCameraHelper.ROOT_PATH + System.currentTimeMillis();
FileUtils.createfile(FileUtils.ROOT_PATH + "test666.h264");
// FileUtils.createfile(FileUtils.ROOT_PATH + "test666.h264");
RecordParams params = new RecordParams();
params.setRecordPath(videoPath);
params.setRecordDuration(0); // 设置为0,不分割保存
params.setVoiceClose(false); // 不屏蔽声音
params.setRecordDuration(0); // 设置为0,不分割保存
params.setVoiceClose(mSwitchVoice.isChecked()); // is close voice
mCameraHelper.startRecording(params, new AbstractUVCCameraHandler.OnEncodeResultListener() {
@Override
public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) {
// type = 0,aac stream
// type = 1,h264 stream
// type = 1,h264 video stream
if (type == 1) {
FileUtils.putFileStream(data, offset, length);
// FileUtils.putFileStream(data, offset, length);
}
// type = 0,aac audio stream
if(type == 0) {
}
}
@Override
public void onRecordResult(String videoPath) {
showShortMsg(videoPath);
Log.i(TAG,"videoPath = "+videoPath);
}
});
showShortMsg("start record...");
mSwitchVoice.setEnabled(false);
} else {
FileUtils.releaseFile();
// FileUtils.releaseFile();
mCameraHelper.stopRecording();
showShortMsg("stop record...");
mSwitchVoice.setEnabled(true);
}
break;
case R.id.menu_resolution:
if (mCameraHelper == null || !mCameraHelper.isCameraOpened()) {
showShortMsg("sorry,camera open failed");
return super.onOptionsItemSelected(item);
}
showResolutionListDialog();
break;
case R.id.menu_focus:
if (mCameraHelper != null) {
mCameraHelper.startCameraFoucs();
if (mCameraHelper == null || !mCameraHelper.isCameraOpened()) {
showShortMsg("sorry,camera open failed");
return super.onOptionsItemSelected(item);
}
mCameraHelper.startCameraFoucs();
break;
}
return super.onOptionsItemSelected(item);
@ -285,14 +306,7 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
if (tmp != null && tmp.length >= 2) {
int widht = Integer.valueOf(tmp[0]);
int height = Integer.valueOf(tmp[1]);
mCameraHelper.updateResolution(widht, height, new UVCCameraHelper.OnPreviewListener() {
@Override
public void onPreviewResult(boolean isSuccess) {
if (isSuccess) {
showShortMsg("update resolution to " + resolution + " success");
}
}
});
mCameraHelper.updateResolution(widht, height);
}
mDialog.dismiss();
}
@ -410,6 +424,7 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
@Override
protected void onDestroy() {
super.onDestroy();
FileUtils.releaseFile();
// step.4 release uvc camera resources
if (mCameraHelper != null) {
mCameraHelper.release();
@ -439,12 +454,7 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
@Override
public void onSurfaceCreated(CameraViewInterface view, Surface surface) {
if (!isPreview && mCameraHelper.isCameraOpened()) {
mCameraHelper.startPreview(mUVCCameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean result) {
}
});
mCameraHelper.startPreview(mUVCCameraView);
isPreview = true;
}
}

14
app/src/main/res/layout/activity_usbcamera.xml

@ -77,4 +77,18 @@
android:layout_height="match_parent" />
</LinearLayout>
<Switch
android:id="@+id/switch_rec_voice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/llayout_brightness"
android:layout_alignStart="@+id/llayout_brightness"
android:layout_below="@+id/toolbar"
android:layout_marginLeft="13dp"
android:layout_marginStart="13dp"
android:layout_marginTop="27dp"
android:checked="true"
android:textColor="@color/colorWhite"
android:text="closeVoice" />
</RelativeLayout>

41
libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java

@ -73,10 +73,6 @@ public class UVCCameraHelper {
void onDisConnectDev(UsbDevice device);
}
public interface OnPreviewListener {
void onPreviewResult(boolean isSuccess);
}
public void initUSBMonitor(Activity activity, CameraViewInterface cameraView, final OnMyDevConnectListener listener) {
this.mActivityWrf = new WeakReference<>(activity);
this.mCamViewWrf = new WeakReference<>(cameraView);
@ -106,14 +102,10 @@ public class UVCCameraHelper {
public void onConnect(final UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
mCtrlBlock = ctrlBlock;
openCamera(ctrlBlock);
startPreview(mCamViewWrf.get(), new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean isConnected) {
if (listener != null) {
listener.onConnectDev(device, isConnected);
}
}
});
startPreview(mCamViewWrf.get());
if(listener != null) {
listener.onConnectDev(device,true);
}
}
// called by disconnect to usb camera
@ -148,7 +140,7 @@ public class UVCCameraHelper {
previewWidth, previewHeight, PREVIEW_FORMAT);
}
public void updateResolution(int width, int height, final OnPreviewListener mPreviewListener) {
public void updateResolution(int width, int height) {
if (previewWidth == width && previewHeight == height) {
return;
}
@ -162,14 +154,7 @@ public class UVCCameraHelper {
mCameraHandler = UVCCameraHandler.createHandler(mActivityWrf.get(), mCamViewWrf.get(), 2,
previewWidth, previewHeight, PREVIEW_FORMAT);
openCamera(mCtrlBlock);
startPreview(mCamViewWrf.get(), new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean result) {
if (mPreviewListener != null) {
mPreviewListener.onPreviewResult(result);
}
}
});
startPreview(mCamViewWrf.get());
}
public void registerUSB() {
@ -229,9 +214,9 @@ public class UVCCameraHelper {
return mUSBMonitor.getDeviceList(deviceFilters.get(0));
}
public void capturePicture(String savePath, AbstractUVCCameraHandler.OnCaptureListener listener) {
public void capturePicture(String savePath) {
if (mCameraHandler != null && mCameraHandler.isOpened()) {
mCameraHandler.captureStill(savePath, listener);
mCameraHandler.captureStill(savePath);
}
}
@ -278,16 +263,22 @@ public class UVCCameraHelper {
return mUSBMonitor;
}
public void setOnPreviewFrameListener(AbstractUVCCameraHandler.OnPreViewResultListener listener) {
if(mCameraHandler != null) {
mCameraHandler.setOnPreViewResultListener(listener);
}
}
private void openCamera(USBMonitor.UsbControlBlock ctrlBlock) {
if (mCameraHandler != null) {
mCameraHandler.open(ctrlBlock);
}
}
public void startPreview(CameraViewInterface cameraView, AbstractUVCCameraHandler.OnPreViewResultListener mPreviewListener) {
public void startPreview(CameraViewInterface cameraView) {
SurfaceTexture st = cameraView.getSurfaceTexture();
if (mCameraHandler != null) {
mCameraHandler.startPreview(st, mPreviewListener);
mCameraHandler.startPreview(st);
}
}

6
libusbcamera/src/main/java/com/jiangdg/usbcamera/utils/FileUtils.java

@ -31,8 +31,10 @@ public class FileUtils {
public static void releaseFile(){
try {
outputStream.flush();
outputStream.close();
if(outputStream != null) {
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}

6
libusbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java

@ -24,6 +24,7 @@
package com.serenegiant.usb;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -33,6 +34,7 @@ import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
@ -882,6 +884,7 @@ public final class USBMonitor {
* @param _info
* @return
*/
@TargetApi(Build.VERSION_CODES.M)
public static UsbDeviceInfo updateDeviceInfo(final UsbManager manager, final UsbDevice device, final UsbDeviceInfo _info) {
final UsbDeviceInfo info = _info != null ? _info : new UsbDeviceInfo();
info.clear();
@ -897,6 +900,9 @@ public final class USBMonitor {
}
if ((manager != null) && manager.hasPermission(device)) {
final UsbDeviceConnection connection = manager.openDevice(device);
if(connection == null) {
return null;
}
final byte[] desc = connection.getRawDescriptors();
if (TextUtils.isEmpty(info.usb_version)) {

84
libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java

@ -16,6 +16,8 @@ import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.jiangdg.usbcamera.task.SaveYuvImageTask;
import com.jiangdg.usbcamera.utils.YUVBean;
import com.serenegiant.usb.IFrameCallback;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.USBMonitor;
@ -74,7 +76,7 @@ public abstract class AbstractUVCCameraHandler extends Handler {
}
public interface OnPreViewResultListener{
void onPreviewResult(boolean result);
void onPreviewResult(byte[] data);
}
public interface OnCaptureListener {
@ -97,6 +99,7 @@ public abstract class AbstractUVCCameraHandler extends Handler {
private final WeakReference<CameraThread> mWeakThread;
private volatile boolean mReleased;
protected boolean isCaptureStill;
protected AbstractUVCCameraHandler(final CameraThread thread) {
mWeakThread = new WeakReference<CameraThread>(thread);
@ -174,21 +177,26 @@ public abstract class AbstractUVCCameraHandler extends Handler {
}
// 开启Camera预览
protected void startPreview(final Object surface,OnPreViewResultListener listener) {
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);
}
this.mPreviewListener = listener;
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);
stopRecording();
if(isRecording()) {
stopRecording();
}
if (isPreviewing()) {
final CameraThread thread = mWeakThread.get();
if (thread == null) return;
@ -208,16 +216,11 @@ public abstract class AbstractUVCCameraHandler extends Handler {
if (DEBUG) Log.v(TAG, "stopPreview:finished");
}
// 捕获图像
protected void captureStill() {
checkReleased();
sendEmptyMessage(MSG_CAPTURE_STILL);
}
public void captureStill(final String path,AbstractUVCCameraHandler.OnCaptureListener listener) {
AbstractUVCCameraHandler.mCaptureListener = listener;
checkReleased();
sendMessage(obtainMessage(MSG_CAPTURE_STILL, path));
// old method, to get screen size picture
// AbstractUVCCameraHandler.mCaptureListener = listener;
// checkReleased();
// sendMessage(obtainMessage(MSG_CAPTURE_STILL, path));
}
// 开始录制
@ -350,7 +353,8 @@ public abstract class AbstractUVCCameraHandler extends Handler {
thread.handleStopPreview();
break;
case MSG_CAPTURE_STILL:
thread.handleCaptureStill((String)msg.obj);
// thread.handleCaptureStill((String)msg.obj);
thread.handleStillPicture((String)msg.obj);
break;
case MSG_CAPTURE_START:
// thread.handleStartRecording((String)msg.obj);
@ -369,13 +373,6 @@ public abstract class AbstractUVCCameraHandler extends Handler {
case MSG_CAMERA_FOUCS:
thread.handleCameraFoucs();
break;
// 音频线程
// case MSG_AUDIO_START:
// thread.startAudioRecord();
// break;
// case MSG_AUDIO_STOP:
// thread.stopAudioRecord();
// break;
default:
throw new RuntimeException("unsupported message:what=" + msg.what);
}
@ -529,17 +526,10 @@ public abstract class AbstractUVCCameraHandler extends Handler {
if ((mUVCCamera == null) || mIsPreviewing) return;
try {
mUVCCamera.setPreviewSize(mWidth, mHeight, 1, 31, mPreviewMode, mBandwidthFactor);
if(mPreviewListener != null){
mPreviewListener.onPreviewResult(true);
}
// 获取USB Camera预览数据
mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21);
} catch (final IllegalArgumentException e) {
// 添加分辨率参数合法性检测
if(mPreviewListener != null){
mPreviewListener.onPreviewResult(false);
}
// try {
// // fallback to YUV mode
// mUVCCamera.setPreviewSize(mWidth, mHeight, 1, 31, UVCCamera.DEFAULT_PREVIEW_MODE, mBandwidthFactor);
@ -568,6 +558,7 @@ public abstract class AbstractUVCCameraHandler extends Handler {
if (mIsPreviewing) {
if (mUVCCamera != null) {
mUVCCamera.stopPreview();
mUVCCamera.setFrameCallback(null, 0);
}
synchronized (mSync) {
mIsPreviewing = false;
@ -688,11 +679,10 @@ public abstract class AbstractUVCCameraHandler extends Handler {
// 停止音视频编码线程
stopAudioRecord();
stopVideoRecord();
// 停止捕获视频数据
if (mUVCCamera != null) {
mUVCCamera.stopCapture();
mUVCCamera.setFrameCallback(null, 0);
}
// // 停止捕获视频数据
// if (mUVCCamera != null) {
// mUVCCamera.stopCapture();
// }
mWeakCameraView.get().setVideoEncoder(null);
// you should not wait here
callOnStopRecording();
@ -751,7 +741,6 @@ public abstract class AbstractUVCCameraHandler extends Handler {
if(mAacConsumer != null){
mAacConsumer.setTmpuMuxer(mMuxer);
}
// isAudioThreadStart = true;
}
private void stopAudioRecord(){
@ -773,7 +762,11 @@ public abstract class AbstractUVCCameraHandler extends Handler {
// isAudioThreadStart = false;
}
private boolean isCaptureStill;
private String picPath;
public void handleStillPicture(String picPath) {
this.picPath = picPath;
}
private final IFrameCallback mIFrameCallback = new IFrameCallback() {
@Override
@ -789,9 +782,26 @@ public abstract class AbstractUVCCameraHandler extends Handler {
int len = frame.capacity();
byte[] yuv = new byte[len];
frame.get(yuv);
// nv21 yuv data callback
if(mPreviewListener != null) {
mPreviewListener.onPreviewResult(yuv);
}
// 捕获图片
if(isCaptureStill) {
if(! TextUtils.isEmpty(picPath)) {
YUVBean bean = new YUVBean();
bean.setYuvData(yuv);
bean.setPicPath(picPath);
bean.setWidth(mWidth);
bean.setHeight(mHeight);
new SaveYuvImageTask(bean, new SaveYuvImageTask.OnSaveYuvResultListener() {
@Override
public void onSaveResult(String savePath) {
if(mCaptureListener != null) {
mCaptureListener.onCaptureResult(savePath);
}
picPath = null;
}
}).execute();
}
// 视频
if(mH264Consumer != null){

4
libusbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java

@ -119,8 +119,8 @@ public class UVCCameraHandler extends AbstractUVCCameraHandler {
}
@Override
public void startPreview(final Object surface,final AbstractUVCCameraHandler.OnPreViewResultListener listener) {
super.startPreview(surface, listener);
public void startPreview(final Object surface) {
super.startPreview(surface);
}
@Override

4
libusbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java

@ -136,10 +136,10 @@ public class UVCCameraHandlerMultiSurface extends AbstractUVCCameraHandler {
}
}
public synchronized void startPreview(OnPreViewResultListener listener) {
public synchronized void startPreview() {
checkReleased();
if (mRendererHolder != null) {
super.startPreview(mRendererHolder.getSurface(),listener);
super.startPreview(mRendererHolder.getSurface());
} else {
throw new IllegalStateException();
}

Loading…
Cancel
Save