howto - madbeef/UVCCamera GitHub Wiki

范例简介

这个范例里现在有8个项目。

Note: 除非真的有必要并且你不会改出错来,否则最好不要修改UVCCamera.java的class名称和字段名,否则APP会在接上USB摄像头的时候罢工.

1. USBCameraTest0

这是最简单的范例了,只有MainActivity一个。用的是SurfaceView,只有简单的开关视频的功能,不能录像。

  • MainActivity :

2. USBCameraTest

这个项目跟USBCameraTest0几乎一样,但是用的是TextureView,代替了之前的SurfaceView,还是不能录像。

widget

  • AspectRatioViewInterface :
  • CheckableLinearLayout :
  • UVCCameraTextureView :

3. USBCameraTest2

从这个范例开始可以录像了。该范例使用MediaCodec Encoder录制视频为.MP4文件。因为用到了MediaMuxer,所以必须用18以上的开发包(Android 4.3以上)。

main

  • 多了录制部分,该范例没有截图,同时删除了一些USBMonitor.OnDeviceConnectListener的代码。

video

  • Encoder :
  • SurfaceEncoder :

4. USBCameraTest3

这个范例除了录像还可以录音了(用内置麦克风),并且还可以保存视频截图。推荐以这个范例为基础编写自己的APP。

widget里多了————

  • CameraViewInterface :
  • UVCCameraTextureView2 :

去掉了video,添加了encoder

  • MediaAudioEncoder :录音
  • MediaEncoder :
  • MediaMuxerWrapper :
  • MediaSurfaceEncoder :
  • MediaVideoEncoder :

多了glutils

  • EGLBase :
  • GLDrawer2D :
  • RenderHandler :

5. USBCameraTest4

这个范例没有添加新功能,但可以把录像变成后台service。这样就可以关上屏幕持续录像了。不过,这个范例使用了IPC机制并用了AIDL。

因为比较特殊,暂不介绍。


6. USBCameraTest5

范例5与范例3很相似,但在保存截图部分用的是IFrameCallback,而不是MediaCodec。 大多数情况下用IFrameCallback效率都是比较低的,但是IFrameCallback提取的视频帧可以作为byte buffer来做更多额外的处理。

把glutils目录删掉了。


7 ) USBCameraTest6
This shows how to split video images to multiple Surface. You can see video images side by side view on this app. This sample also show how to use EGL to render image. If you want to show video images after adding visual effect/filter effects, this sample may help you.

8 ) USBCameraTest7
This shows how to use two camera and show video images from each camera side-by side. This is still experimental and may have some issue.

If you want to build above sample project, just import the project to your IDE and run it. You don't need libUVCCamera library project to build sample unless you want to change/modify/add some features in JNI side.

Internal behavior

sorry this paragraph is not ready yet.

How to change resolution

(This is old. Latest version supports preview resolution setting by UVCCamera#setPreviewSize)

If you want just one higher resolution than 640×480, for example 1920×1080, all you have to do is,

1 ) Change DEFAULT_PREVIEW_WIDTH macro from 640 to 1920 in UVCPreview.h
2 ) Change DEFAULT_PREVIEW_HEIGHT macro from 480 to 1080 in UVCPreview.h
3 ) Rebuild shared libraries using Android NDK
4 ) Replace shared libraries placed {project home directory}/libs/armeabi-v7a in specific sample project.
5 ) Some projects need to set aspect ratio of camera images. It is like this,

    from

    mCameraView.set AspectRatio(640 / 480.f);

    to

    mCameraView.setAspectRatio(1920 / 1080.f);

6 ) Run app or export as apk.

How to use MJPEG mode

(This is old. Latest version supports preview mode setting by UVCCamera#setPreviewSize. All samples try to use MJPEG mode first. If it failed, try YUV mode automatically.)

If you want to use MJPEG mode, please change as follows,

1 ) in UVCPreview::UVCPreview function (this is just safety)

    from

    frameBytes(DEFAULT_PREVIEW_WIDTH * DEFAULT_PREVIEW_HEIGHT * 2)

    to

    frameBytes(DEFAULT_PREVIEW_WIDTH * DEFAULT_PREVIEW_HEIGHT * 4)

2 ) in UVCPreview::prepare_preview function

    from

    result = uvc_get_stream_ctrl_format_size_fps(mDeviceHandle, ctrl,
        UVC_FRAME_FORMAT_YUYV,  
        requestWidth, requestHeight, 1, 30 );

    to  

    result = uvc_get_stream_ctrl_format_size_fps(mDeviceHandle, ctrl,
        UVC_FRAME_FORMAT_MJPEG,
        requestWidth, 1, 30 );  

3 ) in UVCPreview::do_preview function,

    from  

    while (LIKELY(isRunning())) {
        frame = waitPreviewFrame();
        if (LIKELY(frame)) {
            frame = draw_preview_one(frame, &mPreviewWindow, uvc_any2rgbx, 4);
            addCaptureFrame(frame);
        }
    }

    to  

    while (LIKELY(isRunning())) {
        frame_mjpeg = waitPreviewFrame();
        if (LIKELY(frame_mjpeg)) {
            frame_yuyv = uvc_allocate_frame(frame_mjpeg->width * frame_mjpeg->height * 2);
            result = uvc_mjpeg2yuyv(frame_mjpeg, frame_yuyv);	// MJPEG => yuyv
            uvc_free_frame(frame_mjpeg);
            if (LIKELY(!result)) {
                frame_yuyv = draw_preview_one(frame_yuyv, &mPreviewWindow, uvc_any2rgbx, 4);
                addCaptureFrame(frame_yuyv);
            } else {
                uvc_free_frame(frame_yuyv);
            }
        }
    }

of course you need to add “frame_mjpeg” and “frame_yuyv” variables instead of “frame” variavle.

How to create Bitmap in IFrameCallback

I don't recommend this way because IFrameCallback is relatively slow but if you really need to create Bitmap in IFrameCallback, please refer following code.

    private final Bitmap bitmap = Bitmap.createBitmap(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, Bitmap.Config.RGB_565);
    private final IFrameCallback mIFrameCallback = new IFrameCallback() {
    	@Override
    	public void onFrame(final ByteBuffer frame) {
    		frame.clear();
    		synchronized (bitmap) {
    			bitmap.copyPixelsFromBuffer(frame);
    		}
    		mImageView.post(mUpdateImageTask);
    	}
    };
    
    private final Runnable mUpdateImageTask = new Runnable() {
    	@Override
    	public void run() {
    		synchronized (bitmap) {
    			mImageView.setImageBitmap(bitmap);
     		}
    	}
    };

How to start app when user connect UVC device to Android device

If you want to start app automatically, add followings on your AndroidManifest.xml

	    <activity
            android:name="{FQN of your main activiy}"
            android:label="{app name}"
			android:launchMode="singleTask" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
			<intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
		</activity>

You can edit device_filter.xml if you want to use only specific UVC camera.

And request permission when app detects UVC devices.

	private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
		@Override
		public void onAttach(UsbDevice device) {
			// this is called when user connect UVC camera and Android detected it.
			// if you want to use camera automatically, request permission here like as follows.
			final int n = mUSBMonitor.getDeviceCount()
			if ((device == null) && (n > 0)) {
				// #onAttach will be called with null argument when USBMonitor detect device connection without intent.
				final List<UsbDevice> devices = mUSBMonitor.getDeviceList();
				// set first one
				device = devices.get(0);
			}
			if (n == 1) {
				// if there is only one camera, request permission.
				// first time you call #requestPermission or app has no permission, Android shows permission dialog.
				// if app already has permission or user give permission on permission dialog, USBMonitor call #onConnect callback method.
				final boolean result = mUSBMonitor.requestPermission(device);
				if (result) {
					// when failed. your device may not support USB.
				}
			} else if (n > 1) {
				// show dialog to select camera
//				CameraDialog.showDialog(this);
				// or if you know your device-id/product-id that you want to use and device is that one, request permission
			}
		}

		@Override
		public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
			// this is called user give permission. now you cane open camera and start previewing
//			mHandler.openCamera(ctrlBlock);
//			startPreview();
		}

		@Override
		public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
			// this is called when user close camera (and also called when user remove UVC camera while using)
//			mHandler.closeCamera();
		}

		@Override
		public void onDettach(final UsbDevice device) {
			// this is called when UVC camera removed from the device. (will be after #onDisconnect)
		}

		@Override
		public void onCancel(final UsbDevice device) {
			// this is be called when user did not give permission to app
		}
	};
⚠️ **GitHub.com Fallback** ⚠️