Browse Source

支持切换分辨率

main v1.2.0
jiangdongguo 7 years ago
parent
commit
0f6f4f5da9
  1. 35
      app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java
  2. 10
      app/src/main/res/layout/activity_usbcamera.xml
  3. 65
      libusbcamera/src/main/java/com/jiangdg/usbcamera/USBCameraManager.java
  4. 31
      libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
  5. 4
      libusbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java
  6. 4
      libusbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java
  7. 20
      libusbcamera/src/main/java/com/serenegiant/usb/encoder/biz/H264EncodeConsumer.java

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

@ -44,13 +44,13 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
public Button mBtnCapture;
@BindView(R.id.btn_rec_video)
public Button mBtnRecord;
@BindView(R.id.btn_update_resolution)
public Button mBtnUpdateResultion;
private USBCameraManager mUSBManager;
private CameraViewInterface mUVCCameraView;
private boolean isRequest;
private static String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/test1.h264";
private BufferedOutputStream outputStream;
/**
* USB设备事件监听器
@ -85,8 +85,10 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
// 连接USB设备成功
@Override
public void onConnectDev(UsbDevice device) {
public void onConnectDev(UsbDevice device,boolean isConnected) {
if(! isConnected) {
showShortMsg("连接失败,请检查分辨率参数是否正确");
}
}
// 与USB设备断开连接
@ -115,10 +117,6 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
if(mUSBManager != null){
mUSBManager.registerUSB();
}
// 恢复Camera预览
if(mUVCCameraView != null){
mUVCCameraView.onResume();
}
}
@Override
@ -128,16 +126,27 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
if(mUSBManager != null){
mUSBManager.unregisterUSB();
}
// 暂停Camera预览
if(mUVCCameraView != null){
mUVCCameraView.onPause();
}
}
@OnClick({R.id.camera_view, R.id.btn_capture_pic, R.id.btn_rec_video})
@OnClick({R.id.camera_view, R.id.btn_capture_pic, R.id.btn_rec_video,R.id.btn_update_resolution})
public void onViewClick(View view) {
int vId = view.getId();
switch (vId) {
// 切换分辨率
case R.id.btn_update_resolution:
if(mUSBManager == null)
return;
mUSBManager.updateResolution(this, mUVCCameraView, 320, 240, new USBCameraManager.OnPreviewListener() {
@Override
public void onPreviewResult(boolean isSuccess) {
if(! isSuccess) {
showShortMsg("预览失败,不支持该分辨率");
}else {
showShortMsg("以切换到分辨率为320x240");
}
}
});
break;
// 开启或关闭Camera
case R.id.camera_view:
// if(mUSBManager != null){

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

@ -35,4 +35,14 @@
android:textSize="16sp"
android:text="开始录制"/>
<Button
android:layout_above="@id/btn_rec_video"
android:id="@+id/btn_update_resolution"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:textSize="16sp"
android:text="切换分辨率为320x240"/>
</RelativeLayout>

65
libusbcamera/src/main/java/com/jiangdg/usbcamera/USBCameraManager.java

@ -17,8 +17,6 @@ import com.serenegiant.usb.widget.CameraViewInterface;
import java.io.File;
import java.util.List;
import static android.R.attr.filter;
/**USB摄像头工具类
*
* Created by jiangdongguo on 2017/9/30.
@ -30,8 +28,8 @@ public class USBCameraManager{
public static final String SUFFIX_PNG = ".png";
public static final String SUFFIX_MP4 = ".mp4";
private static final String TAG = "USBCameraManager";
private static final int PREVIEW_WIDTH = 640;
private static final int PREVIEW_HEIGHT = 480;
private int previewWidth = 640;
private int previewHeight = 480;
// 使用MediaVideoBufferEncoder
private static final int ENCODER_TYPE = 2;
//0为YUYV,1为MJPEG
@ -44,6 +42,7 @@ public class USBCameraManager{
private UVCCameraHandler mCameraHandler;
private Context mContext;
private USBMonitor.UsbControlBlock mCtrlBlock;
private USBCameraManager(){}
@ -57,10 +56,14 @@ public class USBCameraManager{
public interface OnMyDevConnectListener{
void onAttachDev(UsbDevice device);
void onDettachDev(UsbDevice device);
void onConnectDev(UsbDevice device);
void onConnectDev(UsbDevice device,boolean isConnected);
void onDisConnectDev(UsbDevice device);
}
public interface OnPreviewListener{
void onPreviewResult(boolean isSuccess);
}
/** 初始化
*
* context 上下文
@ -73,6 +76,7 @@ public class USBCameraManager{
mContext = activity.getApplicationContext();
mUSBMonitor = new USBMonitor(activity.getApplicationContext(), new USBMonitor.OnDeviceConnectListener() {
// 当检测到USB设备,被回调
@Override
public void onAttach(UsbDevice device) {
@ -91,14 +95,19 @@ public class USBCameraManager{
// 当连接到USB Camera时,被回调
@Override
public void onConnect(UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
if(listener != null){
listener.onConnectDev(device);
}
public void onConnect(final UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
mCtrlBlock = ctrlBlock;
// 打开摄像头
openCamera(ctrlBlock);
// 开启预览
startPreview(cameraView);
startPreview(cameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean isConnected) {
if(listener != null){
listener.onConnectDev(device,isConnected);
}
}
});
}
// 当与USB Camera断开连接时,被回调
@ -115,11 +124,37 @@ public class USBCameraManager{
public void onCancel(UsbDevice device) {
}
});
cameraView.setAspectRatio(previewWidth / (float)previewHeight);
mCameraHandler = UVCCameraHandler.createHandler(activity,cameraView,ENCODER_TYPE,
previewWidth,previewHeight,PREVIEW_FORMAT);
}
// 设置长宽比
cameraView.setAspectRatio(PREVIEW_WIDTH / (float)PREVIEW_HEIGHT);
// 切换分辨率
public void updateResolution(Activity activity, CameraViewInterface cameraView, int width, int height, final OnPreviewListener mPreviewListener){
this.previewWidth = width;
this.previewHeight = height;
// 关闭摄像头
closeCamera();
// 释放CameraHandler占用的相关资源
if(mCameraHandler != null){
mCameraHandler.release();
mCameraHandler = null;
}
// 重新初始化mCameraHandler
cameraView.setAspectRatio(previewWidth / (float)previewHeight);
mCameraHandler = UVCCameraHandler.createHandler(activity,cameraView,ENCODER_TYPE,
PREVIEW_WIDTH,PREVIEW_HEIGHT,PREVIEW_FORMAT);
previewWidth,previewHeight,PREVIEW_FORMAT);
openCamera(mCtrlBlock);
// 开始预览
startPreview(cameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean result) {
if(mPreviewListener != null){
mPreviewListener.onPreviewResult(result);
}
}
});
}
/**
@ -247,10 +282,10 @@ public class USBCameraManager{
}
}
public void startPreview(CameraViewInterface cameraView) {
public void startPreview(CameraViewInterface cameraView,AbstractUVCCameraHandler.OnPreViewResultListener mPreviewListener) {
SurfaceTexture st = cameraView.getSurfaceTexture();
if(mCameraHandler != null){
mCameraHandler.startPreview(st);
mCameraHandler.startPreview(st,mPreviewListener);
}
}
}

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

@ -66,11 +66,16 @@ public abstract class AbstractUVCCameraHandler extends Handler {
}
public static OnEncodeResultListener mListener;
public static OnPreViewResultListener mPreviewListener;
public interface OnEncodeResultListener{
void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type);
}
public interface OnPreViewResultListener{
void onPreviewResult(boolean result);
}
private static final int MSG_OPEN = 0;
private static final int MSG_CLOSE = 1;
private static final int MSG_PREVIEW_START = 2;
@ -163,11 +168,13 @@ public abstract class AbstractUVCCameraHandler extends Handler {
}
// 开启Camera预览
protected void startPreview(final Object surface) {
protected void startPreview(final Object surface,OnPreViewResultListener listener) {
checkReleased();
if (!((surface instanceof SurfaceHolder) || (surface instanceof Surface) || (surface instanceof SurfaceTexture))) {
throw new IllegalArgumentException("surface should be one of SurfaceHolder, Surface or SurfaceTexture");
}
this.mPreviewListener = listener;
sendMessage(obtainMessage(MSG_PREVIEW_START, surface));
}
@ -210,7 +217,6 @@ public abstract class AbstractUVCCameraHandler extends Handler {
public void startRecording(final RecordParams params, OnEncodeResultListener listener) {
AbstractUVCCameraHandler.mListener = listener;
checkReleased();
// sendEmptyMessage(MSG_CAPTURE_START);
sendMessage(obtainMessage(MSG_CAPTURE_START, params));
}
@ -503,14 +509,21 @@ 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);
}
} 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(mPreviewListener != null){
mPreviewListener.onPreviewResult(false);
}
// 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);
@ -659,7 +672,7 @@ public abstract class AbstractUVCCameraHandler extends Handler {
}
private void startVideoRecord() {
mH264Consumer = new H264EncodeConsumer();
mH264Consumer = new H264EncodeConsumer(getWidth(),getHeight());
mH264Consumer.setOnH264EncodeResultListener(new H264EncodeConsumer.OnH264EncodeResultListener() {
@Override
public void onEncodeResult(byte[] data, int offset, int length, long timestamp) {

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) {
super.startPreview(surface);
public void startPreview(final Object surface,final AbstractUVCCameraHandler.OnPreViewResultListener listener) {
super.startPreview(surface, listener);
}
@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() {
public synchronized void startPreview(OnPreViewResultListener listener) {
checkReleased();
if (mRendererHolder != null) {
super.startPreview(mRendererHolder.getSurface());
super.startPreview(mRendererHolder.getSurface(),listener);
} else {
throw new IllegalStateException();
}

20
libusbcamera/src/main/java/com/serenegiant/usb/encoder/biz/H264EncodeConsumer.java

@ -60,6 +60,15 @@ public class H264EncodeConsumer extends Thread {
this.listener = listener;
}
public H264EncodeConsumer(){
}
public H264EncodeConsumer(int width,int height){
this.mWidth = width;
this.mHeight = height;
}
public synchronized void setTmpuMuxer(Mp4MediaMuxer mMuxer){
this.mMuxerRef = new WeakReference<>(mMuxer);
Mp4MediaMuxer muxer = mMuxerRef.get();
@ -77,8 +86,11 @@ public class H264EncodeConsumer extends Thread {
// 根据编码器支持转换颜色空间格式
// 即 nv21 ---> YUV420sp(21)
// nv21 ---> YUV420p (19)
mWidth = width;
mHeight = height;
if(mWidth != width || mHeight != height){
mWidth = width;
mHeight = height;
return;
}
try {
if (lastPush == 0) {
lastPush = System.currentTimeMillis();
@ -240,7 +252,7 @@ public class H264EncodeConsumer extends Thread {
return;
}
final MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, 640, 480);
final MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mColorFormat);
format.setInteger(MediaFormat.KEY_BIT_RATE, calcBitRate());
format.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
@ -283,7 +295,7 @@ public class H264EncodeConsumer extends Thread {
private static final int FRAME_RATE = 15;
private static final float BPP = 0.50f;
private int calcBitRate() {
final int bitrate = (int)(BPP * FRAME_RATE * 640 * 480);
final int bitrate = (int)(BPP * FRAME_RATE * mWidth * mHeight);
Log.i(TAG, String.format("bitrate=%5.2f[Mbps]", bitrate / 1024f / 1024f));
return bitrate;
}

Loading…
Cancel
Save