diff --git a/app/src/main/java/org/phenoapps/activities/MainActivity.kt b/app/src/main/java/org/phenoapps/activities/MainActivity.kt index fa3449b5..25c54d91 100644 --- a/app/src/main/java/org/phenoapps/activities/MainActivity.kt +++ b/app/src/main/java/org/phenoapps/activities/MainActivity.kt @@ -3,31 +3,17 @@ package org.phenoapps.activities import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import org.phenoapps.androidlibrarybuilder.R -import org.phenoapps.usb.camera.UsbCameraHelper -import org.phenoapps.interfaces.usb.camera.UsbCameraInterface -class MainActivity: AppCompatActivity(), UsbCameraInterface { +class MainActivity: AppCompatActivity() { companion object { private var TAG = this::class.simpleName } - private var helper: UsbCameraHelper? = null - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - - helper = UsbCameraHelper(this) - } - override fun onDestroy() { - super.onDestroy() - helper?.destroy() - } - - override fun getCameraHelper(): UsbCameraHelper? = helper - -} \ No newline at end of file +} diff --git a/phenolib/build.gradle b/phenolib/build.gradle index dfa923d1..35b44fcf 100644 --- a/phenolib/build.gradle +++ b/phenolib/build.gradle @@ -62,8 +62,6 @@ dependencies { api 'com.google.android.exoplayer:exoplayer:2.17.0' api 'com.squareup.okhttp3:okhttp:4.11.0' - //uvc camera java native libs - api "com.serenegiant:common:2.12.4" implementation 'androidx.appcompat:appcompat:1.7.0-alpha02' implementation "com.google.android.material:material:1.9.0" diff --git a/phenolib/libs/arm64-v8a/libUVCCamera.so b/phenolib/libs/arm64-v8a/libUVCCamera.so deleted file mode 100644 index 01027f83..00000000 Binary files a/phenolib/libs/arm64-v8a/libUVCCamera.so and /dev/null differ diff --git a/phenolib/libs/arm64-v8a/libjpeg-turbo212.so b/phenolib/libs/arm64-v8a/libjpeg-turbo212.so deleted file mode 100644 index 465b0f31..00000000 Binary files a/phenolib/libs/arm64-v8a/libjpeg-turbo212.so and /dev/null differ diff --git a/phenolib/libs/arm64-v8a/libusb1.0.so b/phenolib/libs/arm64-v8a/libusb1.0.so deleted file mode 100644 index 772028b9..00000000 Binary files a/phenolib/libs/arm64-v8a/libusb1.0.so and /dev/null differ diff --git a/phenolib/libs/arm64-v8a/libuvc.so b/phenolib/libs/arm64-v8a/libuvc.so deleted file mode 100644 index 76bef01b..00000000 Binary files a/phenolib/libs/arm64-v8a/libuvc.so and /dev/null differ diff --git a/phenolib/libs/arm64-v8a/libyuv.so b/phenolib/libs/arm64-v8a/libyuv.so deleted file mode 100644 index af6b8d0e..00000000 Binary files a/phenolib/libs/arm64-v8a/libyuv.so and /dev/null differ diff --git a/phenolib/libs/armeabi-v7a/libUVCCamera.so b/phenolib/libs/armeabi-v7a/libUVCCamera.so deleted file mode 100644 index b5ced1ac..00000000 Binary files a/phenolib/libs/armeabi-v7a/libUVCCamera.so and /dev/null differ diff --git a/phenolib/libs/armeabi-v7a/libjpeg-turbo212.so b/phenolib/libs/armeabi-v7a/libjpeg-turbo212.so deleted file mode 100644 index d21b107b..00000000 Binary files a/phenolib/libs/armeabi-v7a/libjpeg-turbo212.so and /dev/null differ diff --git a/phenolib/libs/armeabi-v7a/libusb1.0.so b/phenolib/libs/armeabi-v7a/libusb1.0.so deleted file mode 100644 index c12728c1..00000000 Binary files a/phenolib/libs/armeabi-v7a/libusb1.0.so and /dev/null differ diff --git a/phenolib/libs/armeabi-v7a/libuvc.so b/phenolib/libs/armeabi-v7a/libuvc.so deleted file mode 100644 index 8ebe2b16..00000000 Binary files a/phenolib/libs/armeabi-v7a/libuvc.so and /dev/null differ diff --git a/phenolib/libs/armeabi-v7a/libyuv.so b/phenolib/libs/armeabi-v7a/libyuv.so deleted file mode 100644 index 06bf1843..00000000 Binary files a/phenolib/libs/armeabi-v7a/libyuv.so and /dev/null differ diff --git a/phenolib/libs/x86/libUVCCamera.so b/phenolib/libs/x86/libUVCCamera.so deleted file mode 100644 index 351a351b..00000000 Binary files a/phenolib/libs/x86/libUVCCamera.so and /dev/null differ diff --git a/phenolib/libs/x86/libjpeg-turbo212.so b/phenolib/libs/x86/libjpeg-turbo212.so deleted file mode 100644 index 01f5fb2f..00000000 Binary files a/phenolib/libs/x86/libjpeg-turbo212.so and /dev/null differ diff --git a/phenolib/libs/x86/libusb1.0.so b/phenolib/libs/x86/libusb1.0.so deleted file mode 100644 index 6dbc68af..00000000 Binary files a/phenolib/libs/x86/libusb1.0.so and /dev/null differ diff --git a/phenolib/libs/x86/libuvc.so b/phenolib/libs/x86/libuvc.so deleted file mode 100644 index bea34afd..00000000 Binary files a/phenolib/libs/x86/libuvc.so and /dev/null differ diff --git a/phenolib/libs/x86/libyuv.so b/phenolib/libs/x86/libyuv.so deleted file mode 100644 index 4b4618ef..00000000 Binary files a/phenolib/libs/x86/libyuv.so and /dev/null differ diff --git a/phenolib/libs/x86_64/libUVCCamera.so b/phenolib/libs/x86_64/libUVCCamera.so deleted file mode 100644 index 0dbca6db..00000000 Binary files a/phenolib/libs/x86_64/libUVCCamera.so and /dev/null differ diff --git a/phenolib/libs/x86_64/libjpeg-turbo212.so b/phenolib/libs/x86_64/libjpeg-turbo212.so deleted file mode 100644 index 1e50867d..00000000 Binary files a/phenolib/libs/x86_64/libjpeg-turbo212.so and /dev/null differ diff --git a/phenolib/libs/x86_64/libusb1.0.so b/phenolib/libs/x86_64/libusb1.0.so deleted file mode 100644 index aa9841e0..00000000 Binary files a/phenolib/libs/x86_64/libusb1.0.so and /dev/null differ diff --git a/phenolib/libs/x86_64/libuvc.so b/phenolib/libs/x86_64/libuvc.so deleted file mode 100644 index bca18d0c..00000000 Binary files a/phenolib/libs/x86_64/libuvc.so and /dev/null differ diff --git a/phenolib/libs/x86_64/libyuv.so b/phenolib/libs/x86_64/libyuv.so deleted file mode 100644 index 1693e01e..00000000 Binary files a/phenolib/libs/x86_64/libyuv.so and /dev/null differ diff --git a/phenolib/proguard-rules.pro b/phenolib/proguard-rules.pro index b64a7bf4..cf504086 100644 --- a/phenolib/proguard-rules.pro +++ b/phenolib/proguard-rules.pro @@ -19,5 +19,4 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile --keep class com.serenegiant.** { *; } diff --git a/phenolib/src/main/AndroidManifest.xml b/phenolib/src/main/AndroidManifest.xml index fecb0094..ad63d9e9 100644 --- a/phenolib/src/main/AndroidManifest.xml +++ b/phenolib/src/main/AndroidManifest.xml @@ -1,10 +1,6 @@ - - - - diff --git a/phenolib/src/main/java/com/serenegiant/AspectRatioViewInterface.java b/phenolib/src/main/java/com/serenegiant/AspectRatioViewInterface.java deleted file mode 100644 index f6c7d237..00000000 --- a/phenolib/src/main/java/com/serenegiant/AspectRatioViewInterface.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@com.com.serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant; - -public interface AspectRatioViewInterface { - public void setAspectRatio(double aspectRatio); - public void onPause(); - public void onResume(); -} diff --git a/phenolib/src/main/java/com/serenegiant/SimpleUVCCameraTextureView.java b/phenolib/src/main/java/com/serenegiant/SimpleUVCCameraTextureView.java deleted file mode 100644 index e763de04..00000000 --- a/phenolib/src/main/java/com/serenegiant/SimpleUVCCameraTextureView.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@com.com.serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.TextureView; - -/** - * change the view size with keeping the specified aspect ratio. - * if you set this view with in a FrameLayout and set property "android:layout_gravity="center", - * you can show this view in the center of screen and keep the aspect ratio of content - * XXX it is better that can set the aspect raton a a xml property - */ -public class SimpleUVCCameraTextureView extends TextureView // API >= 14 - implements AspectRatioViewInterface { - - private double mRequestedAspect = -1.0; - - public SimpleUVCCameraTextureView(final Context context) { - this(context, null, 0); - } - - public SimpleUVCCameraTextureView(final Context context, final AttributeSet attrs) { - this(context, attrs, 0); - } - - public SimpleUVCCameraTextureView(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public void onResume() { - } - - @Override - public void onPause() { - } - - @Override - public void setAspectRatio(final double aspectRatio) { - if (aspectRatio < 0) { - throw new IllegalArgumentException(); - } - if (mRequestedAspect != aspectRatio) { - mRequestedAspect = aspectRatio; - requestLayout(); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - - if (mRequestedAspect > 0) { - int initialWidth = MeasureSpec.getSize(widthMeasureSpec); - int initialHeight = MeasureSpec.getSize(heightMeasureSpec); - - final int horizPadding = getPaddingLeft() + getPaddingRight(); - final int vertPadding = getPaddingTop() + getPaddingBottom(); - initialWidth -= horizPadding; - initialHeight -= vertPadding; - - final double viewAspectRatio = (double)initialWidth / initialHeight; - final double aspectDiff = mRequestedAspect / viewAspectRatio - 1; - - if (Math.abs(aspectDiff) > 0.01) { - if (aspectDiff > 0) { - // width priority decision - initialHeight = (int) (initialWidth / mRequestedAspect); - } else { - // height priority decison - initialWidth = (int) (initialHeight * mRequestedAspect); - } - initialWidth += horizPadding; - initialHeight += vertPadding; - widthMeasureSpec = MeasureSpec.makeMeasureSpec(initialWidth, MeasureSpec.EXACTLY); - heightMeasureSpec = MeasureSpec.makeMeasureSpec(initialHeight, MeasureSpec.EXACTLY); - } - } - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - -} \ No newline at end of file diff --git a/phenolib/src/main/java/com/serenegiant/encoder/IAudioEncoder.java b/phenolib/src/main/java/com/serenegiant/encoder/IAudioEncoder.java deleted file mode 100644 index 254fdb7e..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/IAudioEncoder.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -public interface IAudioEncoder { -} diff --git a/phenolib/src/main/java/com/serenegiant/encoder/IVideoEncoder.java b/phenolib/src/main/java/com/serenegiant/encoder/IVideoEncoder.java deleted file mode 100644 index 1f229a8e..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/IVideoEncoder.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -public interface IVideoEncoder { - public boolean frameAvailableSoon(); -} diff --git a/phenolib/src/main/java/com/serenegiant/encoder/MediaAudioEncoder.java b/phenolib/src/main/java/com/serenegiant/encoder/MediaAudioEncoder.java deleted file mode 100644 index a6a9010f..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/MediaAudioEncoder.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import android.media.AudioFormat; -import android.media.AudioRecord; -import android.media.MediaCodec; -import android.media.MediaCodecInfo; -import android.media.MediaCodecList; -import android.media.MediaFormat; -import android.media.MediaRecorder; -import android.util.Log; - -public class MediaAudioEncoder extends MediaEncoder implements IAudioEncoder { - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "MediaAudioEncoder"; - - private static final String MIME_TYPE = "audio/mp4a-latm"; - private static final int SAMPLE_RATE = 44100; // 44.1[KHz] is only setting guaranteed to be available on all devices. - private static final int BIT_RATE = 64000; - public static final int SAMPLES_PER_FRAME = 1024; // AAC, bytes/frame/channel - public static final int FRAMES_PER_BUFFER = 25; // AAC, frame/buffer/sec - - private AudioThread mAudioThread = null; - - public MediaAudioEncoder(final MediaMuxerWrapper muxer, final MediaEncoderListener listener) { - super(muxer, listener); - } - - @Override - protected void prepare() throws IOException { - if (DEBUG) Log.v(TAG, "prepare:"); - mTrackIndex = -1; - mMuxerStarted = mIsEOS = false; - // prepare MediaCodec for AAC encoding of audio data from inernal mic. - final MediaCodecInfo audioCodecInfo = selectAudioCodec(MIME_TYPE); - if (audioCodecInfo == null) { - Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE); - return; - } - if (DEBUG) Log.i(TAG, "selected codec: " + audioCodecInfo.getName()); - - final MediaFormat audioFormat = MediaFormat.createAudioFormat(MIME_TYPE, SAMPLE_RATE, 1); - audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC); - audioFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_IN_MONO); - audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); - audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); -// audioFormat.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, inputFile.length()); -// audioFormat.setLong(MediaFormat.KEY_DURATION, (long)durationInMs ); - if (DEBUG) Log.i(TAG, "format: " + audioFormat); - mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE); - mMediaCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); - mMediaCodec.start(); - if (DEBUG) Log.i(TAG, "prepare finishing"); - if (mListener != null) { - try { - mListener.onPrepared(this); - } catch (final Exception e) { - Log.e(TAG, "prepare:", e); - } - } - } - - @Override - protected void startRecording() { - super.startRecording(); - // create and execute audio capturing thread using internal mic - if (mAudioThread == null) { - mAudioThread = new AudioThread(); - mAudioThread.start(); - } - } - - @Override - protected void release() { - mAudioThread = null; - super.release(); - } - - private static final int[] AUDIO_SOURCES = new int[] { - MediaRecorder.AudioSource.DEFAULT, - MediaRecorder.AudioSource.MIC, - MediaRecorder.AudioSource.CAMCORDER, - }; - - /** - * Thread to capture audio data from internal mic as uncompressed 16bit PCM data - * and write them to the MediaCodec encoder - */ - private class AudioThread extends Thread { - @Override - public void run() { - android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO); // THREAD_PRIORITY_URGENT_AUDIO - int cnt = 0; - final int min_buffer_size = AudioRecord.getMinBufferSize( - SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); - int buffer_size = SAMPLES_PER_FRAME * FRAMES_PER_BUFFER; - if (buffer_size < min_buffer_size) - buffer_size = ((min_buffer_size / SAMPLES_PER_FRAME) + 1) * SAMPLES_PER_FRAME * 2; - final ByteBuffer buf = ByteBuffer.allocateDirect(SAMPLES_PER_FRAME).order(ByteOrder.nativeOrder()); - AudioRecord audioRecord = null; - for (final int src: AUDIO_SOURCES) { - try { - audioRecord = new AudioRecord(src, - SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, buffer_size); - if (audioRecord != null) { - if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) { - audioRecord.release(); - audioRecord = null; - } - } - } catch (final Exception e) { - audioRecord = null; - } - if (audioRecord != null) { - break; - } - } - if (audioRecord != null) { - try { - if (mIsCapturing) { - if (DEBUG) Log.v(TAG, "AudioThread:start audio recording"); - int readBytes; - audioRecord.startRecording(); - try { - for ( ; mIsCapturing && !mRequestStop && !mIsEOS ; ) { - // read audio data from internal mic - buf.clear(); - try { - readBytes = audioRecord.read(buf, SAMPLES_PER_FRAME); - } catch (final Exception e) { - break; - } - if (readBytes > 0) { - // set audio data to encoder - buf.position(readBytes); - buf.flip(); - encode(buf, readBytes, getPTSUs()); - frameAvailableSoon(); - cnt++; - } - } - if (cnt > 0) { - frameAvailableSoon(); - } - } finally { - audioRecord.stop(); - } - } - } catch (final Exception e) { - Log.e(TAG, "AudioThread#run", e); - } finally { - audioRecord.release(); - } - } - if (cnt == 0) { - for (int i = 0; mIsCapturing && (i < 5); i++) { - buf.position(SAMPLES_PER_FRAME); - buf.flip(); - try { - encode(buf, SAMPLES_PER_FRAME, getPTSUs()); - frameAvailableSoon(); - } catch (final Exception e) { - break; - } - synchronized(this) { - try { - wait(50); - } catch (final InterruptedException e) { - } - } - } - } - if (DEBUG) Log.v(TAG, "AudioThread:finished"); - } - } - - /** - * select the first codec that match a specific MIME type - * @param mimeType - * @return - */ - private static final MediaCodecInfo selectAudioCodec(final String mimeType) { - if (DEBUG) Log.v(TAG, "selectAudioCodec:"); - - MediaCodecInfo result = null; - // get the list of available codecs - final int numCodecs = MediaCodecList.getCodecCount(); -LOOP: for (int i = 0; i < numCodecs; i++) { - final MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); - if (!codecInfo.isEncoder()) { // skipp decoder - continue; - } - final String[] types = codecInfo.getSupportedTypes(); - for (int j = 0; j < types.length; j++) { - if (DEBUG) Log.i(TAG, "supportedType:" + codecInfo.getName() + ",MIME=" + types[j]); - if (types[j].equalsIgnoreCase(mimeType)) { - if (result == null) { - result = codecInfo; - break LOOP; - } - } - } - } - return result; - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/encoder/MediaEncoder.java b/phenolib/src/main/java/com/serenegiant/encoder/MediaEncoder.java deleted file mode 100644 index c3455acd..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/MediaEncoder.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.nio.ByteBuffer; - -import android.media.MediaCodec; -import android.media.MediaFormat; -import android.util.Log; - -public abstract class MediaEncoder implements Runnable { - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "MediaEncoder"; - - protected static final int TIMEOUT_USEC = 10000; // 10[msec] - protected static final int MSG_FRAME_AVAILABLE = 1; - protected static final int MSG_STOP_RECORDING = 9; - - public interface MediaEncoderListener { - public void onPrepared(MediaEncoder encoder); - public void onStopped(MediaEncoder encoder); - } - - protected final Object mSync = new Object(); - /** - * Flag that indicate this encoder is capturing now. - */ - protected volatile boolean mIsCapturing; - /** - * Flag that indicate the frame data will be available soon. - */ - private int mRequestDrain; - /** - * Flag to request stop capturing - */ - protected volatile boolean mRequestStop; - /** - * Flag that indicate encoder received EOS(End Of Stream) - */ - protected boolean mIsEOS; - /** - * Flag the indicate the muxer is running - */ - protected boolean mMuxerStarted; - /** - * Track Number - */ - protected int mTrackIndex; - /** - * MediaCodec instance for encoding - */ - protected MediaCodec mMediaCodec; // API >= 16(Android4.1.2) - /** - * Weak refarence of MediaMuxerWarapper instance - */ - protected final WeakReference mWeakMuxer; - /** - * BufferInfo instance for dequeuing - */ - private MediaCodec.BufferInfo mBufferInfo; // API >= 16(Android4.1.2) - - protected final MediaEncoderListener mListener; - - public MediaEncoder(final MediaMuxerWrapper muxer, final MediaEncoderListener listener) { - if (listener == null) throw new NullPointerException("MediaEncoderListener is null"); - if (muxer == null) throw new NullPointerException("MediaMuxerWrapper is null"); - mWeakMuxer = new WeakReference(muxer); - muxer.addEncoder(this); - mListener = listener; - synchronized (mSync) { - // create BufferInfo here for effectiveness(to reduce GC) - mBufferInfo = new MediaCodec.BufferInfo(); - // wait for starting thread - new Thread(this, getClass().getSimpleName()).start(); - try { - mSync.wait(); - } catch (final InterruptedException e) { - } - } - } - - public String getOutputPath() { - final MediaMuxerWrapper muxer = mWeakMuxer.get(); - return muxer != null ? muxer.getOutputPath() : null; - } - - /** - * the method to indicate frame data is soon available or already available - * @return return true if encoder is ready to encod. - */ - public boolean frameAvailableSoon() { -// if (DEBUG) Log.v(TAG, "frameAvailableSoon"); - synchronized (mSync) { - if (!mIsCapturing || mRequestStop) { - return false; - } - mRequestDrain++; - mSync.notifyAll(); - } - return true; - } - - /** - * encoding loop on private thread - */ - @Override - public void run() { -// android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); - synchronized (mSync) { - mRequestStop = false; - mRequestDrain = 0; - mSync.notify(); - } - final boolean isRunning = true; - boolean localRequestStop; - boolean localRequestDrain; - while (isRunning) { - synchronized (mSync) { - localRequestStop = mRequestStop; - localRequestDrain = (mRequestDrain > 0); - if (localRequestDrain) - mRequestDrain--; - } - if (localRequestStop) { - drain(); - // request stop recording - signalEndOfInputStream(); - // process output data again for EOS signale - drain(); - // release all related objects - release(); - break; - } - if (localRequestDrain) { - drain(); - } else { - synchronized (mSync) { - try { - mSync.wait(); - } catch (final InterruptedException e) { - break; - } - } - } - } // end of while - if (DEBUG) Log.d(TAG, "Encoder thread exiting"); - synchronized (mSync) { - mRequestStop = true; - mIsCapturing = false; - } - } - - /* - * prepareing method for each sub class - * this method should be implemented in sub class, so set this as abstract method - * @throws IOException - */ - /*package*/ abstract void prepare() throws IOException; - - /*package*/ void startRecording() { - if (DEBUG) Log.v(TAG, "startRecording"); - synchronized (mSync) { - mIsCapturing = true; - mRequestStop = false; - mSync.notifyAll(); - } - } - - /** - * the method to request stop encoding - */ - /*package*/ void stopRecording() { - if (DEBUG) Log.v(TAG, "stopRecording"); - synchronized (mSync) { - if (!mIsCapturing || mRequestStop) { - return; - } - mRequestStop = true; // for rejecting newer frame - mSync.notifyAll(); - // We can not know when the encoding and writing finish. - // so we return immediately after request to avoid delay of caller thread - } - } - -//******************************************************************************** -//******************************************************************************** - /** - * Release all releated objects - */ - protected void release() { - if (DEBUG) Log.d(TAG, "release:"); - try { - mListener.onStopped(this); - } catch (final Exception e) { - Log.e(TAG, "failed onStopped", e); - } - mIsCapturing = false; - if (mMediaCodec != null) { - try { - mMediaCodec.stop(); - mMediaCodec.release(); - mMediaCodec = null; - } catch (final Exception e) { - Log.e(TAG, "failed releasing MediaCodec", e); - } - } - if (mMuxerStarted) { - final MediaMuxerWrapper muxer = mWeakMuxer.get(); - if (muxer != null) { - try { - muxer.stop(); - } catch (final Exception e) { - Log.e(TAG, "failed stopping muxer", e); - } - } - } - mBufferInfo = null; - } - - protected void signalEndOfInputStream() { - if (DEBUG) Log.d(TAG, "sending EOS to encoder"); - // signalEndOfInputStream is only avairable for video encoding with surface - // and equivalent sending a empty buffer with BUFFER_FLAG_END_OF_STREAM flag. -// mMediaCodec.signalEndOfInputStream(); // API >= 18 - encode((byte[])null, 0, getPTSUs()); - } - - /** - * Method to set byte array to the MediaCodec encoder - * @param buffer - * @param length length of byte array, zero means EOS. - * @param presentationTimeUs - */ - @SuppressWarnings("deprecation") - protected void encode(final byte[] buffer, final int length, final long presentationTimeUs) { -// if (DEBUG) Log.v(TAG, "encode:buffer=" + buffer); - if (!mIsCapturing) return; - int ix = 0, sz; - final ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers(); - while (mIsCapturing && ix < length) { - final int inputBufferIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_USEC); - if (inputBufferIndex >= 0) { - final ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; - inputBuffer.clear(); - sz = inputBuffer.remaining(); - sz = (ix + sz < length) ? sz : length - ix; - if (sz > 0 && (buffer != null)) { - inputBuffer.put(buffer, ix, sz); - } - ix += sz; -// if (DEBUG) Log.v(TAG, "encode:queueInputBuffer"); - if (length <= 0) { - // send EOS - mIsEOS = true; - if (DEBUG) Log.i(TAG, "send BUFFER_FLAG_END_OF_STREAM"); - mMediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, - presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); - break; - } else { - mMediaCodec.queueInputBuffer(inputBufferIndex, 0, sz, - presentationTimeUs, 0); - } - } else if (inputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) { - // wait for MediaCodec encoder is ready to encode - // nothing to do here because MediaCodec#dequeueInputBuffer(TIMEOUT_USEC) - // will wait for maximum TIMEOUT_USEC(10msec) on each call - } - } - } - - /** - * Method to set ByteBuffer to the MediaCodec encoder - * @param buffer null means EOS - * @param presentationTimeUs - */ - @SuppressWarnings("deprecation") - protected void encode(final ByteBuffer buffer, final int length, final long presentationTimeUs) { -// if (DEBUG) Log.v(TAG, "encode:buffer=" + buffer); - if (!mIsCapturing) return; - int ix = 0, sz; - final ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers(); - while (mIsCapturing && ix < length) { - final int inputBufferIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_USEC); - if (inputBufferIndex >= 0) { - final ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; - inputBuffer.clear(); - sz = inputBuffer.remaining(); - sz = (ix + sz < length) ? sz : length - ix; - if (sz > 0 && (buffer != null)) { - buffer.position(ix + sz); - buffer.flip(); - inputBuffer.put(buffer); - } - ix += sz; -// if (DEBUG) Log.v(TAG, "encode:queueInputBuffer"); - if (length <= 0) { - // send EOS - mIsEOS = true; - if (DEBUG) Log.i(TAG, "send BUFFER_FLAG_END_OF_STREAM"); - mMediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, - presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); - break; - } else { - mMediaCodec.queueInputBuffer(inputBufferIndex, 0, sz, - presentationTimeUs, 0); - } - } else if (inputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) { - // wait for MediaCodec encoder is ready to encode - // nothing to do here because MediaCodec#dequeueInputBuffer(TIMEOUT_USEC) - // will wait for maximum TIMEOUT_USEC(10msec) on each call - } - } - } - - /** - * drain encoded data and write them to muxer - */ - @SuppressWarnings("deprecation") - protected void drain() { - if (mMediaCodec == null) return; - ByteBuffer[] encoderOutputBuffers = mMediaCodec.getOutputBuffers(); - int encoderStatus, count = 0; - final MediaMuxerWrapper muxer = mWeakMuxer.get(); - if (muxer == null) { -// throw new NullPointerException("muxer is unexpectedly null"); - Log.w(TAG, "muxer is unexpectedly null"); - return; - } -LOOP: while (mIsCapturing) { - // get encoded data with maximum timeout duration of TIMEOUT_USEC(=10[msec]) - encoderStatus = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC); - if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { - // wait 5 counts(=TIMEOUT_USEC x 5 = 50msec) until data/EOS come - if (!mIsEOS) { - if (++count > 5) - break LOOP; // out of while - } - } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { - if (DEBUG) Log.v(TAG, "INFO_OUTPUT_BUFFERS_CHANGED"); - // this shoud not come when encoding - encoderOutputBuffers = mMediaCodec.getOutputBuffers(); - } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { - if (DEBUG) Log.v(TAG, "INFO_OUTPUT_FORMAT_CHANGED"); - // this status indicate the output format of codec is changed - // this should come only once before actual encoded data - // but this status never come on Android4.3 or less - // and in that case, you should treat when MediaCodec.BUFFER_FLAG_CODEC_CONFIG come. - if (mMuxerStarted) { // second time request is error - throw new RuntimeException("format changed twice"); - } - // get output format from codec and pass them to muxer - // getOutputFormat should be called after INFO_OUTPUT_FORMAT_CHANGED otherwise crash. - final MediaFormat format = mMediaCodec.getOutputFormat(); // API >= 16 - mTrackIndex = muxer.addTrack(format); - mMuxerStarted = true; - if (!muxer.start()) { - // we should wait until muxer is ready - synchronized (muxer) { - while (!muxer.isStarted()) - try { - muxer.wait(100); - } catch (final InterruptedException e) { - break LOOP; - } - } - } - } else if (encoderStatus < 0) { - // unexpected status - if (DEBUG) Log.w(TAG, "drain:unexpected result from encoder#dequeueOutputBuffer: " + encoderStatus); - } else { - final ByteBuffer encodedData = encoderOutputBuffers[encoderStatus]; - if (encodedData == null) { - // this never should come...may be a MediaCodec internal error - throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null"); - } - if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) { - // You shoud set output format to muxer here when you target Android4.3 or less - // but MediaCodec#getOutputFormat can not call here(because INFO_OUTPUT_FORMAT_CHANGED don't come yet) - // therefor we should expand and prepare output format from buffer data. - // This sample is for API>=18(>=Android 4.3), just ignore this flag here - if (DEBUG) Log.d(TAG, "drain:BUFFER_FLAG_CODEC_CONFIG"); - mBufferInfo.size = 0; - } - - if (mBufferInfo.size != 0) { - // encoded data is ready, clear waiting counter - count = 0; - if (!mMuxerStarted) { - // muxer is not ready...this will prrograming failure. - throw new RuntimeException("drain:muxer hasn't started"); - } - // write encoded data to muxer(need to adjust presentationTimeUs. - mBufferInfo.presentationTimeUs = getPTSUs(); - muxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo); - prevOutputPTSUs = mBufferInfo.presentationTimeUs; - } - // return buffer to encoder - mMediaCodec.releaseOutputBuffer(encoderStatus, false); - if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { - // when EOS come. - mMuxerStarted = mIsCapturing = false; - break; // out of while - } - } - } - } - - /** - * previous presentationTimeUs for writing - */ - private long prevOutputPTSUs = 0; - /** - * get next encoding presentationTimeUs - * @return - */ - protected long getPTSUs() { - long result = System.nanoTime() / 1000L; - // presentationTimeUs should be monotonic - // otherwise muxer fail to write - if (result < prevOutputPTSUs) - result = (prevOutputPTSUs - result) + result; - return result; - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/encoder/MediaMuxerWrapper.java b/phenolib/src/main/java/com/serenegiant/encoder/MediaMuxerWrapper.java deleted file mode 100644 index 29afe8d1..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/MediaMuxerWrapper.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.text.SimpleDateFormat; -import java.util.GregorianCalendar; -import java.util.Locale; - -import android.media.MediaCodec; -import android.media.MediaFormat; -import android.media.MediaMuxer; -import android.os.Environment; -import android.text.TextUtils; -import android.util.Log; - -public class MediaMuxerWrapper { - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "MediaMuxerWrapper"; - - private static final String DIR_NAME = "USBCameraTest"; - private static final SimpleDateFormat mDateTimeFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US); - - private String mOutputPath; - private final MediaMuxer mMediaMuxer; // API >= 18 - private int mEncoderCount, mStatredCount; - private boolean mIsStarted; - private MediaEncoder mVideoEncoder, mAudioEncoder; - - /** - * Constructor - * @param ext extension of output file - * @throws IOException - */ - public MediaMuxerWrapper(String ext) throws IOException { - if (TextUtils.isEmpty(ext)) ext = ".mp4"; - try { - mOutputPath = getCaptureFile(Environment.DIRECTORY_MOVIES, ext).toString(); - } catch (final NullPointerException e) { - throw new RuntimeException("This app has no permission of writing external storage"); - } - mMediaMuxer = new MediaMuxer(mOutputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); - mEncoderCount = mStatredCount = 0; - mIsStarted = false; - } - - public String getOutputPath() { - return mOutputPath; - } - - public void prepare() throws IOException { - if (mVideoEncoder != null) - mVideoEncoder.prepare(); - if (mAudioEncoder != null) - mAudioEncoder.prepare(); - } - - public void startRecording() { - if (mVideoEncoder != null) - mVideoEncoder.startRecording(); - if (mAudioEncoder != null) - mAudioEncoder.startRecording(); - } - - public void stopRecording() { - if (mVideoEncoder != null) - mVideoEncoder.stopRecording(); - mVideoEncoder = null; - if (mAudioEncoder != null) - mAudioEncoder.stopRecording(); - mAudioEncoder = null; - } - - public synchronized boolean isStarted() { - return mIsStarted; - } - -//********************************************************************** -//********************************************************************** - /** - * assign encoder to this calss. this is called from encoder. - * @param encoder instance of MediaVideoEncoder or MediaAudioEncoder - */ - /*package*/ void addEncoder(final MediaEncoder encoder) { - if (encoder instanceof MediaVideoEncoder) { - if (mVideoEncoder != null) - throw new IllegalArgumentException("Video encoder already added."); - mVideoEncoder = encoder; - } else if (encoder instanceof MediaSurfaceEncoder) { - if (mVideoEncoder != null) - throw new IllegalArgumentException("Video encoder already added."); - mVideoEncoder = encoder; - } else if (encoder instanceof MediaVideoBufferEncoder) { - if (mVideoEncoder != null) - throw new IllegalArgumentException("Video encoder already added."); - mVideoEncoder = encoder; - } else if (encoder instanceof MediaAudioEncoder) { - if (mAudioEncoder != null) - throw new IllegalArgumentException("Video encoder already added."); - mAudioEncoder = encoder; - } else - throw new IllegalArgumentException("unsupported encoder"); - mEncoderCount = (mVideoEncoder != null ? 1 : 0) + (mAudioEncoder != null ? 1 : 0); - } - - /** - * request start recording from encoder - * @return true when muxer is ready to write - */ - /*package*/ synchronized boolean start() { - if (DEBUG) Log.v(TAG, "start:"); - mStatredCount++; - if ((mEncoderCount > 0) && (mStatredCount == mEncoderCount)) { - mMediaMuxer.start(); - mIsStarted = true; - notifyAll(); - if (DEBUG) Log.v(TAG, "MediaMuxer started:"); - } - return mIsStarted; - } - - /** - * request stop recording from encoder when encoder received EOS - */ - /*package*/ synchronized void stop() { - if (DEBUG) Log.v(TAG, "stop:mStatredCount=" + mStatredCount); - mStatredCount--; - if ((mEncoderCount > 0) && (mStatredCount <= 0)) { - try { - mMediaMuxer.stop(); - } catch (final Exception e) { - Log.w(TAG, e); - } - mIsStarted = false; - if (DEBUG) Log.v(TAG, "MediaMuxer stopped:"); - } - } - - /** - * assign encoder to muxer - * @param format - * @return minus value indicate error - */ - /*package*/ synchronized int addTrack(final MediaFormat format) { - if (mIsStarted) - throw new IllegalStateException("muxer already started"); - final int trackIx = mMediaMuxer.addTrack(format); - if (DEBUG) Log.i(TAG, "addTrack:trackNum=" + mEncoderCount + ",trackIx=" + trackIx + ",format=" + format); - return trackIx; - } - - /** - * write encoded data to muxer - * @param trackIndex - * @param byteBuf - * @param bufferInfo - */ - /*package*/ synchronized void writeSampleData(final int trackIndex, final ByteBuffer byteBuf, final MediaCodec.BufferInfo bufferInfo) { - if (mStatredCount > 0) - mMediaMuxer.writeSampleData(trackIndex, byteBuf, bufferInfo); - } - -//********************************************************************** -//********************************************************************** - /** - * generate output file - * @param type Environment.DIRECTORY_MOVIES / Environment.DIRECTORY_DCIM etc. - * @param ext .mp4(.m4a for audio) or .png - * @return return null when this app has no writing permission to external storage. - */ - public static final File getCaptureFile(final String type, final String ext) { - final File dir = new File(Environment.getExternalStoragePublicDirectory(type), DIR_NAME); - Log.d(TAG, "path=" + dir.toString()); - dir.mkdirs(); - if (dir.canWrite()) { - return new File(dir, getDateTimeString() + ext); - } - return null; - } - - /** - * get current date and time as String - * @return - */ - private static final String getDateTimeString() { - final GregorianCalendar now = new GregorianCalendar(); - return mDateTimeFormat.format(now.getTime()); - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/encoder/MediaSurfaceEncoder.java b/phenolib/src/main/java/com/serenegiant/encoder/MediaSurfaceEncoder.java deleted file mode 100644 index 5649e416..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/MediaSurfaceEncoder.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -import java.io.IOException; - -import android.media.MediaCodec; -import android.media.MediaCodecInfo; -import android.media.MediaCodecList; -import android.media.MediaFormat; -import android.util.Log; -import android.view.Surface; - -public class MediaSurfaceEncoder extends MediaEncoder implements IVideoEncoder { - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "MediaSurfaceEncoder"; - - private static final String MIME_TYPE = "video/avc"; - // parameters for recording - private final int mWidth, mHeight; - private static final int FRAME_RATE = 15; - private static final float BPP = 0.50f; - - private Surface mSurface; - - public MediaSurfaceEncoder(final MediaMuxerWrapper muxer, final int width, final int height, final MediaEncoderListener listener) { - super(muxer, listener); - if (DEBUG) Log.i(TAG, "MediaVideoEncoder: "); - mWidth = width; - mHeight = height; - } - - /** - * Returns the encoder's input surface. - */ - public Surface getInputSurface() { - return mSurface; - } - - @Override - protected void prepare() throws IOException { - if (DEBUG) Log.i(TAG, "prepare: "); - mTrackIndex = -1; - mMuxerStarted = mIsEOS = false; - - final MediaCodecInfo videoCodecInfo = selectVideoCodec(MIME_TYPE); - if (videoCodecInfo == null) { - Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE); - return; - } - if (DEBUG) Log.i(TAG, "selected codec: " + videoCodecInfo.getName()); - - final MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight); - format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); // API >= 18 - format.setInteger(MediaFormat.KEY_BIT_RATE, calcBitRate()); - format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE); - format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); - if (DEBUG) Log.i(TAG, "format: " + format); - - mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE); - mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); - // get Surface for encoder input - // this method only can call between #configure and #start - mSurface = mMediaCodec.createInputSurface(); // API >= 18 - mMediaCodec.start(); - if (DEBUG) Log.i(TAG, "prepare finishing"); - if (mListener != null) { - try { - mListener.onPrepared(this); - } catch (final Exception e) { - Log.e(TAG, "prepare:", e); - } - } - } - - @Override - protected void release() { - if (DEBUG) Log.i(TAG, "release:"); - if (mSurface != null) { - mSurface.release(); - mSurface = null; - } - super.release(); - } - - private int calcBitRate() { - final int bitrate = (int)(BPP * FRAME_RATE * mWidth * mHeight); - Log.i(TAG, String.format("bitrate=%5.2f[Mbps]", bitrate / 1024f / 1024f)); - return bitrate; - } - - /** - * select the first codec that match a specific MIME type - * @param mimeType - * @return null if no codec matched - */ - protected static final MediaCodecInfo selectVideoCodec(final String mimeType) { - if (DEBUG) Log.v(TAG, "selectVideoCodec:"); - - // get the list of available codecs - final int numCodecs = MediaCodecList.getCodecCount(); - for (int i = 0; i < numCodecs; i++) { - final MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); - - if (!codecInfo.isEncoder()) { // skipp decoder - continue; - } - // select first codec that match a specific MIME type and color format - final String[] types = codecInfo.getSupportedTypes(); - for (int j = 0; j < types.length; j++) { - if (types[j].equalsIgnoreCase(mimeType)) { - if (DEBUG) Log.i(TAG, "codec:" + codecInfo.getName() + ",MIME=" + types[j]); - final int format = selectColorFormat(codecInfo, mimeType); - if (format > 0) { - return codecInfo; - } - } - } - } - return null; - } - - /** - * select color format available on specific codec and we can use. - * @return 0 if no colorFormat is matched - */ - protected static final int selectColorFormat(final MediaCodecInfo codecInfo, final String mimeType) { - if (DEBUG) Log.i(TAG, "selectColorFormat: "); - int result = 0; - final MediaCodecInfo.CodecCapabilities caps; - try { - Thread.currentThread().setPriority(Thread.MAX_PRIORITY); - caps = codecInfo.getCapabilitiesForType(mimeType); - } finally { - Thread.currentThread().setPriority(Thread.NORM_PRIORITY); - } - int colorFormat; - for (int i = 0; i < caps.colorFormats.length; i++) { - colorFormat = caps.colorFormats[i]; - if (isRecognizedVideoFormat(colorFormat)) { - if (result == 0) - result = colorFormat; - break; - } - } - if (result == 0) - Log.e(TAG, "couldn't find a good color format for " + codecInfo.getName() + " / " + mimeType); - return result; - } - - /** - * color formats that we can use in this class - */ - protected static int[] recognizedFormats; - static { - recognizedFormats = new int[] { -// MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, -// MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, -// MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, - MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface, - }; - } - - private static final boolean isRecognizedVideoFormat(final int colorFormat) { - if (DEBUG) Log.i(TAG, "isRecognizedVideoFormat:colorFormat=" + colorFormat); - final int n = recognizedFormats != null ? recognizedFormats.length : 0; - for (int i = 0; i < n; i++) { - if (recognizedFormats[i] == colorFormat) { - return true; - } - } - return false; - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/encoder/MediaVideoBufferEncoder.java b/phenolib/src/main/java/com/serenegiant/encoder/MediaVideoBufferEncoder.java deleted file mode 100644 index ee06a006..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/MediaVideoBufferEncoder.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import android.annotation.TargetApi; -import android.media.MediaCodec; -import android.media.MediaCodecInfo; -import android.media.MediaCodecList; -import android.media.MediaFormat; -import android.util.Log; - -/** - * This class receives video images as ByteBuffer(strongly recommend direct ByteBuffer) as NV21(YUV420SP) - * and encode them to h.264. - * If you use this directly with IFrameCallback, you should know UVCCamera and it backend native libraries - * never execute color space conversion. This means that color tone of resulted movie will be different - * from that you expected/can see on screen. - */ -public class MediaVideoBufferEncoder extends MediaEncoder implements IVideoEncoder { - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "MediaVideoBufferEncoder"; - - private static final String MIME_TYPE = "video/avc"; - // parameters for recording - private static final int FRAME_RATE = 15; - private static final float BPP = 0.50f; - - private final int mWidth, mHeight; - protected int mColorFormat; - - public MediaVideoBufferEncoder(final MediaMuxerWrapper muxer, final int width, final int height, final MediaEncoderListener listener) { - super(muxer, listener); - if (DEBUG) Log.i(TAG, "MediaVideoEncoder: "); - mWidth = width; - mHeight = height; - } - - public void encode(final ByteBuffer buffer) { -// if (DEBUG) Log.v(TAG, "encode:buffer=" + buffer); - synchronized (mSync) { - if (!mIsCapturing || mRequestStop) return; - } - encode(buffer, buffer.capacity(), getPTSUs()); - } - - @Override - protected void prepare() throws IOException { - if (DEBUG) Log.i(TAG, "prepare: "); - mTrackIndex = -1; - mMuxerStarted = mIsEOS = false; - - final MediaCodecInfo videoCodecInfo = selectVideoCodec(MIME_TYPE); - if (videoCodecInfo == null) { - Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE); - return; - } - if (DEBUG) Log.i(TAG, "selected codec: " + videoCodecInfo.getName()); - - 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, FRAME_RATE); - format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); - if (DEBUG) Log.i(TAG, "format: " + format); - - mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE); - mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); - mMediaCodec.start(); - if (DEBUG) Log.i(TAG, "prepare finishing"); - if (mListener != null) { - try { - mListener.onPrepared(this); - } catch (final Exception e) { - Log.e(TAG, "prepare:", e); - } - } - } - - private int calcBitRate() { - final int bitrate = (int)(BPP * FRAME_RATE * mWidth * mHeight); - Log.i(TAG, String.format("bitrate=%5.2f[Mbps]", bitrate / 1024f / 1024f)); - return bitrate; - } - - /** - * select the first codec that match a specific MIME type - * @param mimeType - * @return null if no codec matched - */ - @SuppressWarnings("deprecation") - protected final MediaCodecInfo selectVideoCodec(final String mimeType) { - if (DEBUG) Log.v(TAG, "selectVideoCodec:"); - - // get the list of available codecs - final int numCodecs = MediaCodecList.getCodecCount(); - for (int i = 0; i < numCodecs; i++) { - final MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); - - if (!codecInfo.isEncoder()) { // skipp decoder - continue; - } - // select first codec that match a specific MIME type and color format - final String[] types = codecInfo.getSupportedTypes(); - for (int j = 0; j < types.length; j++) { - if (types[j].equalsIgnoreCase(mimeType)) { - if (DEBUG) Log.i(TAG, "codec:" + codecInfo.getName() + ",MIME=" + types[j]); - final int format = selectColorFormat(codecInfo, mimeType); - if (format > 0) { - mColorFormat = format; - return codecInfo; - } - } - } - } - return null; - } - - /** - * select color format available on specific codec and we can use. - * @return 0 if no colorFormat is matched - */ - protected static final int selectColorFormat(final MediaCodecInfo codecInfo, final String mimeType) { - if (DEBUG) Log.i(TAG, "selectColorFormat: "); - int result = 0; - final MediaCodecInfo.CodecCapabilities caps; - try { - Thread.currentThread().setPriority(Thread.MAX_PRIORITY); - caps = codecInfo.getCapabilitiesForType(mimeType); - } finally { - Thread.currentThread().setPriority(Thread.NORM_PRIORITY); - } - int colorFormat; - for (int i = 0; i < caps.colorFormats.length; i++) { - colorFormat = caps.colorFormats[i]; - if (isRecognizedViewoFormat(colorFormat)) { - if (result == 0) - result = colorFormat; - break; - } - } - if (result == 0) - Log.e(TAG, "couldn't find a good color format for " + codecInfo.getName() + " / " + mimeType); - return result; - } - - /** - * color formats that we can use in this class - */ - protected static int[] recognizedFormats; - static { - recognizedFormats = new int[] { -// MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, - MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, - MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, -// MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface, - }; - } - - private static final boolean isRecognizedViewoFormat(final int colorFormat) { - if (DEBUG) Log.i(TAG, "isRecognizedViewoFormat:colorFormat=" + colorFormat); - final int n = recognizedFormats != null ? recognizedFormats.length : 0; - for (int i = 0; i < n; i++) { - if (recognizedFormats[i] == colorFormat) { - return true; - } - } - return false; - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/encoder/MediaVideoEncoder.java b/phenolib/src/main/java/com/serenegiant/encoder/MediaVideoEncoder.java deleted file mode 100644 index fb99c59d..00000000 --- a/phenolib/src/main/java/com/serenegiant/encoder/MediaVideoEncoder.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.encoder; - -import java.io.IOException; - -import android.media.MediaCodec; -import android.media.MediaCodecInfo; -import android.media.MediaCodecList; -import android.media.MediaFormat; -import android.util.Log; -import android.view.Surface; - -import com.serenegiant.glutils.EGLBase; -import com.serenegiant.glutils.RenderHandler; - -/** - * Encode texture images as H.264 video - * using MediaCodec. - * This class render texture images into recording surface - * camera from MediaCodec encoder using Open GL|ES - */ -public class MediaVideoEncoder extends MediaEncoder implements IVideoEncoder { - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "MediaVideoEncoder"; - - private static final String MIME_TYPE = "video/avc"; - // parameters for recording - private final int mWidth, mHeight; - private static final int FRAME_RATE = 15; - private static final float BPP = 0.50f; - - private RenderHandler mRenderHandler; - private Surface mSurface; - - public MediaVideoEncoder(final MediaMuxerWrapper muxer, final int width, final int height, final MediaEncoderListener listener) { - super(muxer, listener); - if (DEBUG) Log.i(TAG, "MediaVideoEncoder: "); - mRenderHandler = RenderHandler.createHandler(TAG); - mWidth = width; - mHeight = height; - } - - public boolean frameAvailableSoon(final float[] tex_matrix) { - boolean result; - if (result = super.frameAvailableSoon()) - mRenderHandler.draw(tex_matrix); - return result; - } - - /** - * This method does not work correctly on this class, - * use #frameAvailableSoon(final float[]) instead - * @return - */ - @Override - public boolean frameAvailableSoon() { - boolean result; - if (result = super.frameAvailableSoon()) - mRenderHandler.draw(null); - return result; - } - - @Override - protected void prepare() throws IOException { - if (DEBUG) Log.i(TAG, "prepare: "); - mTrackIndex = -1; - mMuxerStarted = mIsEOS = false; - - final MediaCodecInfo videoCodecInfo = selectVideoCodec(MIME_TYPE); - if (videoCodecInfo == null) { - Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE); - return; - } - if (DEBUG) Log.i(TAG, "selected codec: " + videoCodecInfo.getName()); - - final MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight); - format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); // API >= 18 - format.setInteger(MediaFormat.KEY_BIT_RATE, calcBitRate()); - format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE); - format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); - if (DEBUG) Log.i(TAG, "format: " + format); - - mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE); - mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); - // get Surface for encoder input - // this method only can call between #configure and #start - mSurface = mMediaCodec.createInputSurface(); // API >= 18 - mMediaCodec.start(); - if (DEBUG) Log.i(TAG, "prepare finishing"); - if (mListener != null) { - try { - mListener.onPrepared(this); - } catch (final Exception e) { - Log.e(TAG, "prepare:", e); - } - } - } - - public void setEglContext(final EGLBase.IContext sharedContext, final int tex_id) { - mRenderHandler.setEglContext(sharedContext, tex_id, mSurface, true); - } - - @Override - protected void release() { - if (DEBUG) Log.i(TAG, "release:"); - if (mSurface != null) { - mSurface.release(); - mSurface = null; - } - if (mRenderHandler != null) { - mRenderHandler.release(); - mRenderHandler = null; - } - super.release(); - } - - private int calcBitRate() { - final int bitrate = (int)(BPP * FRAME_RATE * mWidth * mHeight); - Log.i(TAG, String.format("bitrate=%5.2f[Mbps]", bitrate / 1024f / 1024f)); - return bitrate; - } - - /** - * select the first codec that match a specific MIME type - * @param mimeType - * @return null if no codec matched - */ - protected static final MediaCodecInfo selectVideoCodec(final String mimeType) { - if (DEBUG) Log.v(TAG, "selectVideoCodec:"); - - // get the list of available codecs - final int numCodecs = MediaCodecList.getCodecCount(); - for (int i = 0; i < numCodecs; i++) { - final MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); - - if (!codecInfo.isEncoder()) { // skipp decoder - continue; - } - // select first codec that match a specific MIME type and color format - final String[] types = codecInfo.getSupportedTypes(); - for (int j = 0; j < types.length; j++) { - if (types[j].equalsIgnoreCase(mimeType)) { - if (DEBUG) Log.i(TAG, "codec:" + codecInfo.getName() + ",MIME=" + types[j]); - final int format = selectColorFormat(codecInfo, mimeType); - if (format > 0) { - return codecInfo; - } - } - } - } - return null; - } - - /** - * select color format available on specific codec and we can use. - * @return 0 if no colorFormat is matched - */ - protected static final int selectColorFormat(final MediaCodecInfo codecInfo, final String mimeType) { - if (DEBUG) Log.i(TAG, "selectColorFormat: "); - int result = 0; - final MediaCodecInfo.CodecCapabilities caps; - try { - Thread.currentThread().setPriority(Thread.MAX_PRIORITY); - caps = codecInfo.getCapabilitiesForType(mimeType); - } finally { - Thread.currentThread().setPriority(Thread.NORM_PRIORITY); - } - int colorFormat; - for (int i = 0; i < caps.colorFormats.length; i++) { - colorFormat = caps.colorFormats[i]; - if (isRecognizedVideoFormat(colorFormat)) { - if (result == 0) - result = colorFormat; - break; - } - } - if (result == 0) - Log.e(TAG, "couldn't find a good color format for " + codecInfo.getName() + " / " + mimeType); - return result; - } - - /** - * color formats that we can use in this class - */ - protected static int[] recognizedFormats; - static { - recognizedFormats = new int[] { -// MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, -// MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, -// MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, - MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface, - }; - } - - private static final boolean isRecognizedVideoFormat(final int colorFormat) { - if (DEBUG) Log.i(TAG, "isRecognizedVideoFormat:colorFormat=" + colorFormat); - final int n = recognizedFormats != null ? recognizedFormats.length : 0; - for (int i = 0; i < n; i++) { - if (recognizedFormats[i] == colorFormat) { - return true; - } - } - return false; - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/DeviceFilter.java b/phenolib/src/main/java/com/serenegiant/usb/DeviceFilter.java deleted file mode 100644 index c7d2388b..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/DeviceFilter.java +++ /dev/null @@ -1,527 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@com.com.serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usb; - -import android.content.Context; -import android.content.res.Resources.NotFoundException; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbInterface; -import android.text.TextUtils; -import android.util.Log; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public final class DeviceFilter { - - private static final String TAG = "DeviceFilter"; - - // USB Vendor ID (or -1 for unspecified) - public final int mVendorId; - // USB Product ID (or -1 for unspecified) - public final int mProductId; - // USB device or interface class (or -1 for unspecified) - public final int mClass; - // USB device subclass (or -1 for unspecified) - public final int mSubclass; - // USB device protocol (or -1 for unspecified) - public final int mProtocol; - // USB device manufacturer name string (or null for unspecified) - public final String mManufacturerName; - // USB device product name string (or null for unspecified) - public final String mProductName; - // USB device serial number string (or null for unspecified) - public final String mSerialNumber; - // set true if specific device(s) should exclude - public final boolean isExclude; - - public DeviceFilter(final int vid, final int pid, final int clasz, final int subclass, - final int protocol, final String manufacturer, final String product, final String serialNum) { - this(vid, pid, clasz, subclass, protocol, manufacturer, product, serialNum, false); - } - - public DeviceFilter(final int vid, final int pid, final int clasz, final int subclass, - final int protocol, final String manufacturer, final String product, final String serialNum, final boolean isExclude) { - mVendorId = vid; - mProductId = pid; - mClass = clasz; - mSubclass = subclass; - mProtocol = protocol; - mManufacturerName = manufacturer; - mProductName = product; - mSerialNumber = serialNum; - this.isExclude = isExclude; -/* Log.i(TAG, String.format("vendorId=0x%04x,productId=0x%04x,class=0x%02x,subclass=0x%02x,protocol=0x%02x", - mVendorId, mProductId, mClass, mSubclass, mProtocol)); */ - } - - public DeviceFilter(final UsbDevice device) { - this(device, false); - } - - public DeviceFilter(final UsbDevice device, final boolean isExclude) { - mVendorId = device.getVendorId(); - mProductId = device.getProductId(); - mClass = device.getDeviceClass(); - mSubclass = device.getDeviceSubclass(); - mProtocol = device.getDeviceProtocol(); - mManufacturerName = null; // device.getManufacturerName(); - mProductName = null; // device.getProductName(); - mSerialNumber = null; // device.getSerialNumber(); - this.isExclude = isExclude; -/* Log.i(TAG, String.format("vendorId=0x%04x,productId=0x%04x,class=0x%02x,subclass=0x%02x,protocol=0x%02x", - mVendorId, mProductId, mClass, mSubclass, mProtocol)); */ - } - - /** - * 指定したxmlリソースからDeviceFilterリストを生成する - * @param context - * @param deviceFilterXmlId - * @return - */ - public static List getDeviceFilters(final Context context, final int deviceFilterXmlId) { - final XmlPullParser parser = context.getResources().getXml(deviceFilterXmlId); - final List deviceFilters = new ArrayList(); - try { - int eventType = parser.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - final DeviceFilter deviceFilter = readEntryOne(context, parser); - if (deviceFilter != null) { - deviceFilters.add(deviceFilter); - } - } - eventType = parser.next(); - } - } catch (final XmlPullParserException e) { - Log.d(TAG, "XmlPullParserException", e); - } catch (final IOException e) { - Log.d(TAG, "IOException", e); - } - - return Collections.unmodifiableList(deviceFilters); - } - - /** - * read as integer values with default value from xml(w/o exception throws) - * resource integer id is also resolved into integer - * @param parser - * @param namespace - * @param name - * @param defaultValue - * @return - */ - private static final int getAttributeInteger(final Context context, final XmlPullParser parser, final String namespace, final String name, final int defaultValue) { - int result = defaultValue; - try { - String v = parser.getAttributeValue(namespace, name); - if (!TextUtils.isEmpty(v) && v.startsWith("@")) { - final String r = v.substring(1); - final int resId = context.getResources().getIdentifier(r, null, context.getPackageName()); - if (resId > 0) { - result = context.getResources().getInteger(resId); - } - } else { - int radix = 10; - if (v != null && v.length() > 2 && v.charAt(0) == '0' && - (v.charAt(1) == 'x' || v.charAt(1) == 'X')) { - // allow hex values starting with 0x or 0X - radix = 16; - v = v.substring(2); - } - result = Integer.parseInt(v, radix); - } - } catch (final NotFoundException e) { - result = defaultValue; - } catch (final NumberFormatException e) { - result = defaultValue; - } catch (final NullPointerException e) { - result = defaultValue; - } - return result; - } - - /** - * read as boolean values with default value from xml(w/o exception throws) - * resource boolean id is also resolved into boolean - * if the value is zero, return false, if the value is non-zero integer, return true - * @param context - * @param parser - * @param namespace - * @param name - * @param defaultValue - * @return - */ - private static final boolean getAttributeBoolean(final Context context, final XmlPullParser parser, final String namespace, final String name, final boolean defaultValue) { - boolean result = defaultValue; - try { - String v = parser.getAttributeValue(namespace, name); - if ("TRUE".equalsIgnoreCase(v)) { - result = true; - } else if ("FALSE".equalsIgnoreCase(v)) { - result = false; - } else if (!TextUtils.isEmpty(v) && v.startsWith("@")) { - final String r = v.substring(1); - final int resId = context.getResources().getIdentifier(r, null, context.getPackageName()); - if (resId > 0) { - result = context.getResources().getBoolean(resId); - } - } else { - int radix = 10; - if (v != null && v.length() > 2 && v.charAt(0) == '0' && - (v.charAt(1) == 'x' || v.charAt(1) == 'X')) { - // allow hex values starting with 0x or 0X - radix = 16; - v = v.substring(2); - } - final int val = Integer.parseInt(v, radix); - result = val != 0; - } - } catch (final NotFoundException e) { - result = defaultValue; - } catch (final NumberFormatException e) { - result = defaultValue; - } catch (final NullPointerException e) { - result = defaultValue; - } - return result; - } - - /** - * read as String attribute with default value from xml(w/o exception throws) - * resource string id is also resolved into string - * @param parser - * @param namespace - * @param name - * @param defaultValue - * @return - */ - private static final String getAttributeString(final Context context, final XmlPullParser parser, final String namespace, final String name, final String defaultValue) { - String result = defaultValue; - try { - result = parser.getAttributeValue(namespace, name); - if (result == null) - result = defaultValue; - if (!TextUtils.isEmpty(result) && result.startsWith("@")) { - final String r = result.substring(1); - final int resId = context.getResources().getIdentifier(r, null, context.getPackageName()); - if (resId > 0) - result = context.getResources().getString(resId); - } - } catch (final NotFoundException e) { - result = defaultValue; - } catch (final NumberFormatException e) { - result = defaultValue; - } catch (final NullPointerException e) { - result = defaultValue; - } - return result; - } - - public static DeviceFilter readEntryOne(final Context context, final XmlPullParser parser) - throws XmlPullParserException, IOException { - int vendorId = -1; - int productId = -1; - int deviceClass = -1; - int deviceSubclass = -1; - int deviceProtocol = -1; - boolean exclude = false; - String manufacturerName = null; - String productName = null; - String serialNumber = null; - boolean hasValue = false; - - String tag; - int eventType = parser.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { - tag = parser.getName(); - if (!TextUtils.isEmpty(tag) && (tag.equalsIgnoreCase("usb-device"))) { - if (eventType == XmlPullParser.START_TAG) { - hasValue = true; - vendorId = getAttributeInteger(context, parser, null, "vendor-id", -1); - if (vendorId == -1) { - vendorId = getAttributeInteger(context, parser, null, "vendorId", -1); - if (vendorId == -1) - vendorId = getAttributeInteger(context, parser, null, "venderId", -1); - } - productId = getAttributeInteger(context, parser, null, "product-id", -1); - if (productId == -1) - productId = getAttributeInteger(context, parser, null, "productId", -1); - deviceClass = getAttributeInteger(context, parser, null, "class", -1); - deviceSubclass = getAttributeInteger(context, parser, null, "subclass", -1); - deviceProtocol = getAttributeInteger(context, parser, null, "protocol", -1); - manufacturerName = getAttributeString(context, parser, null, "manufacturer-name", null); - if (TextUtils.isEmpty(manufacturerName)) - manufacturerName = getAttributeString(context, parser, null, "manufacture", null); - productName = getAttributeString(context, parser, null, "product-name", null); - if (TextUtils.isEmpty(productName)) - productName = getAttributeString(context, parser, null, "product", null); - serialNumber = getAttributeString(context, parser, null, "serial-number", null); - if (TextUtils.isEmpty(serialNumber)) - serialNumber = getAttributeString(context, parser, null, "serial", null); - exclude = getAttributeBoolean(context, parser, null, "exclude", false); - } else if (eventType == XmlPullParser.END_TAG) { - if (hasValue) { - return new DeviceFilter(vendorId, productId, deviceClass, - deviceSubclass, deviceProtocol, manufacturerName, productName, - serialNumber, exclude); - } - } - } - eventType = parser.next(); - } - return null; - } - -/* public void write(XmlSerializer serializer) throws IOException { - serializer.startTag(null, "usb-device"); - if (mVendorId != -1) { - serializer - .attribute(null, "vendor-id", Integer.toString(mVendorId)); - } - if (mProductId != -1) { - serializer.attribute(null, "product-id", - Integer.toString(mProductId)); - } - if (mClass != -1) { - serializer.attribute(null, "class", Integer.toString(mClass)); - } - if (mSubclass != -1) { - serializer.attribute(null, "subclass", Integer.toString(mSubclass)); - } - if (mProtocol != -1) { - serializer.attribute(null, "protocol", Integer.toString(mProtocol)); - } - if (mManufacturerName != null) { - serializer.attribute(null, "manufacturer-name", mManufacturerName); - } - if (mProductName != null) { - serializer.attribute(null, "product-name", mProductName); - } - if (mSerialNumber != null) { - serializer.attribute(null, "serial-number", mSerialNumber); - } - serializer.attribute(null, "serial-number", Boolean.toString(isExclude)); - serializer.endTag(null, "usb-device"); - } */ - - /** - * 指定したクラス・サブクラス・プロトコルがこのDeviceFilterとマッチするかどうかを返す - * mExcludeフラグは別途#isExcludeか自前でチェックすること - * @param clasz - * @param subclass - * @param protocol - * @return - */ - private boolean matches(final int clasz, final int subclass, final int protocol) { - return ((mClass == -1 || clasz == mClass) - && (mSubclass == -1 || subclass == mSubclass) && (mProtocol == -1 || protocol == mProtocol)); - } - - /** - * 指定したUsbDeviceがこのDeviceFilterにマッチするかどうかを返す - * mExcludeフラグは別途#isExcludeか自前でチェックすること - * @param device - * @return - */ - public boolean matches(final UsbDevice device) { - if (mVendorId != -1 && device.getVendorId() != mVendorId) { - return false; - } - if (mProductId != -1 && device.getProductId() != mProductId) { - return false; - } -/* if (mManufacturerName != null && device.getManufacturerName() == null) - return false; - if (mProductName != null && device.getProductName() == null) - return false; - if (mSerialNumber != null && device.getSerialNumber() == null) - return false; - if (mManufacturerName != null && device.getManufacturerName() != null - && !mManufacturerName.equals(device.getManufacturerName())) - return false; - if (mProductName != null && device.getProductName() != null - && !mProductName.equals(device.getProductName())) - return false; - if (mSerialNumber != null && device.getSerialNumber() != null - && !mSerialNumber.equals(device.getSerialNumber())) - return false; */ - - // check device class/subclass/protocol - if (matches(device.getDeviceClass(), device.getDeviceSubclass(), device.getDeviceProtocol())) { - return true; - } - - // if device doesn't match, check the interfaces - final int count = device.getInterfaceCount(); - for (int i = 0; i < count; i++) { - final UsbInterface intf = device.getInterface(i); - if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(), intf.getInterfaceProtocol())) { - return true; - } - } - - return false; - } - - /** - * このDeviceFilterに一致してかつmExcludeがtrueならtrueを返す - * @param device - * @return - */ - public boolean isExclude(final UsbDevice device) { - return isExclude && matches(device); - } - - /** - * これって要らんかも, equalsでできる気が - * @param f - * @return - */ - public boolean matches(final DeviceFilter f) { - if (isExclude != f.isExclude) { - return false; - } - if (mVendorId != -1 && f.mVendorId != mVendorId) { - return false; - } - if (mProductId != -1 && f.mProductId != mProductId) { - return false; - } - if (f.mManufacturerName != null && mManufacturerName == null) { - return false; - } - if (f.mProductName != null && mProductName == null) { - return false; - } - if (f.mSerialNumber != null && mSerialNumber == null) { - return false; - } - if (mManufacturerName != null && f.mManufacturerName != null - && !mManufacturerName.equals(f.mManufacturerName)) { - return false; - } - if (mProductName != null && f.mProductName != null - && !mProductName.equals(f.mProductName)) { - return false; - } - if (mSerialNumber != null && f.mSerialNumber != null - && !mSerialNumber.equals(f.mSerialNumber)) { - return false; - } - - // check device class/subclass/protocol - return matches(f.mClass, f.mSubclass, f.mProtocol); - } - - @Override - public boolean equals(final Object obj) { - // can't compare if we have wildcard strings - if (mVendorId == -1 || mProductId == -1 || mClass == -1 - || mSubclass == -1 || mProtocol == -1) { - return false; - } - if (obj instanceof DeviceFilter) { - final DeviceFilter filter = (DeviceFilter) obj; - - if (filter.mVendorId != mVendorId - || filter.mProductId != mProductId - || filter.mClass != mClass || filter.mSubclass != mSubclass - || filter.mProtocol != mProtocol) { - return false; - } - if ((filter.mManufacturerName != null && mManufacturerName == null) - || (filter.mManufacturerName == null && mManufacturerName != null) - || (filter.mProductName != null && mProductName == null) - || (filter.mProductName == null && mProductName != null) - || (filter.mSerialNumber != null && mSerialNumber == null) - || (filter.mSerialNumber == null && mSerialNumber != null)) { - return false; - } - if ((filter.mManufacturerName != null && mManufacturerName != null && !mManufacturerName - .equals(filter.mManufacturerName)) - || (filter.mProductName != null && mProductName != null && !mProductName - .equals(filter.mProductName)) - || (filter.mSerialNumber != null && mSerialNumber != null && !mSerialNumber - .equals(filter.mSerialNumber))) { - return false; - } - return (filter.isExclude != isExclude); - } - if (obj instanceof UsbDevice) { - final UsbDevice device = (UsbDevice) obj; - if (isExclude - || (device.getVendorId() != mVendorId) - || (device.getProductId() != mProductId) - || (device.getDeviceClass() != mClass) - || (device.getDeviceSubclass() != mSubclass) - || (device.getDeviceProtocol() != mProtocol) ) { - return false; - } -/* if ((mManufacturerName != null && device.getManufacturerName() == null) - || (mManufacturerName == null && device - .getManufacturerName() != null) - || (mProductName != null && device.getProductName() == null) - || (mProductName == null && device.getProductName() != null) - || (mSerialNumber != null && device.getSerialNumber() == null) - || (mSerialNumber == null && device.getSerialNumber() != null)) { - return (false); - } */ -/* if ((device.getManufacturerName() != null && !mManufacturerName - .equals(device.getManufacturerName())) - || (device.getProductName() != null && !mProductName - .equals(device.getProductName())) - || (device.getSerialNumber() != null && !mSerialNumber - .equals(device.getSerialNumber()))) { - return (false); - } */ - return true; - } - return false; - } - - @Override - public int hashCode() { - return (((mVendorId << 16) | mProductId) ^ ((mClass << 16) - | (mSubclass << 8) | mProtocol)); - } - - @Override - public String toString() { - return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" - + mProductId + ",mClass=" + mClass + ",mSubclass=" + mSubclass - + ",mProtocol=" + mProtocol - + ",mManufacturerName=" + mManufacturerName - + ",mProductName=" + mProductName - + ",mSerialNumber=" + mSerialNumber - + ",isExclude=" + isExclude - + "]"; - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/IButtonCallback.java b/phenolib/src/main/java/com/serenegiant/usb/IButtonCallback.java deleted file mode 100644 index 4025085c..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/IButtonCallback.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.serenegiant.usb; - -public interface IButtonCallback { - void onButton(int button, int state); -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/IFrameCallback.java b/phenolib/src/main/java/com/serenegiant/usb/IFrameCallback.java deleted file mode 100644 index 9b77f728..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/IFrameCallback.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@com.com.serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usb; - -import java.nio.ByteBuffer; - -/** - * Callback interface for UVCCamera class - * If you need frame data as ByteBuffer, you can use this callback interface with UVCCamera#setFrameCallback - */ -public interface IFrameCallback { - /** - * This method is called from native library via JNI on the same thread as UVCCamera#startCapture. - * You can use both UVCCamera#startCapture and #setFrameCallback - * but it is better to use either for better performance. - * You can also pass pixel format type to UVCCamera#setFrameCallback for this method. - * Some frames may drops if this method takes a time. - * When you use some color format like NV21, this library never execute color space conversion, - * just execute pixel format conversion. If you want to get same result as on screen, please try to - * consider to get images via texture(SurfaceTexture) and read pixel buffer from it using OpenGL|ES2/3 - * instead of using IFrameCallback(this way is much efficient in most case than using IFrameCallback). - * @param frame this is direct ByteBuffer from JNI layer and you should handle it's byte order and limitation. - */ - public void onFrame(ByteBuffer frame); -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/IStatusCallback.java b/phenolib/src/main/java/com/serenegiant/usb/IStatusCallback.java deleted file mode 100644 index ad743204..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/IStatusCallback.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.serenegiant.usb; - -import java.nio.ByteBuffer; - -public interface IStatusCallback { - void onStatus(int statusClass, int event, int selector, int statusAttribute, ByteBuffer data); -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/Size.java b/phenolib/src/main/java/com/serenegiant/usb/Size.java deleted file mode 100644 index 7b445cb6..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/Size.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@com.com.serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usb; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Locale; - -public class Size implements Parcelable { - // - /** - * native側のuvc_raw_format_tの値, こっちは主にlibuvc用 - * 9999 is still image - */ - public int type; - /** - * native側のraw_frame_tの値, androusb用, - * libuvcは対応していない - */ - public int frame_type; - public int index; - public int width; - public int height; - public int frameIntervalType; - public int frameIntervalIndex; - public int[] intervals; - // ここ以下はframeIntervalTypeとintervalsから#updateFrameRateで計算する - public float[] fps; - private String frameRates; - - /** - * コンストラクタ - * @param _type native側のraw_format_tの値, ただし9999は静止画 - * @param _frame_type native側のraw_frame_tの値 - * @param _index - * @param _width - * @param _height - */ - public Size(final int _type, final int _frame_type, final int _index, final int _width, final int _height) { - type = _type; - frame_type = _frame_type; - index = _index; - width = _width; - height = _height; - frameIntervalType = -1; - frameIntervalIndex = 0; - intervals = null; - updateFrameRate(); - } - - /** - * コンストラクタ - * @param _type native側のraw_format_tの値, ただし9999は静止画 - * @param _frame_type native側のraw_frame_tの値 - * @param _index - * @param _width - * @param _height - * @param _min_intervals - * @param _max_intervals - */ - public Size(final int _type, final int _frame_type, final int _index, final int _width, final int _height, final int _min_intervals, final int _max_intervals, final int _step) { - type = _type; - frame_type = _frame_type; - index = _index; - width = _width; - height = _height; - frameIntervalType = 0; - frameIntervalIndex = 0; - intervals = new int[3]; - intervals[0] = _min_intervals; - intervals[1] = _max_intervals; - intervals[2] = _step; - updateFrameRate(); - } - - /** - * コンストラクタ - * @param _type native側のraw_format_tの値, ただし9999は静止画 - * @param _frame_type native側のraw_frame_tの値 - * @param _index - * @param _width - * @param _height - * @param _intervals - */ - public Size(final int _type, final int _frame_type, final int _index, final int _width, final int _height, final int[] _intervals) { - type = _type; - frame_type = _frame_type; - index = _index; - width = _width; - height = _height; - final int n = _intervals != null ? _intervals.length : -1; - if (n > 0) { - frameIntervalType = n; - intervals = new int[n]; - System.arraycopy(_intervals, 0, intervals, 0, n); - } else { - frameIntervalType = -1; - intervals = null; - } - frameIntervalIndex = 0; - updateFrameRate(); - } - - /** - * コピーコンストラクタ - * @param other - */ - public Size(final Size other) { - type = other.type; - frame_type = other.frame_type; - index = other.index; - width = other.width; - height = other.height; - frameIntervalType = other.frameIntervalType; - frameIntervalIndex = other.frameIntervalIndex; - final int n = other.intervals != null ? other.intervals.length : -1; - if (n > 0) { - intervals = new int[n]; - System.arraycopy(other.intervals, 0, intervals, 0, n); - } else { - intervals = null; - } - updateFrameRate(); - } - - private Size(final Parcel source) { - // 読み取り順はwriteToParcelでの書き込み順と同じでないとダメ - type = source.readInt(); - frame_type = source.readInt(); - index = source.readInt(); - width = source.readInt(); - height = source.readInt(); - frameIntervalType = source.readInt(); - frameIntervalIndex = source.readInt(); - if (frameIntervalType >= 0) { - if (frameIntervalType > 0) { - intervals = new int[frameIntervalType]; - } else { - intervals = new int[3]; - } - source.readIntArray(intervals); - } else { - intervals = null; - } - updateFrameRate(); - } - - public Size set(final Size other) { - if (other != null) { - type = other.type; - frame_type = other.frame_type; - index = other.index; - width = other.width; - height = other.height; - frameIntervalType = other.frameIntervalType; - frameIntervalIndex = other.frameIntervalIndex; - final int n = other.intervals != null ? other.intervals.length : -1; - if (n > 0) { - intervals = new int[n]; - System.arraycopy(other.intervals, 0, intervals, 0, n); - } else { - intervals = null; - } - updateFrameRate(); - } - return this; - } - - public float getCurrentFrameRate() throws IllegalStateException { - final int n = fps != null ? fps.length : 0; - if ((frameIntervalIndex >= 0) && (frameIntervalIndex < n)) { - return fps[frameIntervalIndex]; - } - throw new IllegalStateException("unknown frame rate or not ready"); - } - - public void setCurrentFrameRate(final float frameRate) { - // 一番近いのを選ぶ - int index = -1; - final int n = fps != null ? fps.length : 0; - for (int i = 0; i < n; i++) { - if (fps[i] <= frameRate) { - index = i; - break; - } - } - frameIntervalIndex = index; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(final Parcel dest, final int flags) { - dest.writeInt(type); - dest.writeInt(frame_type); - dest.writeInt(index); - dest.writeInt(width); - dest.writeInt(height); - dest.writeInt(frameIntervalType); - dest.writeInt(frameIntervalIndex); - if (intervals != null) { - dest.writeIntArray(intervals); - } - } - - public void updateFrameRate() { - final int n = frameIntervalType; - if (n > 0) { - fps = new float[n]; - for (int i = 0; i < n; i++) { - final float _fps = fps[i] = 10000000.0f / intervals[i]; - } - } else if (n == 0) { - try { - final int min = Math.min(intervals[0], intervals[1]); - final int max = Math.max(intervals[0], intervals[1]); - final int step = intervals[2]; - if (step > 0) { - int m = 0; - for (int i = min; i <= max; i+= step) { m++; } - fps = new float[m]; - m = 0; - for (int i = min; i <= max; i+= step) { - final float _fps = fps[m++] = 10000000.0f / i; - } - } else { - final float max_fps = 10000000.0f / min; - int m = 0; - for (float fps = 10000000.0f / min; fps <= max_fps; fps += 1.0f) { m++; } - fps = new float[m]; - m = 0; - for (float fps = 10000000.0f / min; fps <= max_fps; fps += 1.0f) { - this.fps[m++] = fps; - } - } - } catch (final Exception e) { - // ignore, なんでかminとmaxが0になってるんちゃうかな - fps = null; - } - } - final int m = fps != null ? fps.length : 0; - final StringBuilder sb = new StringBuilder(); - sb.append("["); - for (int i = 0; i < m; i++) { - sb.append(String.format(Locale.US, "%4.1f", fps[i])); - if (i < m-1) { - sb.append(","); - } - } - sb.append("]"); - frameRates = sb.toString(); - if (frameIntervalIndex > m) { - frameIntervalIndex = 0; - } - } - - @Override - public String toString() { - float frame_rate = 0.0f; - try { - frame_rate = getCurrentFrameRate(); - } catch (final Exception e) { - } - return String.format(Locale.US, "Size(%dx%d@%4.1f,type:%d,frame:%d,index:%d,%s)", width, height, frame_rate, type, frame_type, index, frameRates); - } - - public static final Creator CREATOR = new Creator() { - @Override - public Size createFromParcel(final Parcel source) { - return new Size(source); - } - @Override - public Size[] newArray(final int size) { - return new Size[size]; - } - }; -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/USBMonitor.java b/phenolib/src/main/java/com/serenegiant/usb/USBMonitor.java deleted file mode 100644 index b4429036..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/USBMonitor.java +++ /dev/null @@ -1,1376 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usb; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -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.Environment; -import android.os.Handler; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseArray; - -import com.serenegiant.utils.BuildCheck; -import com.serenegiant.utils.HandlerThreadHandler; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; - -public final class USBMonitor { - - private static final boolean DEBUG = false; // TODO set false on production - private static final String TAG = "USBMonitor"; - - private static final String ACTION_USB_PERMISSION_BASE = "com.serenegiant.USB_PERMISSION."; - private final String ACTION_USB_PERMISSION = ACTION_USB_PERMISSION_BASE + hashCode(); - - public static final String ACTION_USB_DEVICE_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED"; - - /** - * openしているUsbControlBlock - */ - private final ConcurrentHashMap mCtrlBlocks = new ConcurrentHashMap(); - private final SparseArray> mHasPermissions = new SparseArray>(); - - private final WeakReference mWeakContext; - private final UsbManager mUsbManager; - private final OnDeviceConnectListener mOnDeviceConnectListener; - private PendingIntent mPermissionIntent = null; - private List mDeviceFilters = new ArrayList(); - - /** - * コールバックをワーカースレッドで呼び出すためのハンドラー - */ - private final Handler mAsyncHandler; - private volatile boolean destroyed; - /** - * USB機器の状態変更時のコールバックリスナー - */ - public interface OnDeviceConnectListener { - /** - * called when device attached - * @param device - */ - public void onAttach(UsbDevice device); - /** - * called when device dettach(after onDisconnect) - * @param device - */ - public void onDetach(UsbDevice device); - /** - * called after device opend - * @param device - * @param ctrlBlock - * @param createNew - */ - public void onConnect(UsbDevice device, UsbControlBlock ctrlBlock, boolean createNew); - /** - * called when USB device removed or its power off (this callback is called after device closing) - * @param device - * @param ctrlBlock - */ - public void onDisconnect(UsbDevice device, UsbControlBlock ctrlBlock); - /** - * called when canceled or could not get permission from user - * @param device - */ - public void onCancel(UsbDevice device); - } - - public USBMonitor(final Context context, final OnDeviceConnectListener listener) { - if (DEBUG) Log.v(TAG, "USBMonitor:Constructor"); - if (listener == null) - throw new IllegalArgumentException("OnDeviceConnectListener should not null."); - mWeakContext = new WeakReference(context); - mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE); - mOnDeviceConnectListener = listener; - mAsyncHandler = HandlerThreadHandler.createHandler(TAG); - destroyed = false; - if (DEBUG) Log.v(TAG, "USBMonitor:mUsbManager=" + mUsbManager); - } - - /** - * Release all related resources, - * never reuse again - */ - public void destroy() { - if (DEBUG) Log.i(TAG, "destroy:"); - unregister(); - if (!destroyed) { - destroyed = true; - // モニターしているUSB機器を全てcloseする - final Set keys = mCtrlBlocks.keySet(); - if (keys != null) { - UsbControlBlock ctrlBlock; - try { - for (final UsbDevice key: keys) { - ctrlBlock = mCtrlBlocks.remove(key); - if (ctrlBlock != null) { - ctrlBlock.close(); - } - } - } catch (final Exception e) { - Log.e(TAG, "destroy:", e); - } - } - mCtrlBlocks.clear(); - try { - mAsyncHandler.getLooper().quit(); - } catch (final Exception e) { - Log.e(TAG, "destroy:", e); - } - } - } - - /** - * register BroadcastReceiver to monitor USB events - * @throws IllegalStateException - */ - public synchronized void register() throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - if (mPermissionIntent == null) { - if (DEBUG) Log.i(TAG, "register:"); - final Context context = mWeakContext.get(); - if (context != null) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0); - } else { - mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE); - } - final IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); - // ACTION_USB_DEVICE_ATTACHED never comes on some devices so it should not be added here - filter.addAction(ACTION_USB_DEVICE_ATTACHED); - filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - context.registerReceiver(mUsbReceiver, filter, Context.RECEIVER_EXPORTED); - } else { - context.registerReceiver(mUsbReceiver, filter); - } - } - // start connection check - mDeviceCounts = 0; - mAsyncHandler.postDelayed(mDeviceCheckRunnable, 1000); - } - } - - /** - * unregister BroadcastReceiver - * @throws IllegalStateException - */ - public synchronized void unregister() throws IllegalStateException { - // 接続チェック用Runnableを削除 - mDeviceCounts = 0; - if (!destroyed) { - mAsyncHandler.removeCallbacks(mDeviceCheckRunnable); - } - if (mPermissionIntent != null) { -// if (DEBUG) Log.i(TAG, "unregister:"); - final Context context = mWeakContext.get(); - try { - if (context != null) { - context.unregisterReceiver(mUsbReceiver); - } - } catch (final Exception e) { - Log.w(TAG, e); - } - mPermissionIntent = null; - } - } - - public synchronized boolean isRegistered() { - return !destroyed && (mPermissionIntent != null); - } - - /** - * set device filter - * @param filter - * @throws IllegalStateException - */ - public void setDeviceFilter(final DeviceFilter filter) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - mDeviceFilters.clear(); - mDeviceFilters.add(filter); - } - - /** - * デバイスフィルターを追加 - * @param filter - * @throws IllegalStateException - */ - public void addDeviceFilter(final DeviceFilter filter) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - mDeviceFilters.add(filter); - } - - /** - * デバイスフィルターを削除 - * @param filter - * @throws IllegalStateException - */ - public void removeDeviceFilter(final DeviceFilter filter) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - mDeviceFilters.remove(filter); - } - - /** - * set device filters - * @param filters - * @throws IllegalStateException - */ - public void setDeviceFilter(final List filters) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - mDeviceFilters.clear(); - mDeviceFilters.addAll(filters); - } - - /** - * add device filters - * @param filters - * @throws IllegalStateException - */ - public void addDeviceFilter(final List filters) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - mDeviceFilters.addAll(filters); - } - - /** - * remove device filters - * @param filters - */ - public void removeDeviceFilter(final List filters) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - mDeviceFilters.removeAll(filters); - } - - /** - * return the number of connected USB devices that matched device filter - * @return - * @throws IllegalStateException - */ - public int getDeviceCount() throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - return getDeviceList().size(); - } - - /** - * return device list, return empty list if no device matched - * @return - * @throws IllegalStateException - */ - public List getDeviceList() throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - return getDeviceList(mDeviceFilters); - } - - /** - * return device list, return empty list if no device matched - * @param filters - * @return - * @throws IllegalStateException - */ - public List getDeviceList(final List filters) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - // get detected devices - final HashMap deviceList = mUsbManager.getDeviceList(); - final List result = new ArrayList(); - if (deviceList != null) { - if ((filters == null) || filters.isEmpty()) { - result.addAll(deviceList.values()); - } else { - for (final UsbDevice device: deviceList.values() ) { - // match devices - for (final DeviceFilter filter: filters) { - if ((filter != null) && filter.matches(device) || (filter != null && filter.mSubclass == device.getDeviceSubclass())) { - // when filter matches - if (!filter.isExclude) { - result.add(device); - } - break; - } - } - } - } - } - return result; - } - - /** - * return device list, return empty list if no device matched - * @param filter - * @return - * @throws IllegalStateException - */ - public List getDeviceList(final DeviceFilter filter) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - final HashMap deviceList = mUsbManager.getDeviceList(); - final List result = new ArrayList(); - if (deviceList != null) { - for (final UsbDevice device: deviceList.values() ) { - if ((filter == null) || (filter.matches(device) && !filter.isExclude)) { - result.add(device); - } - } - } - return result; - } - - /** - * get USB device list, without filter - * @return - * @throws IllegalStateException - */ - public Iterator getDevices() throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - Iterator iterator = null; - final HashMap list = mUsbManager.getDeviceList(); - if (list != null) - iterator = list.values().iterator(); - return iterator; - } - - /** - * output device list to LogCat - */ - public final void dumpDevices() { - final HashMap list = mUsbManager.getDeviceList(); - if (list != null) { - final Set keys = list.keySet(); - if (keys != null && keys.size() > 0) { - final StringBuilder sb = new StringBuilder(); - for (final String key: keys) { - final UsbDevice device = list.get(key); - final int num_interface = device != null ? device.getInterfaceCount() : 0; - sb.setLength(0); - for (int i = 0; i < num_interface; i++) { - sb.append(String.format(Locale.US, "interface%d:%s", i, device.getInterface(i).toString())); - } - Log.i(TAG, "key=" + key + ":" + device + ":" + sb.toString()); - } - } else { - Log.i(TAG, "no device"); - } - } else { - Log.i(TAG, "no device"); - } - } - - /** - * return whether the specific Usb device has permission - * @param device - * @return true: 指定したUsbDeviceにパーミッションがある - * @throws IllegalStateException - */ - public final boolean hasPermission(final UsbDevice device) throws IllegalStateException { - if (destroyed) throw new IllegalStateException("already destroyed"); - return updatePermission(device, device != null && mUsbManager.hasPermission(device)); - } - - /** - * 内部で保持しているパーミッション状態を更新 - * @param device - * @param hasPermission - * @return hasPermission - */ - private boolean updatePermission(final UsbDevice device, final boolean hasPermission) { - // fix api >= 29, permission SecurityException - try { - final int deviceKey = getDeviceKey(device, true); - synchronized (mHasPermissions) { - if (hasPermission) { - if (mHasPermissions.get(deviceKey) == null) { - mHasPermissions.put(deviceKey, new WeakReference(device)); - } - } else { - mHasPermissions.remove(deviceKey); - } - } - } catch (SecurityException e) { - Log.w("jiangdg", e.getLocalizedMessage()); - } - - return hasPermission; - } - - /** - * request permission to access to USB device - * @param device - * @return true if fail to request permission - */ - public synchronized boolean requestPermission(final UsbDevice device) { -// if (DEBUG) Log.v(TAG, "requestPermission:device=" + device); - boolean result = false; - if (isRegistered()) { - if (device != null) { - if (mUsbManager.hasPermission(device)) { - // call onConnect if app already has permission - processConnect(device); - } else { - try { - // パーミッションがなければ要求する - mUsbManager.requestPermission(device, mPermissionIntent); - } catch (final Exception e) { - // Android5.1.xのGALAXY系でandroid.permission.sec.MDM_APP_MGMTという意味不明の例外生成するみたい - Log.w(TAG, e); - processCancel(device); - result = true; - } - } - } else { - processCancel(device); - result = true; - } - } else { - processCancel(device); - result = true; - } - return result; - } - - /** - * 指定したUsbDeviceã‚’openする - * @param device - * @return - * @throws SecurityException パーミッションがなければSecurityExceptionを投げる - */ - public UsbControlBlock openDevice(final UsbDevice device) throws SecurityException { - if (hasPermission(device)) { - UsbControlBlock result = mCtrlBlocks.get(device); - if (result == null) { - result = new UsbControlBlock(USBMonitor.this, device); // この中でopenDeviceする - mCtrlBlocks.put(device, result); - } - return result; - } else { - throw new SecurityException("has no permission"); - } - } - - /** - * BroadcastReceiver for USB permission - */ - private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - - @Override - public void onReceive(final Context context, final Intent intent) { - if (destroyed) return; - final String action = intent.getAction(); - if (ACTION_USB_PERMISSION.equals(action)) { - // when received the result of requesting USB permission - synchronized (USBMonitor.this) { - final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { - if (device != null) { - // get permission, call onConnect - processConnect(device); - } - } else { - // failed to get permission - processCancel(device); - } - } - } else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { - final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - updatePermission(device, hasPermission(device)); - processAttach(device); - } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { - // when device removed - final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - if (device != null) { - UsbControlBlock ctrlBlock = mCtrlBlocks.remove(device); - if (ctrlBlock != null) { - // cleanup - ctrlBlock.close(); - } - mDeviceCounts = 0; - processDettach(device); - } - } - } - }; - - /** number of connected & detected devices */ - private volatile int mDeviceCounts = 0; - /** - * periodically check connected devices and if it changed, call onAttach - */ - private final Runnable mDeviceCheckRunnable = new Runnable() { - @Override - public void run() { - if (destroyed) return; - final List devices = getDeviceList(); - final int n = devices.size(); - final int hasPermissionCounts; - final int m; - synchronized (mHasPermissions) { - hasPermissionCounts = mHasPermissions.size(); - mHasPermissions.clear(); - for (final UsbDevice device: devices) { - hasPermission(device); - } - m = mHasPermissions.size(); - } - if ((n > mDeviceCounts) || (m > hasPermissionCounts)) { - mDeviceCounts = n; - if (mOnDeviceConnectListener != null) { - for (int i = 0; i < n; i++) { - final UsbDevice device = devices.get(i); - mAsyncHandler.post(new Runnable() { - @Override - public void run() { - mOnDeviceConnectListener.onAttach(device); - } - }); - } - } - } - mAsyncHandler.postDelayed(this, 2000); // confirm every 2 seconds - } - }; - - /** - * open specific USB device - * @param device - */ - private final void processConnect(final UsbDevice device) { - if (destroyed) return; - updatePermission(device, true); - mAsyncHandler.post(new Runnable() { - @Override - public void run() { - if (DEBUG) Log.v(TAG, "processConnect:device=" + device); - UsbControlBlock ctrlBlock; - final boolean createNew; - ctrlBlock = mCtrlBlocks.get(device); - if (ctrlBlock == null) { - ctrlBlock = new UsbControlBlock(USBMonitor.this, device); - mCtrlBlocks.put(device, ctrlBlock); - createNew = true; - } else { - createNew = false; - } - if (mOnDeviceConnectListener != null) { - mOnDeviceConnectListener.onConnect(device, ctrlBlock, createNew); - } - } - }); - } - - private final void processCancel(final UsbDevice device) { - if (destroyed) return; - if (DEBUG) Log.v(TAG, "processCancel:"); - updatePermission(device, false); - if (mOnDeviceConnectListener != null) { - mAsyncHandler.post(new Runnable() { - @Override - public void run() { - mOnDeviceConnectListener.onCancel(device); - } - }); - } - } - - private final void processAttach(final UsbDevice device) { - if (destroyed) return; - if (DEBUG) Log.v(TAG, "processAttach:"); - if (mOnDeviceConnectListener != null) { - mAsyncHandler.post(new Runnable() { - @Override - public void run() { - mOnDeviceConnectListener.onAttach(device); - } - }); - } - } - - private final void processDettach(final UsbDevice device) { - if (destroyed) return; - if (DEBUG) Log.v(TAG, "processDettach:"); - if (mOnDeviceConnectListener != null) { - mAsyncHandler.post(new Runnable() { - @Override - public void run() { - mOnDeviceConnectListener.onDetach(device); - } - }); - } - } - - /** - * USB機器毎の設定保存用にデバイスキー名を生成する。 - * ベンダーID, プロダクトID, デバイスクラス, デバイスサブクラス, デバイスプロトコルから生成 - * 同種の製品だと同じキー名になるので注意 - * @param device nullなら空文字列を返す - * @return - */ - public static final String getDeviceKeyName(final UsbDevice device) { - return getDeviceKeyName(device, null, false); - } - - /** - * USB機器毎の設定保存用にデバイスキー名を生成する。 - * useNewAPI=falseで同種の製品だと同じデバイスキーになるので注意 - * @param device - * @param useNewAPI - * @return - */ - public static final String getDeviceKeyName(final UsbDevice device, final boolean useNewAPI) { - return getDeviceKeyName(device, null, useNewAPI); - } - /** - * USB機器毎の設定保存用にデバイスキー名を生成する。この機器名をHashMapのキーにする - * UsbDeviceがopenしている時のみ有効 - * ベンダーID, プロダクトID, デバイスクラス, デバイスサブクラス, デバイスプロトコルから生成 - * serialがnullや空文字でなければserialを含めたデバイスキー名を生成する - * useNewAPI=trueでAPIレベルを満たしていればマニュファクチャ名, バージョン, コンフィギュレーションカウントも使う - * @param device nullなら空文字列を返す - * @param serial UsbDeviceConnection#getSerialで取得したシリアル番号を渡す, nullでuseNewAPI=trueでAPI>=21なら内部で取得 - * @param useNewAPI API>=21またはAPI>=23のみで使用可能なメソッドも使用する(ただし機器によってはnullが返ってくるので有効かどうかは機器による) - * @return - */ - @SuppressLint("NewApi") - public static final String getDeviceKeyName(final UsbDevice device, final String serial, final boolean useNewAPI) { - if (device == null) return ""; - final StringBuilder sb = new StringBuilder(); - sb.append(device.getVendorId()); sb.append("#"); // API >= 12 - sb.append(device.getProductId()); sb.append("#"); // API >= 12 - sb.append(device.getDeviceClass()); sb.append("#"); // API >= 12 - sb.append(device.getDeviceSubclass()); sb.append("#"); // API >= 12 - sb.append(device.getDeviceProtocol()); // API >= 12 - if (!TextUtils.isEmpty(serial)) { - sb.append("#"); sb.append(serial); - } - if (useNewAPI && BuildCheck.isAndroid5()) { - sb.append("#"); - if (TextUtils.isEmpty(serial)) { - try { sb.append(device.getSerialNumber()); sb.append("#"); } // API >= 21 & targetSdkVersion has to be <= 28 - catch(SecurityException ignore) {} - } - sb.append(device.getManufacturerName()); sb.append("#"); // API >= 21 - sb.append(device.getConfigurationCount()); sb.append("#"); // API >= 21 - if (BuildCheck.isMarshmallow()) { - sb.append(device.getVersion()); sb.append("#"); // API >= 23 - } - } -// if (DEBUG) Log.v(TAG, "getDeviceKeyName:" + sb.toString()); - return sb.toString(); - } - - /** - * デバイスキーを整数として取得 - * getDeviceKeyNameで得られる文字列のhasCodeを取得 - * ベンダーID, プロダクトID, デバイスクラス, デバイスサブクラス, デバイスプロトコルから生成 - * 同種の製品だと同じデバイスキーになるので注意 - * @param device nullなら0を返す - * @return - */ - public static final int getDeviceKey(final UsbDevice device) { - return device != null ? getDeviceKeyName(device, null, false).hashCode() : 0; - } - - /** - * デバイスキーを整数として取得 - * getDeviceKeyNameで得られる文字列のhasCodeを取得 - * useNewAPI=falseで同種の製品だと同じデバイスキーになるので注意 - * @param device - * @param useNewAPI - * @return - */ - public static final int getDeviceKey(final UsbDevice device, final boolean useNewAPI) { - return device != null ? getDeviceKeyName(device, null, useNewAPI).hashCode() : 0; - } - - /** - * デバイスキーを整数として取得 - * getDeviceKeyNameで得られる文字列のhasCodeを取得 - * serialがnullでuseNewAPI=falseで同種の製品だと同じデバイスキーになるので注意 - * @param device nullなら0を返す - * @param serial UsbDeviceConnection#getSerialで取得したシリアル番号を渡す, nullでuseNewAPI=trueでAPI>=21なら内部で取得 - * @param useNewAPI API>=21またはAPI>=23のみで使用可能なメソッドも使用する(ただし機器によってはnullが返ってくるので有効かどうかは機器による) - * @return - */ - public static final int getDeviceKey(final UsbDevice device, final String serial, final boolean useNewAPI) { - return device != null ? getDeviceKeyName(device, serial, useNewAPI).hashCode() : 0; - } - - public static class UsbDeviceInfo { - public String usb_version; - public String manufacturer; - public String product; - public String version; - public String serial; - - private void clear() { - usb_version = manufacturer = product = version = serial = null; - } - - @Override - public String toString() { - return String.format("UsbDevice:usb_version=%s,manufacturer=%s,product=%s,version=%s,serial=%s", - usb_version != null ? usb_version : "", - manufacturer != null ? manufacturer : "", - product != null ? product : "", - version != null ? version : "", - serial != null ? serial : ""); - } - } - - private static final int USB_DIR_OUT = 0; - private static final int USB_DIR_IN = 0x80; - private static final int USB_TYPE_MASK = (0x03 << 5); - private static final int USB_TYPE_STANDARD = (0x00 << 5); - private static final int USB_TYPE_CLASS = (0x01 << 5); - private static final int USB_TYPE_VENDOR = (0x02 << 5); - private static final int USB_TYPE_RESERVED = (0x03 << 5); - private static final int USB_RECIP_MASK = 0x1f; - private static final int USB_RECIP_DEVICE = 0x00; - private static final int USB_RECIP_INTERFACE = 0x01; - private static final int USB_RECIP_ENDPOINT = 0x02; - private static final int USB_RECIP_OTHER = 0x03; - private static final int USB_RECIP_PORT = 0x04; - private static final int USB_RECIP_RPIPE = 0x05; - private static final int USB_REQ_GET_STATUS = 0x00; - private static final int USB_REQ_CLEAR_FEATURE = 0x01; - private static final int USB_REQ_SET_FEATURE = 0x03; - private static final int USB_REQ_SET_ADDRESS = 0x05; - private static final int USB_REQ_GET_DESCRIPTOR = 0x06; - private static final int USB_REQ_SET_DESCRIPTOR = 0x07; - private static final int USB_REQ_GET_CONFIGURATION = 0x08; - private static final int USB_REQ_SET_CONFIGURATION = 0x09; - private static final int USB_REQ_GET_INTERFACE = 0x0A; - private static final int USB_REQ_SET_INTERFACE = 0x0B; - private static final int USB_REQ_SYNCH_FRAME = 0x0C; - private static final int USB_REQ_SET_SEL = 0x30; - private static final int USB_REQ_SET_ISOCH_DELAY = 0x31; - private static final int USB_REQ_SET_ENCRYPTION = 0x0D; - private static final int USB_REQ_GET_ENCRYPTION = 0x0E; - private static final int USB_REQ_RPIPE_ABORT = 0x0E; - private static final int USB_REQ_SET_HANDSHAKE = 0x0F; - private static final int USB_REQ_RPIPE_RESET = 0x0F; - private static final int USB_REQ_GET_HANDSHAKE = 0x10; - private static final int USB_REQ_SET_CONNECTION = 0x11; - private static final int USB_REQ_SET_SECURITY_DATA = 0x12; - private static final int USB_REQ_GET_SECURITY_DATA = 0x13; - private static final int USB_REQ_SET_WUSB_DATA = 0x14; - private static final int USB_REQ_LOOPBACK_DATA_WRITE = 0x15; - private static final int USB_REQ_LOOPBACK_DATA_READ = 0x16; - private static final int USB_REQ_SET_INTERFACE_DS = 0x17; - - private static final int USB_REQ_STANDARD_DEVICE_SET = (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE); // 0x10 - private static final int USB_REQ_STANDARD_DEVICE_GET = (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE); // 0x90 - private static final int USB_REQ_STANDARD_INTERFACE_SET = (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE); // 0x11 - private static final int USB_REQ_STANDARD_INTERFACE_GET = (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE); // 0x91 - private static final int USB_REQ_STANDARD_ENDPOINT_SET = (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT); // 0x12 - private static final int USB_REQ_STANDARD_ENDPOINT_GET = (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT); // 0x92 - - private static final int USB_REQ_CS_DEVICE_SET = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE); // 0x20 - private static final int USB_REQ_CS_DEVICE_GET = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE); // 0xa0 - private static final int USB_REQ_CS_INTERFACE_SET = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); // 0x21 - private static final int USB_REQ_CS_INTERFACE_GET = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); // 0xa1 - private static final int USB_REQ_CS_ENDPOINT_SET = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT); // 0x22 - private static final int USB_REQ_CS_ENDPOINT_GET = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT); // 0xa2 - - private static final int USB_REQ_VENDER_DEVICE_SET = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE); // 0x40 - private static final int USB_REQ_VENDER_DEVICE_GET = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE); // 0xc0 - private static final int USB_REQ_VENDER_INTERFACE_SET = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); // 0x41 - private static final int USB_REQ_VENDER_INTERFACE_GET = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); // 0xc1 - private static final int USB_REQ_VENDER_ENDPOINT_SET = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT); // 0x42 - private static final int USB_REQ_VENDER_ENDPOINT_GET = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT); // 0xc2 - - private static final int USB_DT_DEVICE = 0x01; - private static final int USB_DT_CONFIG = 0x02; - private static final int USB_DT_STRING = 0x03; - private static final int USB_DT_INTERFACE = 0x04; - private static final int USB_DT_ENDPOINT = 0x05; - private static final int USB_DT_DEVICE_QUALIFIER = 0x06; - private static final int USB_DT_OTHER_SPEED_CONFIG = 0x07; - private static final int USB_DT_INTERFACE_POWER = 0x08; - private static final int USB_DT_OTG = 0x09; - private static final int USB_DT_DEBUG = 0x0a; - private static final int USB_DT_INTERFACE_ASSOCIATION = 0x0b; - private static final int USB_DT_SECURITY = 0x0c; - private static final int USB_DT_KEY = 0x0d; - private static final int USB_DT_ENCRYPTION_TYPE = 0x0e; - private static final int USB_DT_BOS = 0x0f; - private static final int USB_DT_DEVICE_CAPABILITY = 0x10; - private static final int USB_DT_WIRELESS_ENDPOINT_COMP = 0x11; - private static final int USB_DT_WIRE_ADAPTER = 0x21; - private static final int USB_DT_RPIPE = 0x22; - private static final int USB_DT_CS_RADIO_CONTROL = 0x23; - private static final int USB_DT_PIPE_USAGE = 0x24; - private static final int USB_DT_SS_ENDPOINT_COMP = 0x30; - private static final int USB_DT_CS_DEVICE = (USB_TYPE_CLASS | USB_DT_DEVICE); - private static final int USB_DT_CS_CONFIG = (USB_TYPE_CLASS | USB_DT_CONFIG); - private static final int USB_DT_CS_STRING = (USB_TYPE_CLASS | USB_DT_STRING); - private static final int USB_DT_CS_INTERFACE = (USB_TYPE_CLASS | USB_DT_INTERFACE); - private static final int USB_DT_CS_ENDPOINT = (USB_TYPE_CLASS | USB_DT_ENDPOINT); - private static final int USB_DT_DEVICE_SIZE = 18; - - /** - * 指定したIDのStringディスクリプタから文字列を取得する。取得できなければnull - * @param connection - * @param id - * @param languageCount - * @param languages - * @return - */ - private static String getString(final UsbDeviceConnection connection, final int id, final int languageCount, final byte[] languages) { - final byte[] work = new byte[256]; - String result = null; - for (int i = 1; i <= languageCount; i++) { - int ret = connection.controlTransfer( - USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE - USB_REQ_GET_DESCRIPTOR, - (USB_DT_STRING << 8) | id, languages[i], work, 256, 0); - if ((ret > 2) && (work[0] == ret) && (work[1] == USB_DT_STRING)) { - // skip first two bytes(bLength & bDescriptorType), and copy the rest to the string - try { - result = new String(work, 2, ret - 2, "UTF-16LE"); - if (!"Љ".equals(result)) { // 変なゴミが返ってくる時がある - break; - } else { - result = null; - } - } catch (final UnsupportedEncodingException e) { - // ignore - } - } - } - return result; - } - - /** - * ベンダー名・製品名・バージョン・シリアルを取得する - * @param device - * @return - */ - public UsbDeviceInfo getDeviceInfo(final UsbDevice device) { - return updateDeviceInfo(mUsbManager, device, null); - } - - /** - * ベンダー名・製品名・バージョン・シリアルを取得する - * #updateDeviceInfo(final UsbManager, final UsbDevice, final UsbDeviceInfo)のヘルパーメソッド - * @param context - * @param device - * @return - */ - public static UsbDeviceInfo getDeviceInfo(final Context context, final UsbDevice device) { - return updateDeviceInfo((UsbManager)context.getSystemService(Context.USB_SERVICE), device, new UsbDeviceInfo()); - } - - /** - * ベンダー名・製品名・バージョン・シリアルを取得する - * @param manager - * @param device - * @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(); - - if (device != null) { - if (BuildCheck.isLollipop()) { - info.manufacturer = device.getManufacturerName(); - info.product = device.getProductName(); - info.serial = device.getSerialNumber(); - } - if (BuildCheck.isMarshmallow()) { - info.usb_version = device.getVersion(); - } - 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)) { - info.usb_version = String.format("%x.%02x", ((int)desc[3] & 0xff), ((int)desc[2] & 0xff)); - } - if (TextUtils.isEmpty(info.version)) { - info.version = String.format("%x.%02x", ((int)desc[13] & 0xff), ((int)desc[12] & 0xff)); - } - if (TextUtils.isEmpty(info.serial)) { - info.serial = connection.getSerial(); - } - - final byte[] languages = new byte[256]; - int languageCount = 0; - // controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout) - try { - int result = connection.controlTransfer( - USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE - USB_REQ_GET_DESCRIPTOR, - (USB_DT_STRING << 8) | 0, 0, languages, 256, 0); - if (result > 0) { - languageCount = (result - 2) / 2; - } - if (languageCount > 0) { - if (TextUtils.isEmpty(info.manufacturer)) { - info.manufacturer = getString(connection, desc[14], languageCount, languages); - } - if (TextUtils.isEmpty(info.product)) { - info.product = getString(connection, desc[15], languageCount, languages); - } - if (TextUtils.isEmpty(info.serial)) { - info.serial = getString(connection, desc[16], languageCount, languages); - } - } - } finally { - connection.close(); - } - } - if (TextUtils.isEmpty(info.manufacturer)) { - info.manufacturer = USBVendorId.vendorName(device.getVendorId()); - } - if (TextUtils.isEmpty(info.manufacturer)) { - info.manufacturer = String.format("%04x", device.getVendorId()); - } - if (TextUtils.isEmpty(info.product)) { - info.product = String.format("%04x", device.getProductId()); - } - } - return info; - } - - /** - * control class - * never reuse the instance when it closed - */ - public static final class UsbControlBlock implements Cloneable { - private final WeakReference mWeakMonitor; - private final WeakReference mWeakDevice; - protected UsbDeviceConnection mConnection; - protected final UsbDeviceInfo mInfo; - private final int mBusNum; - private final int mDevNum; - private final SparseArray> mInterfaces = new SparseArray>(); - - /** - * this class needs permission to access USB device before constructing - * @param monitor - * @param device - */ - private UsbControlBlock(final USBMonitor monitor, final UsbDevice device) { - if (DEBUG) Log.i(TAG, "UsbControlBlock:constructor"); - mWeakMonitor = new WeakReference(monitor); - mWeakDevice = new WeakReference(device); - mConnection = monitor.mUsbManager.openDevice(device); - mInfo = updateDeviceInfo(monitor.mUsbManager, device, null); - final String name = device.getDeviceName(); - final String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null; - int busnum = 0; - int devnum = 0; - if (v != null) { - busnum = Integer.parseInt(v[v.length-2]); - devnum = Integer.parseInt(v[v.length-1]); - } - mBusNum = busnum; - mDevNum = devnum; -// if (DEBUG) { - if (mConnection != null) { - final int desc = mConnection.getFileDescriptor(); - final byte[] rawDesc = mConnection.getRawDescriptors(); - Log.i(TAG, String.format(Locale.US, "name=%s,desc=%d,busnum=%d,devnum=%d,rawDesc=", name, desc, busnum, devnum) + rawDesc); - } else { - Log.e(TAG, "could not connect to device " + name); - } -// } - } - - /** - * copy constructor - * @param src - * @throws IllegalStateException - */ - private UsbControlBlock(final UsbControlBlock src) throws IllegalStateException { - final USBMonitor monitor = src.getUSBMonitor(); - final UsbDevice device = src.getDevice(); - if (device == null) { - throw new IllegalStateException("device may already be removed"); - } - mConnection = monitor.mUsbManager.openDevice(device); - if (mConnection == null) { - throw new IllegalStateException("device may already be removed or have no permission"); - } - mInfo = updateDeviceInfo(monitor.mUsbManager, device, null); - mWeakMonitor = new WeakReference(monitor); - mWeakDevice = new WeakReference(device); - mBusNum = src.mBusNum; - mDevNum = src.mDevNum; - // FIXME USBMonitor.mCtrlBlocksに追加する(今はHashMapなので追加すると置き換わってしまうのでだめ, ListかHashMapにListをぶら下げる?) - } - - /** - * duplicate by clone - * need permission - * USBMonitor never handle cloned UsbControlBlock, you should release it after using it. - * @return - * @throws CloneNotSupportedException - */ - @Override - public UsbControlBlock clone() throws CloneNotSupportedException { - final UsbControlBlock ctrlblock; - try { - ctrlblock = new UsbControlBlock(this); - } catch (final IllegalStateException e) { - throw new CloneNotSupportedException(e.getMessage()); - } - return ctrlblock; - } - - public USBMonitor getUSBMonitor() { - return mWeakMonitor.get(); - } - - public final UsbDevice getDevice() { - return mWeakDevice.get(); - } - - /** - * get device name - * @return - */ - public String getDeviceName() { - final UsbDevice device = mWeakDevice.get(); - return device != null ? device.getDeviceName() : ""; - } - - /** - * get device id - * @return - */ - public int getDeviceId() { - final UsbDevice device = mWeakDevice.get(); - return device != null ? device.getDeviceId() : 0; - } - - /** - * get device key string - * @return same value if the devices has same vendor id, product id, device class, device subclass and device protocol - */ - public String getDeviceKeyName() { - return USBMonitor.getDeviceKeyName(mWeakDevice.get()); - } - - /** - * get device key string - * @param useNewAPI if true, try to use serial number - * @return - * @throws IllegalStateException - */ - public String getDeviceKeyName(final boolean useNewAPI) throws IllegalStateException { - if (useNewAPI) checkConnection(); - return USBMonitor.getDeviceKeyName(mWeakDevice.get(), mInfo.serial, useNewAPI); - } - - /** - * get device key - * @return - * @throws IllegalStateException - */ - public int getDeviceKey() throws IllegalStateException { - checkConnection(); - return USBMonitor.getDeviceKey(mWeakDevice.get()); - } - - /** - * get device key - * @param useNewAPI if true, try to use serial number - * @return - * @throws IllegalStateException - */ - public int getDeviceKey(final boolean useNewAPI) throws IllegalStateException { - if (useNewAPI) checkConnection(); - return USBMonitor.getDeviceKey(mWeakDevice.get(), mInfo.serial, useNewAPI); - } - - /** - * get device key string - * if device has serial number, use it - * @return - */ - public String getDeviceKeyNameWithSerial() { - return USBMonitor.getDeviceKeyName(mWeakDevice.get(), mInfo.serial, false); - } - - /** - * get device key - * if device has serial number, use it - * @return - */ - public int getDeviceKeyWithSerial() { - return getDeviceKeyNameWithSerial().hashCode(); - } - - /** - * get UsbDeviceConnection - * @return - */ - public synchronized UsbDeviceConnection getConnection() { - return mConnection; - } - - /** - * get file descriptor to access USB device - * @return - * @throws IllegalStateException - */ - public synchronized int getFileDescriptor() throws IllegalStateException { - checkConnection(); - return mConnection.getFileDescriptor(); - } - - /** - * get raw descriptor for the USB device - * @return - * @throws IllegalStateException - */ - public synchronized byte[] getRawDescriptors() throws IllegalStateException { - checkConnection(); - return mConnection.getRawDescriptors(); - } - - /** - * get vendor id - * @return - */ - public int getVenderId() { - final UsbDevice device = mWeakDevice.get(); - return device != null ? device.getVendorId() : 0; - } - - /** - * get product id - * @return - */ - public int getProductId() { - final UsbDevice device = mWeakDevice.get(); - return device != null ? device.getProductId() : 0; - } - - /** - * get version string of USB - * @return - */ - public String getUsbVersion() { - return mInfo.usb_version; - } - - /** - * get manufacture - * @return - */ - public String getManufacture() { - return mInfo.manufacturer; - } - - /** - * get product name - * @return - */ - public String getProductName() { - return mInfo.product; - } - - /** - * get version - * @return - */ - public String getVersion() { - return mInfo.version; - } - - /** - * get serial number - * @return - */ - public String getSerial() { - return mInfo.serial; - } - - public int getBusNum() { - return mBusNum; - } - - public int getDevNum() { - return mDevNum; - } - - /** - * get interface - * @param interface_id - * @throws IllegalStateException - */ - public synchronized UsbInterface getInterface(final int interface_id) throws IllegalStateException { - return getInterface(interface_id, 0); - } - - /** - * get interface - * @param interface_id - * @param altsetting - * @return - * @throws IllegalStateException - */ - public synchronized UsbInterface getInterface(final int interface_id, final int altsetting) throws IllegalStateException { - checkConnection(); - SparseArray intfs = mInterfaces.get(interface_id); - if (intfs == null) { - intfs = new SparseArray(); - mInterfaces.put(interface_id, intfs); - } - UsbInterface intf = intfs.get(altsetting); - if (intf == null) { - final UsbDevice device = mWeakDevice.get(); - final int n = device.getInterfaceCount(); - for (int i = 0; i < n; i++) { - final UsbInterface temp = device.getInterface(i); - if ((temp.getId() == interface_id) && (temp.getAlternateSetting() == altsetting)) { - intf = temp; - break; - } - } - if (intf != null) { - intfs.append(altsetting, intf); - } - } - return intf; - } - - /** - * open specific interface - * @param intf - */ - public synchronized void claimInterface(final UsbInterface intf) { - claimInterface(intf, true); - } - - public synchronized void claimInterface(final UsbInterface intf, final boolean force) { - checkConnection(); - mConnection.claimInterface(intf, force); - } - - /** - * close interface - * @param intf - * @throws IllegalStateException - */ - public synchronized void releaseInterface(final UsbInterface intf) throws IllegalStateException { - checkConnection(); - final SparseArray intfs = mInterfaces.get(intf.getId()); - if (intfs != null) { - final int index = intfs.indexOfValue(intf); - intfs.removeAt(index); - if (intfs.size() == 0) { - mInterfaces.remove(intf.getId()); - } - } - mConnection.releaseInterface(intf); - } - - /** - * Close device - * This also close interfaces if they are opened in Java side - */ - public synchronized void close() { - if (DEBUG) Log.i(TAG, "UsbControlBlock#close:"); - - if (mConnection != null) { - final int n = mInterfaces.size(); - for (int i = 0; i < n; i++) { - final SparseArray intfs = mInterfaces.valueAt(i); - if (intfs != null) { - final int m = intfs.size(); - for (int j = 0; j < m; j++) { - final UsbInterface intf = intfs.valueAt(j); - mConnection.releaseInterface(intf); - } - intfs.clear(); - } - } - mInterfaces.clear(); - mConnection.close(); - mConnection = null; - final USBMonitor monitor = mWeakMonitor.get(); - if (monitor != null) { - if (monitor.mOnDeviceConnectListener != null) { - monitor.mOnDeviceConnectListener.onDisconnect(mWeakDevice.get(), UsbControlBlock.this); - } - monitor.mCtrlBlocks.remove(getDevice()); - } - } - } - - @Override - public boolean equals(final Object o) { - if (o == null) return false; - if (o instanceof UsbControlBlock) { - final UsbDevice device = ((UsbControlBlock) o).getDevice(); - return device == null ? mWeakDevice.get() == null - : device.equals(mWeakDevice.get()); - } else if (o instanceof UsbDevice) { - return o.equals(mWeakDevice.get()); - } - return super.equals(o); - } - -// @Override -// protected void finalize() throws Throwable { -/// close(); -// super.finalize(); -// } - - private synchronized void checkConnection() throws IllegalStateException { - if (mConnection == null) { - throw new IllegalStateException("already closed"); - } - } - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/USBVendorId.java b/phenolib/src/main/java/com/serenegiant/usb/USBVendorId.java deleted file mode 100644 index 94dd2548..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/USBVendorId.java +++ /dev/null @@ -1,859 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@com.com.serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usb; - -import android.util.SparseArray; - -public class USBVendorId { - private static final SparseArray IDS = new SparseArray(); - - public static String vendorName(final int vendor_id) { - return IDS.get(vendor_id); - } - - static { - IDS.put(10006, "YUEN DA ELECTRONIC PRODUCTS FACTORY"); - IDS.put(10013, "Gionee Communication Equipment Co., Ltd. ShenZhen"); - IDS.put(10022, "Universal Electronics Inc. (dba: TVIEW)"); - IDS.put(1003, "Atmel Corporation"); - IDS.put(1006, "Mitsumi"); - IDS.put(1008, "HP Inc."); - IDS.put(10112, "M31 Technology Corp."); - IDS.put(10113, "Liteconn Co., Ltd."); - IDS.put(10121, "Suzhou WEIJU Electronics Technology Co., Ltd."); - IDS.put(10144, "Mondokey Limited"); - IDS.put(10149, "Advantest Corporation"); - IDS.put(10150, "iRobot Corporation"); - IDS.put(1020, "Elitegroup Computer Systems"); - IDS.put(1021, "Xilinx Inc."); - IDS.put(10226, "Sibridge Tech."); - IDS.put(1026, "ALi Corporation"); - IDS.put(1027, "Future Technology Devices International Limited"); - IDS.put(10275, "Dongguan Jiumutong Industry Co., Ltd."); - IDS.put(10289, "Power Integrations"); - IDS.put(10291, "Oculus VR, Inc."); - IDS.put(10300, "HIGH TEK HARNESS ENTERPRISE CO., LTD."); - IDS.put(10316, "Full in Hope Co., Ltd."); - IDS.put(1032, "Quanta Computer Inc."); - IDS.put(10329, "Viconn Technology (HK) Co., Ltd."); - IDS.put(1033, "NEC Corporation"); - IDS.put(1035, "Weltrend Semiconductor"); - IDS.put(1037, "VIA Technologies, Inc."); - IDS.put(10374, "Seeed Technology Co., Ltd."); - IDS.put(10375, "Specwerkz"); - IDS.put(1038, "MCCI Corporation"); - IDS.put(10398, "Esselte Leitz GmbH & Co. KG"); - IDS.put(10406, "E-SEEK Inc."); - IDS.put(1041, "BUFFALO INC."); - IDS.put(10423, "Pleora Technologies Inc."); - IDS.put(10431, "Vitetech Int'l Co., Ltd."); - IDS.put(1044, "Giga-Byte Technology Co., Ltd."); - IDS.put(10446, "Changzhou Shi Wujin Miqi East Electronic Co., Ltd."); - IDS.put(10457, "Shenzhen Ourconn Technology Co., Ltd."); - IDS.put(10458, "G.SKILL Int'l Enterprice Co., Ltd."); - IDS.put(1046, "Nuvoton Technology Corp."); - IDS.put(10466, "Surplus Electronic Technology Co., Ltd."); - IDS.put(10470, "BIAMP SYSTEMS"); - IDS.put(10509, "IBCONN Technologies (Shenzhen) Co., Ltd."); - IDS.put(10510, "Fugoo Inc."); - IDS.put(10519, "Pan Xin Precision Electronics Co., Ltd."); - IDS.put(10530, "Dongguan Digi-in Digital Technology Co., Ltd."); - IDS.put(1054, "Creative Labs"); - IDS.put(10540, "GENUSION, Inc."); - IDS.put(10544, "Ineda Systems Inc."); - IDS.put(10545, "Jolla Ltd."); - IDS.put(10546, "Peraso Technologies, Inc."); - IDS.put(10549, "Nanjing Magewell Electronics Co., Ltd."); - IDS.put(10560, "Shenzhen Yiwanda Electronics Co., Ltd."); - IDS.put(1057, "Nokia Corporation"); - IDS.put(10575, "Dollar Connection Ltd."); - IDS.put(10595, "BIO-key International, Inc."); - IDS.put(1060, "Microchip-SMSC"); - IDS.put(10603, "Xacti Corporation"); - IDS.put(10615, "Shenzhen Zowee Technology Co., Ltd."); - IDS.put(10643, "ADPlaus Technology Limited"); - IDS.put(10646, "Unwired Technology"); - IDS.put(1065, "Cirrus Logic Inc."); - IDS.put(10657, "Union Electric Plug & Connector Corp."); - IDS.put(10674, "Canova Tech"); - IDS.put(10685, "Silicon Works"); - IDS.put(10695, "HANRICO ANFU ELECTRONICS CO., LTD."); - IDS.put(10700, "Kodak Alaris"); - IDS.put(10702, "JGR Optics Inc."); - IDS.put(10703, "Richtek Technology Corporation"); - IDS.put(10705, "Binatone Electronics Int. Ltd."); - IDS.put(1071, "Molex Inc."); - IDS.put(10715, "Shenzhen iBoard Technology Co., Ltd."); - IDS.put(10719, "SMIT(HK) Limited"); - IDS.put(1072, "Fujitsu Component Limited"); - IDS.put(10725, "Dongguan Kechenda Electronic Technology Co., Ltd."); - IDS.put(10726, "Fengshun Peiying Electro-Acoustic Co., Ltd."); - IDS.put(10744, "MD ELEKTRONIK GmbH"); - IDS.put(10749, "Bad Elf, LLC"); - IDS.put(10770, "Vreo Limited"); - IDS.put(10772, "Kanex"); - IDS.put(10781, "Oxford Nanopore Technologies"); - IDS.put(10782, "Obsidian Technology"); - IDS.put(10783, "Lucent Trans Electronics Co., Ltd."); - IDS.put(10784, "GUOGUANG GROUP CO., LTD."); - IDS.put(10788, "CNPLUS"); - IDS.put(10789, "Fourstar Group"); - IDS.put(10790, "Tragant International Co., Ltd."); - IDS.put(10791, "DongGuan LianGang Optoelectronic Technology Co., Ltd."); - IDS.put(10797, "Atrust Computer Corp."); - IDS.put(10798, "VIA Alliance Semiconductor Co., Ltd."); - IDS.put(10799, "BSUN Electronics Co., Ltd."); - IDS.put(1080, "Advanced Micro Devices"); - IDS.put(10807, "RTD Embedded Technologies, Inc."); - IDS.put(10816, "Shenzhen Choseal Industrial Co., Ltd."); - IDS.put(10817, "Canyon Semiconductor"); - IDS.put(10818, "Spectra7 Microsystems Corp."); - IDS.put(10821, "Meizu Technology Co., Ltd."); - IDS.put(10822, "Hubei Yingtong Telecommunication Cable Inc."); - IDS.put(10829, "Wilder Technologies"); - IDS.put(10837, "Diodes Inc."); - IDS.put(10846, "DuPont"); - IDS.put(1085, "Lexmark International Inc."); - IDS.put(10852, "Zhejiang Songcheng Electronics Co., Ltd."); - IDS.put(10859, "VSN Mobil"); - IDS.put(10875, "Bellwether Electronic Corp."); - IDS.put(10878, "VAIO Corporation"); - IDS.put(10879, "Perixx Computer GmbH"); - IDS.put(10885, "HANK ELECTRONICS CO., LTD"); - IDS.put(10892, "Sonnet Technologies, Inc."); - IDS.put(10893, "Keysight Technologies Inc."); - IDS.put(10895, "Manutronics Vietnam Joint Stock Company"); - IDS.put(10900, "G2 Touch Co., Ltd."); - IDS.put(10902, "Micromax Informatics Ltd"); - IDS.put(10910, "SEIKO SOLUTIONS Inc."); - IDS.put(10912, "Casco Products Corp."); - IDS.put(10922, "Virtium Technology, Inc."); - IDS.put(10923, "Field and Company LLC, dba Leef USA"); - IDS.put(10928, "GM Global Technology Operations LLC"); - IDS.put(10931, "Key Asic Inc."); - IDS.put(10943, "Revolabs, Inc."); - IDS.put(10945, "Lattice Semiconductor Corp"); - IDS.put(10947, "Foshan Nanhai Saga Audio Equipment Co., Ltd."); - IDS.put(10957, "Silergy Corp."); - IDS.put(10963, "Shenzhen Hali-Power Industrial Co., Ltd."); - IDS.put(10971, "I-PEX (Dai-ichi Seiko)"); - IDS.put(10973, "SEE-PLUS INDUSTRIAL LTD."); - IDS.put(10990, "Adapt-IP Company"); - IDS.put(10997, "Libratone A/S"); - IDS.put(10999, "Shenzhen Hazens Automotive Electronics (SZ) Co., Ltd."); - IDS.put(11000, "Jiangsu Toppower Automotive Electronics Co., Ltd."); - IDS.put(11001, "Drapho Electronics Technology Co., Ltd."); - IDS.put(1102, "Alps Electric Co., Ltd."); - IDS.put(11022, "Le Shi Zhi Xin Electronic Technology (Tian Jin) Limited"); - IDS.put(11024, "Cardiac Insight, Inc."); - IDS.put(11028, "EverPro Technologies Company, Ltd."); - IDS.put(11029, "Rosenberger Hochfrequenztechnik"); - IDS.put(11035, "Dongguan City Sanji Electronics Co., Ltd."); - IDS.put(11037, "Lintes Technology Co., Ltd."); - IDS.put(11039, "KinnexA, Inc."); - IDS.put(11042, "Metra Electronics Corp."); - IDS.put(11044, "KeepKey, LLC"); - IDS.put(11047, "FluxData Incorporated"); - IDS.put(1105, "Texas Instruments"); - IDS.put(11061, "Assem Technology Co., Ltd."); - IDS.put(11062, "Dongguan City Jianghan Electronics Co., Ltd."); - IDS.put(11063, "Huizhou Desay SV Automotive Co., Ltd."); - IDS.put(11064, "Ningbo Rixing Electronics Co., Ltd."); - IDS.put(11069, "GuangDong YuanFeng Automotive Electroics Co., Ltd."); - IDS.put(11080, "Sounding Audio Industrial Limited"); - IDS.put(11082, "Yueqing Huaxin Electronic Co., Ltd."); - IDS.put(11098, "Universal Audio, Inc."); - IDS.put(11111, "Lifesize, Inc."); - IDS.put(11123, "Pioneer DJ Corporation"); - IDS.put(11124, "Embedded Intelligence, Inc."); - IDS.put(11125, "New Matter"); - IDS.put(11126, "Shanghai Wingtech Electronic Technology Co., Ltd."); - IDS.put(11127, "Epiphan Systems Inc."); - IDS.put(11130, "Spin Master Far East Ltd."); - IDS.put(11131, "Gigaset Digital Technology (Shenzhen) Co., Ltd."); - IDS.put(11132, "Noveltek Semiconductor Corp."); - IDS.put(11139, "Silicon Line GmbH"); - IDS.put(11140, "Ever Win International Corp."); - IDS.put(11144, "Socionext Inc."); - IDS.put(11145, "Ugreen Group Limited"); - IDS.put(11146, "Shanghai Pateo Electronic Equipment Mfg. Co., Ltd."); - IDS.put(1115, "Renesas Electronics Corp."); - IDS.put(11154, "i-BLADES, Inc."); - IDS.put(11155, "Altia Systems Inc."); - IDS.put(11156, "ShenZhen Baoyuanda Electronics Co., Ltd."); - IDS.put(11157, "iST - Integrated Service Technology Inc."); - IDS.put(11158, "HYUNDAI MOBIS Co., Ltd."); - IDS.put(11161, "360fly, Inc."); - IDS.put(11162, "HUIZHOU CHENG SHUO HARDWARE PLASTIC CO., LTD."); - IDS.put(11163, "Zhongshan Aute Electronics Technology Co., Ltd."); - IDS.put(11164, "Guangdong King Link Industrial Co., Ltd."); - IDS.put(11167, "Scietera Technologies, Inc."); - IDS.put(11168, "InVue Security Products"); - IDS.put(11169, "I-Sheng Electric Wire & Cable Co., Ltd."); - IDS.put(11170, "China Daheng Group Inc Beijing Image Vision Tech Branch"); - IDS.put(11171, "Shenzhen FeiTianXia Technology Ltd."); - IDS.put(11172, "Shenzhen HengJia New Energy Auto Part Co., Ltd."); - IDS.put(11175, "77 Elektronika Kft."); - IDS.put(11176, "YUDU EASON ELECTRONIC CO., LTD."); - IDS.put(1118, "Microsoft Corporation"); - IDS.put(11181, "XIN JI (SHENZHEN) COMPUTER PARTS CO., LTD."); - IDS.put(11189, "Silk ID Systems"); - IDS.put(11190, "3D Imaging & Simulations Corp. (3DISC)"); - IDS.put(11191, "Dongguan ChengXiang Industrial Co., Ltd."); - IDS.put(11192, "OCC (Zhuhai) Electronic Co., Ltd."); - IDS.put(11194, "Sinseader Electronic Co., Ltd."); - IDS.put(11195, "DONGGUAN YELLOWKNIFE Industrial Co., Ltd."); - IDS.put(11197, "RF Creations Ltd."); - IDS.put(11198, "Chengyi Semiconductors (Shanghai) Co., Ltd."); - IDS.put(11199, "Shenzhen Shinning Electronic Co., Ltd."); - IDS.put(11200, "Shenzhen WFD Electronics Co., Ltd."); - IDS.put(11201, "Dongguan Sino Syncs Industrial Co., Ltd."); - IDS.put(11202, "JNTC Co., Ltd."); - IDS.put(11208, "DONGGUAN POLIXIN ELECTRIC CO., LTD."); - IDS.put(11209, "Tama Electric (Suzhou) Co., Ltd."); - IDS.put(1121, "Primax Electronics"); - IDS.put(11210, "Exvision, Inc."); - IDS.put(11216, "mophie, LLC"); - IDS.put(11219, "Dongguan ULT-unite electronic technology co., LTD"); - IDS.put(11220, "JL Audio, Inc."); - IDS.put(11221, "Cable Matters Inc."); - IDS.put(11222, "CoroWare, Inc."); - IDS.put(11229, "Charm Sciences Inc."); - IDS.put(1123, "EATON"); - IDS.put(11230, "Pickering Interfaces Limited"); - IDS.put(11231, "Hangzhou Hikvision Digital Technology Co., Ltd."); - IDS.put(11232, "FULLINK ELECTRONICS TECHNOLOGY (SZ) LTD"); - IDS.put(11233, "AutoChips Inc."); - IDS.put(11234, "Electric Connector Technology Co., Ltd."); - IDS.put(11237, "LELTEK"); - IDS.put(11238, "Dongguan KaiWin Electronics Co., Ltd."); - IDS.put(11239, "BEFS Co., Ltd."); - IDS.put(11240, "Archisite, Inc."); - IDS.put(11241, "Magneti Marelli S.p.A Electr BL"); - IDS.put(11246, "Ventev Mobile"); - IDS.put(11247, "Quanta Storage Inc."); - IDS.put(11248, "Tech-Top Technology Limited"); - IDS.put(11253, "Shenzhen YOOBAO Technology Co., Ltd."); - IDS.put(11254, "Shenzhen Sinotek Technology Co., Ltd."); - IDS.put(11255, "KEYW"); - IDS.put(11256, "Visual Land Inc."); - IDS.put(11264, "MEEM SL Ltd"); - IDS.put(11265, "Dongguan Arin Electronics Technology Co., Ltd."); - IDS.put(11266, "DongGuan City JianNuo Electronics Co., Ltd."); - IDS.put(11268, "Shenzhen XOX Electronics Co., Ltd."); - IDS.put(11269, "Protop International Inc."); - IDS.put(11270, "Microsemi Semiconductor (US) Inc."); - IDS.put(11271, "Webcloak LLC"); - IDS.put(11272, "INVECAS INC."); - IDS.put(11274, "ATANS Technology Inc."); - IDS.put(11275, "Triple Win Precision Technology Co., Ltd."); - IDS.put(11276, "IC Realtech"); - IDS.put(11277, "Embrava Pty Ltd"); - IDS.put(1128, "Wieson Technologies Co., Ltd."); - IDS.put(11280, "Sinotronics Co., Ltd."); - IDS.put(11281, "ALLBEST ELECTRONICS TECHNOLOGY CO., LTD."); - IDS.put(11282, "Shenzhen Xin Kai Feng Electronics Factory"); - IDS.put(11283, "MOST WELL Technology Corp."); - IDS.put(11284, "Buffalo Memory Co., Ltd."); - IDS.put(11285, "Xentris Wireless"); - IDS.put(11286, "Priferential Accessories Ltd"); - IDS.put(11289, "Sunlike Technology Co., Ltd."); - IDS.put(11290, "Young Fast Optoelectronics Co., Ltd."); - IDS.put(11291, "ISAW Camera Inc"); - IDS.put(11298, "Qanba USA, LLC"); - IDS.put(11299, "Super Micro Computer Inc."); - IDS.put(11302, "Micromax International Corporation"); - IDS.put(11304, "Granite River Labs Japan Ltd."); - IDS.put(11305, "Coagent Enterprise Limited"); - IDS.put(11306, "LEIA Inc."); - IDS.put(11309, "Shenzhen Ebull Technology Limited"); - IDS.put(1131, "American Megatrends"); - IDS.put(11310, "Hualun Technology Co., Ltd."); - IDS.put(11311, "Sensel, Inc."); - IDS.put(11319, "Shenzhen Adition Audio Science & Technology Co., Ltd."); - IDS.put(11320, "Goldenconn Electronics Technology (Suzhou) Co., Ltd."); - IDS.put(11321, "JIB Electronics Technology Co., Ltd."); - IDS.put(11322, "Changzhou Shinco Automotive Electronics Co., Ltd."); - IDS.put(11323, "Shenzhen Hangsheng Electronics Corp., Ltd."); - IDS.put(11324, "Beartooth Radio, Inc."); - IDS.put(11325, "Audience, A Knowles Company"); - IDS.put(11327, "Nextbit Systems, Inc."); - IDS.put(11328, "Leadtrend"); - IDS.put(11329, "Adaptertek Technology Co., Ltd."); - IDS.put(1133, "Logitech Inc."); - IDS.put(11330, "Feature Integration Technology Inc."); - IDS.put(11331, "Avegant Corporation"); - IDS.put(11335, "Chunghsin International Electronics Co., Ltd."); - IDS.put(11336, "Delphi Electrical Centers (Shanghai) Co., Ltd."); - IDS.put(11341, "VVETEK DOO"); - IDS.put(11347, "Huizhou Foryou General Electronics Co., Ltd."); - IDS.put(11348, "LifeWatch Technologies Ltd."); - IDS.put(11349, "Magicleap"); - IDS.put(11355, "Dongguan City Shenglan Electronics Co., LTD."); - IDS.put(11356, "Neusoft Corporation"); - IDS.put(11357, "SIP Simya Electronics Technology Co., Ltd."); - IDS.put(11358, "GNSD Automotive Co., Ltd."); - IDS.put(11359, "YOODS Co., Ltd."); - IDS.put(11360, "Sirin Mobile Technologies AG"); - IDS.put(11361, "Jadmam Corporation dba: Boytone"); - IDS.put(11373, "Gibson Innovations"); - IDS.put(11374, "Shen Zhen Xian Shuo Technology Co. LTD"); - IDS.put(11375, "PST Eletronica LTDA"); - IDS.put(11376, "PERI, Inc."); - IDS.put(11377, "Bozhou BoTong Information Technology Co., Ltd."); - IDS.put(11383, "Profindustry GmbH"); - IDS.put(11384, "BRAGI GmbH"); - IDS.put(11385, "WAWGD, Inc. (DBA: Foresight Sports)"); - IDS.put(11390, "Dongguan Allpass Electronic Co., Ltd."); - IDS.put(11391, "SHENZHEN D-VITEC INDUSTRIAL CO., LTD."); - IDS.put(11392, "motomobile AG"); - IDS.put(11393, "Indie Semiconductor"); - IDS.put(11397, "Audientes"); - IDS.put(11403, "Huizhou Dehong Technology Co., Ltd."); - IDS.put(11404, "PowerCenter Technology Limited"); - IDS.put(11405, "Mizco International, Inc."); - IDS.put(11408, "I. AM. PLUS, LLC"); - IDS.put(11409, "Corigine, Inc."); - IDS.put(11410, "Ningbo Yinzhou Shengke Electronics Co., Ltd."); - IDS.put(11417, "Prusa Research s.r.o."); - IDS.put(11423, "e-Smart Systems Pvt. Ltd."); - IDS.put(11424, "Leagtech Jiangxi Electronic Co., Ltd."); - IDS.put(11425, "Dongguan Yujia Electronics Technology Co., Ltd."); - IDS.put(11426, "GuangZhou MingPing Electronics Technology"); - IDS.put(11427, "DJI Technology Co., Ltd."); - IDS.put(11428, "Shenzhen Alex Technology Co., Ltd."); - IDS.put(11433, "JITS TECHNOLOGY CO., LIMITED"); - IDS.put(11434, "LIVV Brand llc"); - IDS.put(11444, "Ava Enterprises, Inc. dba: Boss Audio Systems"); - IDS.put(11448, "Shenzhen Sydixon Electronic Technology Co., Ltd."); - IDS.put(11449, "On-Bright Electronics (Shanghai) Co., Ltd."); - IDS.put(11450, "Dongguan Puxu Industrial Co., Ltd."); - IDS.put(11451, "Shenzhen Soling Indusrtial Co., Ltd."); - IDS.put(11453, "EGGCYTE, INC."); - IDS.put(11455, "Donggguan Yuhua Electronic Co., Ltd."); - IDS.put(11456, "Hangzhou Zero Zero Technology Co., Ltd."); - IDS.put(11462, "Prodigy Technovations Pvt Ltd"); - IDS.put(11463, "EmergiTech, Inc"); - IDS.put(11464, "Hewlett Packard Enterprise"); - IDS.put(11465, "Monolithic Power Systems Inc."); - IDS.put(11467, "USB Memory Direct"); - IDS.put(11468, "Silicon Mitus Inc."); - IDS.put(11472, "Technics Global Electronics & JCE Co., Ltd."); - IDS.put(11478, "Immersive Media"); - IDS.put(11479, "Cosemi Technologies Inc."); - IDS.put(11481, "Cambrionix Ltd"); - IDS.put(11482, "CXUN Co. Ltd."); - IDS.put(11483, "China Tsp Inc"); - IDS.put(11490, "Yanfeng Visteon (Chongqing) Automotive Electronics Co"); - IDS.put(11491, "Alcorlink Corp."); - IDS.put(11492, "ISBC Ltd."); - IDS.put(11493, "InX8 Inc dba: AKiTiO"); - IDS.put(11494, "SDAN Tecchnology Co., Ltd."); - IDS.put(11495, "Lemobile Information Technology (Beijing) Co., Ltd."); - IDS.put(11496, "GongGuan HWX Electronic Technology Co., Ltd."); - IDS.put(11497, "Suzhu Jingshi Electronic Technology Co., Ltd."); - IDS.put(11498, "Zhong Shan City Richsound Electronic Industrial Ltd."); - IDS.put(11499, "Dongguang Kangbang Electronics Co., Ltd."); - IDS.put(1151, "Plantronics, Inc."); - IDS.put(1154, "Kyocera Corporation"); - IDS.put(1155, "STMicroelectronics"); - IDS.put(1161, "Foxconn / Hon Hai"); - IDS.put(1165, "ITE Tech Inc."); - IDS.put(1177, "Yamaha Corporation"); - IDS.put(1188, "Hitachi, Ltd."); - IDS.put(1191, "Visioneer"); - IDS.put(1193, "Canon Inc."); - IDS.put(1200, "Nikon Corporation"); - IDS.put(1201, "Pan International"); - IDS.put(1204, "Cypress Semiconductor"); - IDS.put(1205, "ROHM Co., Ltd."); - IDS.put(1207, "Compal Electronics, Inc."); - IDS.put(1208, "Seiko Epson Corp."); - IDS.put(1211, "I-O Data Device, Inc."); - IDS.put(1221, "Fujitsu Ltd."); - IDS.put(1227, "FUJIFILM Corporation"); - IDS.put(1238, "Mentor Graphics"); - IDS.put(1240, "Microchip Technology Inc."); - IDS.put(1241, "Holtek Semiconductor, Inc."); - IDS.put(1242, "Panasonic Corporation"); - IDS.put(1245, "Sharp Corporation"); - IDS.put(1250, "Exar Corporation"); - IDS.put(1254, "Identiv, Inc."); - IDS.put(1256, "Samsung Electronics Co., Ltd."); - IDS.put(1260, "Tokyo Electron Device Limited"); - IDS.put(1266, "Chicony Electronics Co., Ltd."); - IDS.put(1271, "Newnex Technology Corp."); - IDS.put(1273, "Brother Industries, Ltd."); - IDS.put(1276, "SUNPLUS TECHNOLOGY CO., LTD."); - IDS.put(1278, "PFU Limited"); - IDS.put(1281, "Fujikura/DDK"); - IDS.put(1282, "Acer, Inc."); - IDS.put(1287, "Hosiden Corporation"); - IDS.put(1293, "Belkin International, Inc."); - IDS.put(1300, "FCI Electronics"); - IDS.put(1302, "Longwell Electronics/Longwell Company"); - IDS.put(1305, "Star Micronics Co., LTD"); - IDS.put(1309, "American Power Conversion"); - IDS.put(1314, "ACON, Advanced-Connectek, Inc."); - IDS.put(1343, "Synopsys, Inc."); - IDS.put(1356, "Sony Corporation"); - IDS.put(1360, "Fuji Xerox Co., Ltd."); - IDS.put(1367, "ATEN International Co. Ltd."); - IDS.put(1369, "Cadence Design Systems, Inc."); - IDS.put(1386, "WACOM Co., Ltd."); - IDS.put(1389, "EIZO Corporation"); - IDS.put(1390, "Elecom Co., Ltd."); - IDS.put(1394, "Conexant Systems, Inc."); - IDS.put(1398, "BAFO/Quality Computer Accessories"); - IDS.put(1403, "Y-E Data, Inc."); - IDS.put(1404, "AVM GmbH"); - IDS.put(1410, "Roland Corporation"); - IDS.put(1412, "RATOC Systems, Inc."); - IDS.put(1419, "Infineon Technologies"); - IDS.put(1423, "Alcor Micro, Corp."); - IDS.put(1424, "OMRON Corporation"); - IDS.put(1447, "Bose Corporation"); - IDS.put(1449, "OmniVision Technologies, Inc."); - IDS.put(1452, "Apple"); - IDS.put(1453, "Y.C. Cable U.S.A., Inc"); - IDS.put(14627, "National Instruments"); - IDS.put(1470, "Tyco Electronics Corp., a TE Connectivity Ltd. company"); - IDS.put(1473, "MegaChips Corporation"); - IDS.put(1478, "Qualcomm, Inc"); - IDS.put(1480, "Foxlink/Cheng Uei Precision Industry Co., Ltd."); - IDS.put(1482, "Ricoh Company Ltd."); - IDS.put(1498, "Microtek International Inc."); - IDS.put(1504, "Symbol Technologies"); - IDS.put(1507, "Genesys Logic, Inc."); - IDS.put(1509, "Fuji Electric Co., Ltd."); - IDS.put(1525, "Unixtar Technology Inc."); - IDS.put(1529, "Datalogic ADC"); - IDS.put(1535, "LeCroy Corporation"); - IDS.put(1539, "Novatek Microelectronics Corp."); - IDS.put(1545, "SMK Manufacturing Inc."); - IDS.put(1551, "Joinsoon Electronics Mfg. Co., Ltd."); - IDS.put(1555, "TransAct Technologies Incorporated"); - IDS.put(1561, "Seiko Instruments Inc."); - IDS.put(1582, "JPC/MAIN SUPER Inc."); - IDS.put(1583, "Sin Sheng Terminal & Machine Inc."); - IDS.put(1593, "Chrontel, Inc."); - IDS.put(1611, "Analog Devices, Inc. Development Tools"); - IDS.put(1612, "Ji-Haw Industrial Co., Ltd"); - IDS.put(1614, "Suyin Corporation"); - IDS.put(1621, "Space Shuttle Hi-Tech Co.,Ltd."); - IDS.put(1622, "Glory Mark Electronic Ltd."); - IDS.put(1623, "Tekcon Electronics Corp."); - IDS.put(1624, "Sigma Designs, Inc."); - IDS.put(1631, "Good Way Technology Co., Ltd. & GWC technology Inc"); - IDS.put(1632, "TSAY-E (BVI) International Inc."); - IDS.put(1633, "Hamamatsu Photonics K.K."); - IDS.put(1642, "Total Technologies, Ltd."); - IDS.put(1659, "Prolific Technology, Inc."); - IDS.put(16700, "Dell Inc."); - IDS.put(1680, "Golden Bridge Electech Inc."); - IDS.put(1689, "Tektronix, Inc."); - IDS.put(1690, "Askey Computer Corporation"); - IDS.put(1709, "Greatland Electronics Taiwan Ltd."); - IDS.put(1710, "Eurofins Digital Testing Belgium"); - IDS.put(1720, "Pixela Corporation"); - IDS.put(1724, "Oki Data Corporation"); - IDS.put(1727, "Leoco Corporation"); - IDS.put(1732, "Bizlink Technology, Inc."); - IDS.put(1736, "SIIG, Inc."); - IDS.put(1747, "Mitsubishi Electric Corporation"); - IDS.put(1758, "Heisei Technology Co., Ltd."); - IDS.put(1802, "Oki Electric Industry Co., Ltd."); - IDS.put(1805, "Comoss Electronic Co., Ltd."); - IDS.put(1809, "Magic Control Technology Corp."); - IDS.put(1816, "Imation Corp."); - IDS.put(1838, "Sunix Co., Ltd."); - IDS.put(1846, "Lorom Industrial Co., Ltd."); - IDS.put(1848, "Mad Catz, Inc."); - IDS.put(1899, "HID Global GmbH"); - IDS.put(1901, "Denso Corporation"); - IDS.put(1913, "Fairchild Semiconductor"); - IDS.put(1921, "SanDisk Corporation"); - IDS.put(1937, "Copartner Technology Corporation"); - IDS.put(1954, "National Technical Systems"); - IDS.put(1971, "Plustek, Inc."); - IDS.put(1972, "OLYMPUS CORPORATION"); - IDS.put(1975, "TIME Interconnect Ltd."); - IDS.put(1994, "AVerMedia Technologies, Inc."); - IDS.put(1999, "Casio Computer Co., Ltd."); - IDS.put(2015, "David Electronics Company, Ltd."); - IDS.put(2039, "Century Corporation"); - IDS.put(2058, "Evermuch Technology Co., Ltd."); - IDS.put(2101, "Action Star Enterprise Co., Ltd."); - IDS.put(2112, "Argosy Research Inc."); - IDS.put(2122, "Wipro Limited"); - IDS.put(2159, "MEC IMEX INC/HPT"); - IDS.put(2205, "Icron Technologies Corporation"); - IDS.put(2247, "TAI TWUN ENTERPRISE CO., LTD."); - IDS.put(2276, "Pioneer Corporation"); - IDS.put(2278, "Gemalto SA"); - IDS.put(2310, "FARADAY Technology Corp."); - IDS.put(2313, "Audio-Technica Corp."); - IDS.put(2316, "Silicon Motion, Inc. - Taiwan"); - IDS.put(2334, "Garmin International"); - IDS.put(2352, "Toshiba Corporation"); - IDS.put(2362, "Pixart Imaging, Inc."); - IDS.put(2363, "Plextor LLC"); - IDS.put(2366, "J.S.T. Mfg. Co., Ltd."); - IDS.put(2385, "Kingston Technology Company"); - IDS.put(2389, "NVIDIA"); - IDS.put(2395, "Medialogic Corporation"); - IDS.put(2397, "Polycom, Inc."); - IDS.put(2468, "Contech Research, Inc."); - IDS.put(2472, "Lin Shiung Enterprise Co., Ltd."); - IDS.put(2475, "Japan Cash Machine Co., Ltd."); - IDS.put(2498, "NISCA Corporation"); - IDS.put(2511, "Electronics Testing Center, Taiwan"); - IDS.put(2522, "A-FOUR TECH CO., LTD."); - IDS.put(2555, "Altera"); - IDS.put(2578, "Cambridge Silicon Radio Ltd."); - IDS.put(2583, "HOYA Corporation"); - IDS.put(2631, "Hirose Electric Co., Ltd."); - IDS.put(2636, "COMPUTEX Co., Ltd."); - IDS.put(2640, "Mimaki Engineering Co., Ltd."); - IDS.put(2652, "Broadcom Corp."); - IDS.put(2667, "Green House Co., Ltd."); - IDS.put(2702, "Japan Aviation Electronics Industry Ltd. (JAE)"); - IDS.put(2727, "Wincor Nixdorf GmbH & Co KG"); - IDS.put(2733, "Rohde & Schwarz GmbH & Co. KG"); - IDS.put(2787, "Allion Labs, Inc."); - IDS.put(2821, "ASUSTek Computer Inc."); - IDS.put(2849, "Yokogawa Electric Corporation"); - IDS.put(2851, "Pan-Asia Electronics Co., Ltd."); - IDS.put(2894, "Musical Electronics Ltd."); - IDS.put(2907, "Anritsu Corporation"); - IDS.put(2922, "Maxim Integrated Products"); - IDS.put(2965, "ASIX Electronics Corporation"); - IDS.put(2967, "O2Micro, Inc."); - IDS.put(3010, "Seagate Technology LLC"); - IDS.put(3034, "Realtek Semiconductor Corp."); - IDS.put(3035, "Ericsson AB"); - IDS.put(3044, "Elka International Ltd."); - IDS.put(3056, "Pace Micro Technology PLC"); - IDS.put(3108, "Taiyo Yuden Co., Ltd."); - IDS.put(3129, "Aeroflex"); - IDS.put(3132, "Radius Co., Ltd."); - IDS.put(3141, "Sonix Technology Co., Ltd."); - IDS.put(3158, "Billion Bright (HK) Corporation Limited"); - IDS.put(3161, "Dong Guan Shinko Wire Co., Ltd."); - IDS.put(3170, "Chant Sincere Co., Ltd"); - IDS.put(3190, "Solid State System Co., Ltd."); - IDS.put(3209, "Honda Tsushin Kogyo Co., Ltd"); - IDS.put(3245, "Motorola Solutions"); - IDS.put(3255, "Singatron Enterprise Co. Ltd."); - IDS.put(3268, "emsys Embedded Systems GmbH"); - IDS.put(32902, "Intel Corporation"); - IDS.put(3294, "Z-Com INC."); - IDS.put(3313, "e-CONN ELECTRONIC CO., LTD."); - IDS.put(3314, "ENE Technology Inc."); - IDS.put(3351, "NALTEC, Inc."); - IDS.put(3402, "NF Corporation"); - IDS.put(3403, "Grape Systems Inc."); - IDS.put(3409, "Volex (Asia) Pte Ltd"); - IDS.put(3425, "MEILU ELECTRONICS (SHENZHEN) CO., LTD."); - IDS.put(3441, "Hirakawa Hewtech Corp."); - IDS.put(3452, "Taiwan Line Tek Electronic Co., Ltd."); - IDS.put(3463, "Dolby Laboratories Inc."); - IDS.put(3468, "C-MEDIA ELECTRONICS INC."); - IDS.put(3472, "Sure-Fire Electrical Corporation"); - IDS.put(3495, "IOGEAR, Inc."); - IDS.put(3504, "Micro-Star International Co., Ltd."); - IDS.put(3537, "Contek Electronics Co., Ltd."); - IDS.put(3540, "Custom Engineering SPA"); - IDS.put(3641, "Smart Modular Technologies, Inc."); - IDS.put(3658, "Shenzhen Bao Hing Electric Wire & Cable Mfr. Co."); - IDS.put(3673, "Bourns, Inc."); - IDS.put(3690, "Megawin Technology Co., Ltd."); - IDS.put(3698, "Hsi-Chin Electronics Co., Ltd."); - IDS.put(3714, "Ching Tai Electric Wire & Cable Co., Ltd."); - IDS.put(3724, "Well Force Electronic Co., Ltd"); - IDS.put(3725, "MediaTek Inc."); - IDS.put(3728, "CRU"); - IDS.put(3744, "Ours Technology Inc."); - IDS.put(3762, "Y-S ELECTRONIC CO., LTD."); - IDS.put(3778, "Sweetray Industrial Ltd."); - IDS.put(3779, "Axell Corporation"); - IDS.put(3782, "InnoVISION Multimedia Limited"); - IDS.put(3790, "TaiSol Electronics Co., Ltd."); - IDS.put(3812, "Sunrich Technology (H.K.) Ltd."); - IDS.put(3868, "Funai Electric Co., Ltd."); - IDS.put(3873, "IOI Technology Corporation"); - IDS.put(3890, "YFC-BonEagle Electric Co., Ltd."); - IDS.put(3896, "Nien-Yi Industrial Corp."); - IDS.put(3916, "WORLDWIDE CABLE OPTO CORP."); - IDS.put(3923, "Taiyo Cable (Dongguan) Co. Ltd."); - IDS.put(3924, "Kawai Musical Instruments Mfg. Co., Ltd."); - IDS.put(3936, "GuangZhou Chief Tech Electronic Technology Co. Ltd."); - IDS.put(3944, "UQUEST, LTD."); - IDS.put(3991, "CviLux Corporation"); - IDS.put(4003, "Chief Land Electronic Co., Ltd."); - IDS.put(4046, "Sony Mobile Communications"); - IDS.put(4087, "CHI SHING COMPUTER ACCESSORIES CO., LTD."); - IDS.put(4096, "Speed Tech Corp."); - IDS.put(4100, "LG Electronics Inc."); - IDS.put(4101, "Apacer Technology Inc."); - IDS.put(4134, "Newly Corporation"); - IDS.put(4168, "Targus Group International"); - IDS.put(4172, "AMCO TEC International Inc."); - IDS.put(4183, "ON Semiconductor"); - IDS.put(4184, "Western Digital Technologies, Inc."); - IDS.put(4227, "CANON ELECTRONICS INC."); - IDS.put(4235, "Grand-tek Technology Co., Ltd."); - IDS.put(4236, "Robert Bosch GmbH"); - IDS.put(4238, "Lotes Co., Ltd."); - IDS.put(4266, "Cables To Go"); - IDS.put(4267, "Universal Global Scientific Industrial Co., Ltd."); - IDS.put(4292, "Silicon Laboratories, Inc."); - IDS.put(4301, "Kycon Inc."); - IDS.put(4362, "Moxa Inc."); - IDS.put(4370, "Golden Bright (Sichuan) Electronic Technology Co Ltd"); - IDS.put(4382, "VSO ELECTRONICS CO., LTD."); - IDS.put(4398, "Master Hill Electric Wire and Cable Co., Ltd."); - IDS.put(4477, "Santa Electronic Inc."); - IDS.put(4505, "Sierra Wireless Inc."); - IDS.put(4522, "GlobalMedia Group, LLC"); - IDS.put(4528, "ATECH FLASH TECHNOLOGY"); - IDS.put(4643, "SKYCABLE ENTERPRISE CO., LTD."); - IDS.put(4703, "ADATA Technology Co., Ltd."); - IDS.put(4716, "Aristocrat Technologies"); - IDS.put(4717, "Bel Stewart"); - IDS.put(4742, "MARVELL SEMICONDUCTOR, INC."); - IDS.put(4756, "RISO KAGAKU CORP."); - IDS.put(4792, "Zhejiang Xinya Electronic Technology Co., Ltd."); - IDS.put(4817, "Huawei Technologies Co., Ltd."); - IDS.put(4823, "Better Holdings (HK) Limited"); - IDS.put(4907, "Konica Minolta, Inc."); - IDS.put(4925, "Jasco Products Company"); - IDS.put(4989, "Pericom Semiconductor Corp."); - IDS.put(5008, "TomTom International B.V."); - IDS.put(5075, "AzureWave Technologies, Inc."); - IDS.put(5117, "Initio Corporation"); - IDS.put(5118, "Phison Electronics Corp."); - IDS.put(5134, "Telechips, Inc."); - IDS.put(5145, "ABILITY ENTERPRISE CO., LTD."); - IDS.put(5148, "Leviton Manufacturing"); - IDS.put(5271, "Panstrong Company Ltd."); - IDS.put(5293, "CTK Corporation"); - IDS.put(5296, "StarTech.com Ltd."); - IDS.put(5376, "Ellisys"); - IDS.put(5404, "VeriSilicon Holdings Co., Ltd."); - IDS.put(5421, "JMicron Technology Corp."); - IDS.put(5422, "HLDS (Hitachi-LG Data Storage, Inc.)"); - IDS.put(5440, "Phihong Technology Co., Ltd."); - IDS.put(5451, "PNY Technologies Inc."); - IDS.put(5453, "Rapid Conn, Connect County Holdings Bhd"); - IDS.put(5454, "D & M Holdings, Inc."); - IDS.put(5480, "Sunf Pu Technology Co., Ltd"); - IDS.put(5488, "ALLTOP TECHNOLOGY CO., LTD."); - IDS.put(5510, "Palconn Technology Co., Ltd."); - IDS.put(5528, "Kunshan Guoji Electronics Co., Ltd."); - IDS.put(5546, "DongGuan Ya Lian Electronics Co., Ltd."); - IDS.put(5645, "Samtec"); - IDS.put(5694, "HongLin Electronics Co., Ltd."); - IDS.put(5753, "Total Phase"); - IDS.put(5766, "ZOOM Corporation"); - IDS.put(5836, "silex technology, Inc."); - IDS.put(5946, "F. Hoffmann-La Roche AG"); - IDS.put(5960, "MQP Electronics Ltd."); - IDS.put(5964, "ASMedia Technology Inc."); - IDS.put(5998, "UD electronic corp."); - IDS.put(6001, "Shenzhen Alex Connector Co., Ltd."); - IDS.put(6002, "System Level Solutions, Inc."); - IDS.put(6018, "Spreadtrum Hong Kong Limited"); - IDS.put(6024, "ShenZhen Litkconn Technology Co., Ltd."); - IDS.put(6053, "Advanced Connection Technology Inc."); - IDS.put(6095, "Hip Hing Cable & Plug Mfy. Ltd."); - IDS.put(6121, "DisplayLink (UK) Ltd."); - IDS.put(6127, "Lenovo"); - IDS.put(6133, "K.K. Rocky"); - IDS.put(6160, "Wanshih Electronic Co., Ltd."); - IDS.put(6185, "Dongguan YuQiu Electronics Co., Ltd."); - IDS.put(6193, "Gwo Jinn Industries Co., Ltd."); - IDS.put(6297, "Linkiss Co., Ltd."); - IDS.put(6353, "Google Inc."); - IDS.put(6394, "Kuang Ying Computer Equipment Co., Ltd."); - IDS.put(6421, "Nordic Semiconductor ASA"); - IDS.put(6448, "Shenzhen Xianhe Technology Co., Ltd."); - IDS.put(6449, "Ningbo Broad Telecommunication Co., Ltd."); - IDS.put(6470, "Irisguard UK Ltd"); - IDS.put(6473, "Lab126"); - IDS.put(6481, "Hyperstone GmbH"); - IDS.put(6487, "BIOS Corporation"); - IDS.put(6626, "Solomon Systech Limited"); - IDS.put(6639, "Pak Heng Technology (Shenzhen) Co., Ltd."); - IDS.put(6655, "Best Buy China Ltd."); - IDS.put(6666, "USB-IF non-workshop"); - IDS.put(6709, "Artesyn Technologies Inc."); - IDS.put(6720, "TERMINUS TECHNOLOGY INC."); - IDS.put(6766, "Global Unichip Corp."); - IDS.put(6786, "Proconn Technology Co., Ltd."); - IDS.put(6794, "Simula Technology Inc."); - IDS.put(6795, "SGS Taiwan Ltd."); - IDS.put(6830, "Johnson Component & Equipments Co., Ltd."); - IDS.put(6834, "Allied Vision Technologies GmbH"); - IDS.put(6859, "Salcomp Plc"); - IDS.put(6865, "Desan Wire Co., Ltd."); - IDS.put(6944, "MStar Semiconductor, Inc."); - IDS.put(6984, "Plastron Precision Co., Ltd."); - IDS.put(7013, "The Hong Kong Standards and Testing Centre Ltd."); - IDS.put(7048, "ShenMing Electron (Dong Guan) Co., Ltd."); - IDS.put(7086, "Vuzix Corporation"); - IDS.put(7108, "Ford Motor Co."); - IDS.put(7118, "Contac Cable Industrial Limited"); - IDS.put(7119, "Sunplus Innovation Technology Inc."); - IDS.put(7120, "Hangzhou Riyue Electronics Co., Ltd."); - IDS.put(7158, "Orient Semiconductor Electronics, Ltd."); - IDS.put(7207, "SHENZHEN DNS INDUSTRIES CO., LTD."); - IDS.put(7217, "LS Mtron Ltd."); - IDS.put(7229, "NONIN MEDICAL INC."); - IDS.put(7275, "Philips & Lite-ON Digital Solutions Corporation"); - IDS.put(7310, "ASTRON INTERNATIONAL CORP."); - IDS.put(7320, "ALPINE ELECTRONICS, INC."); - IDS.put(7347, "Aces Electronics Co., Ltd."); - IDS.put(7348, "OPEX CORPORATION"); - IDS.put(7390, "Telecommunications Technology Association (TTA)"); - IDS.put(7434, "Visteon Corporation"); - IDS.put(7465, "Horng Tong Enterprise Co., Ltd."); - IDS.put(7501, "Pegatron Corporation"); - IDS.put(7516, "Fresco Logic Inc."); - IDS.put(7529, "Walta Electronic Co., Ltd."); - IDS.put(7543, "Yueqing Changling Electronic Instrument Corp., Ltd."); - IDS.put(7584, "Parade Technologies, Inc."); - IDS.put(7647, "L&T Technology Services"); - IDS.put(7649, "Actions Microelectronics Co., Ltd."); - IDS.put(7666, "China Telecommunication Technology Labs - Terminals"); - IDS.put(7668, "SHEN ZHEN FORMAN PRECISION INDUSTRY CO., LTD."); - IDS.put(7682, "GLOBEMASTER TECHNOLOGIES CO., LTD."); - IDS.put(7696, "Point Grey Research Inc."); - IDS.put(7751, "HUNG TA H.T.ENTERPRISE CO., LTD."); - IDS.put(7758, "Etron Technology, Inc."); - IDS.put(7795, "COMLINK ELECTRONICS CO., LTD."); - IDS.put(7818, "HIBEST Electronic (DongGuan) Co., Ltd."); - IDS.put(7825, "Other World Computing"); - IDS.put(7863, "WIN WIN PRECISION INDUSTRIAL CO., LTD."); - IDS.put(7879, "Gefen Inc."); - IDS.put(7881, "MOSER BAER INDIA LIMITED"); - IDS.put(7898, "AIRTIES WIRELESS NETWORKS"); - IDS.put(7956, "Astoria Networks GmbH"); - IDS.put(7969, "Scosche Industries"); - IDS.put(7976, "Cal-Comp Electronics & Communications"); - IDS.put(7977, "Analogix Semiconductor, Inc."); - IDS.put(7989, "Amphenol ShouhMin Industry (ShenZhen) Co., Ltd"); - IDS.put(7996, "Chang Yang Electronics Company Ltd."); - IDS.put(8073, "Dongguan Goldconn Electronics Co., Ltd."); - IDS.put(8074, "Morning Star Industrial Co., Ltd."); - IDS.put(8117, "Unify Software and Solutions GmbH & Co. KG"); - IDS.put(8137, "NXP Semiconductors"); - IDS.put(8181, "Changzhou Wujin BEST Electronic Cables Co., Ltd."); - IDS.put(8205, "Belkin Electronic (Changzhou) Co., Ltd."); - IDS.put(8220, "Freeport Resources Enterprises Corp."); - IDS.put(8222, "Qingdao Haier Telecom Co., Ltd."); - IDS.put(8284, "Shenzhen Tronixin Electronics Co., Ltd."); - IDS.put(8294, "Unicorn Electronics Components Co., Ltd."); - IDS.put(8334, "Luxshare-ICT"); - IDS.put(8341, "CE LINK LIMITED"); - IDS.put(8342, "Microconn Electronic Co., Ltd."); - IDS.put(8367, "Shenzhen CARVE Electronics Co., Ltd."); - IDS.put(8382, "BURY GmbH & Co. KG"); - IDS.put(8384, "FENGHUA KINGSUN CO., LTD."); - IDS.put(8386, "Sumitomo Electric Ind., Ltd., Optical Comm. R&D Lab"); - IDS.put(8439, "XIMEA s.r.o."); - IDS.put(8457, "VIA Labs, Inc."); - IDS.put(8492, "Shenzhen Linoya Electronic Co., Ltd."); - IDS.put(8494, "Amphenol AssembleTech (Xiamen) Co., Ltd."); - IDS.put(8524, "Y Soft Corporation"); - IDS.put(8550, "JVC KENWOOD Corporation"); - IDS.put(8564, "Transcend Information, Inc."); - IDS.put(8566, "TMC/Allion Test Labs"); - IDS.put(8613, "Genesis Technology USA, Inc."); - IDS.put(8627, "Dongguan Teconn Electronics Technology Co., Ltd."); - IDS.put(8644, "Netcom Technology (HK) Limited"); - IDS.put(8659, "Compupack Technology Co., Ltd."); - IDS.put(8667, "G-Max Technology Co., Ltd."); - IDS.put(8679, "Sagemcom Broadband SAS"); - IDS.put(8695, "Wuerth-Elektronik eiSos GmbH & Co. KG"); - IDS.put(8707, "Shin Shin Co., Ltd."); - IDS.put(8709, "3eYamaichi Electronics Co., Ltd."); - IDS.put(8710, "Wiretek International Investment Ltd."); - IDS.put(8711, "Fuzhou Rockchip Electronics Co., Ltd."); - IDS.put(8752, "Plugable Technologies"); - IDS.put(8756, "T-CONN PRECISION CORPORATION"); - IDS.put(8831, "Granite River Labs"); - IDS.put(8842, "Hotron Precision Electronic Ind. Corp."); - IDS.put(8875, "Trigence Semiconductor, Inc."); - IDS.put(8888, "Motorola Mobility Inc."); - IDS.put(8904, "Karming Electronic (Shenzhen) Co., Ltd."); - IDS.put(8981, "Avery Design Systems, Inc."); - IDS.put(8993, "iKingdom Corp. (d.b.a. iConnectivity)"); - IDS.put(9051, "KangXiang Electronic Co., Ltd."); - IDS.put(9068, "ZheJiang Chunsheng Electronics Co., Ltd."); - IDS.put(9130, "DOK (HK) Trading Limited"); - IDS.put(9132, "Marunix Electron Limited"); - IDS.put(9165, "Avconn Precise Connector Co., Ltd."); - IDS.put(9184, "BitifEye Digital Test Solutions GmbH"); - IDS.put(9205, "Speed Conn Co., Ltd."); - IDS.put(9222, "INSIDE Secure"); - IDS.put(9292, "Minebea Co., Ltd."); - IDS.put(9299, "BAANTO"); - IDS.put(9338, "Suzhou Jutze Technologies Co., Ltd"); - IDS.put(9355, "DONGGUAN SYNCONN PRECISION INDUSTRY CO. LTD."); - IDS.put(9382, "Shenzhen Pangngai Industrial Co., Ltd."); - IDS.put(9422, "Shenzhen Deren Electronic Co., Ltd."); - IDS.put(9424, "Smith Micro Software, Inc."); - IDS.put(9453, "ZEN FACTORY GROUP (ASIA) LTD."); - IDS.put(9481, "Chain-In Electronic Co., Ltd."); - IDS.put(9514, "SUZHOU KELI TECHNOLOGY DEVELOPMENT CO., LTD."); - IDS.put(9515, "TOP Exactitude Industry (ShenZhen) Co., Ltd."); - IDS.put(9525, "ShenZhen Hogend Precision Technology Co., Ltd."); - IDS.put(9527, "Norel Systems Ltd."); - IDS.put(9556, "ASSA ABLOY AB"); - IDS.put(9575, "DongGuan LongTao Electronic Co., Ltd."); - IDS.put(9577, "DongGuan City MingJi Electronics Co., Ltd."); - IDS.put(9589, "Weida Hi-Tech Co., Ltd."); - IDS.put(9593, "Dongguan Wisechamp Electronic Co., Ltd."); - IDS.put(9613, "Sequans Communications"); - IDS.put(9636, "ALGOLTEK, INC."); - IDS.put(9651, "DongGuan Elinke Industrial Co., Ltd."); - IDS.put(9679, "Corning Optical Communications LLC"); - IDS.put(9714, "Dongguan Jinyue Electronics Co., Ltd."); - IDS.put(9723, "RICOH IMAGING COMPANY, LTD."); - IDS.put(9742, "DongGuan HYX Industrial Co., Ltd."); - IDS.put(9753, "Advanced Silicon SA"); - IDS.put(9756, "EISST Limited"); - IDS.put(9771, "YTOP Electronics Technical (Kunshan) Co., Ltd."); - IDS.put(9841, "Innovative Logic"); - IDS.put(9842, "GoPro"); - IDS.put(9846, "Basler AG"); - IDS.put(9851, "Palpilot International Corp."); - IDS.put(9896, "UNIREX CORPORATION"); - IDS.put(9917, "Integral Memory Plc."); - IDS.put(9973, "Morning Star Digital Connector Co., Ltd."); - IDS.put(9984, "MITACHI CO., LTD."); - IDS.put(9999, "HGST, a Western Digital Company"); - } -} diff --git a/phenolib/src/main/java/com/serenegiant/usb/UVCCamera.java b/phenolib/src/main/java/com/serenegiant/usb/UVCCamera.java deleted file mode 100644 index b803ccc4..00000000 --- a/phenolib/src/main/java/com/serenegiant/usb/UVCCamera.java +++ /dev/null @@ -1,1224 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@com.com.serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usb; - -import android.graphics.SurfaceTexture; -import android.hardware.usb.UsbDevice; -import android.text.TextUtils; -import android.util.Log; -import android.view.Surface; -import android.view.SurfaceHolder; - -import com.serenegiant.usb.USBMonitor.UsbControlBlock; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.List; - -public class UVCCamera { - private static final boolean DEBUG = false; // TODO set false when releasing - private static final String TAG = UVCCamera.class.getSimpleName(); - private static final String DEFAULT_USBFS = "/dev/bus/usb"; - - public static final int DEFAULT_PREVIEW_WIDTH = 640; - public static final int DEFAULT_PREVIEW_HEIGHT = 480; - public static final int DEFAULT_PREVIEW_MODE = 0; - public static final int DEFAULT_PREVIEW_MIN_FPS = 1; - public static final int DEFAULT_PREVIEW_MAX_FPS = 30; - public static final float DEFAULT_BANDWIDTH = 1.0f; - - public static final int FRAME_FORMAT_YUYV = 0; - public static final int FRAME_FORMAT_MJPEG = 1; - - public static final int PIXEL_FORMAT_RAW = 0; - public static final int PIXEL_FORMAT_YUV = 1; - public static final int PIXEL_FORMAT_RGB565 = 2; - public static final int PIXEL_FORMAT_RGBX = 3; - public static final int PIXEL_FORMAT_YUV420SP = 4; - public static final int PIXEL_FORMAT_NV21 = 5; // = YVU420SemiPlanar - - //-------------------------------------------------------------------------------- - public static final int CTRL_SCANNING = 0x00000001; // D0: Scanning Mode - public static final int CTRL_AE = 0x00000002; // D1: Auto-Exposure Mode - public static final int CTRL_AE_PRIORITY = 0x00000004; // D2: Auto-Exposure Priority - public static final int CTRL_AE_ABS = 0x00000008; // D3: Exposure Time (Absolute) - public static final int CTRL_AR_REL = 0x00000010; // D4: Exposure Time (Relative) - public static final int CTRL_FOCUS_ABS = 0x00000020; // D5: Focus (Absolute) - public static final int CTRL_FOCUS_REL = 0x00000040; // D6: Focus (Relative) - public static final int CTRL_IRIS_ABS = 0x00000080; // D7: Iris (Absolute) - public static final int CTRL_IRIS_REL = 0x00000100; // D8: Iris (Relative) - public static final int CTRL_ZOOM_ABS = 0x00000200; // D9: Zoom (Absolute) - public static final int CTRL_ZOOM_REL = 0x00000400; // D10: Zoom (Relative) - public static final int CTRL_PANTILT_ABS = 0x00000800; // D11: PanTilt (Absolute) - public static final int CTRL_PANTILT_REL = 0x00001000; // D12: PanTilt (Relative) - public static final int CTRL_ROLL_ABS = 0x00002000; // D13: Roll (Absolute) - public static final int CTRL_ROLL_REL = 0x00004000; // D14: Roll (Relative) - public static final int CTRL_FOCUS_AUTO = 0x00020000; // D17: Focus, Auto - public static final int CTRL_PRIVACY = 0x00040000; // D18: Privacy - public static final int CTRL_FOCUS_SIMPLE = 0x00080000; // D19: Focus, Simple - public static final int CTRL_WINDOW = 0x00100000; // D20: Window - - public static final int PU_BRIGHTNESS = 0x80000001; // D0: Brightness - public static final int PU_CONTRAST = 0x80000002; // D1: Contrast - public static final int PU_HUE = 0x80000004; // D2: Hue - public static final int PU_SATURATION = 0x80000008; // D3: Saturation - public static final int PU_SHARPNESS = 0x80000010; // D4: Sharpness - public static final int PU_GAMMA = 0x80000020; // D5: Gamma - public static final int PU_WB_TEMP = 0x80000040; // D6: White Balance Temperature - public static final int PU_WB_COMPO = 0x80000080; // D7: White Balance Component - public static final int PU_BACKLIGHT = 0x80000100; // D8: Backlight Compensation - public static final int PU_GAIN = 0x80000200; // D9: Gain - public static final int PU_POWER_LF = 0x80000400; // D10: Power Line Frequency - public static final int PU_HUE_AUTO = 0x80000800; // D11: Hue, Auto - public static final int PU_WB_TEMP_AUTO = 0x80001000; // D12: White Balance Temperature, Auto - public static final int PU_WB_COMPO_AUTO = 0x80002000; // D13: White Balance Component, Auto - public static final int PU_DIGITAL_MULT = 0x80004000; // D14: Digital Multiplier - public static final int PU_DIGITAL_LIMIT = 0x80008000; // D15: Digital Multiplier Limit - public static final int PU_AVIDEO_STD = 0x80010000; // D16: Analog Video Standard - public static final int PU_AVIDEO_LOCK = 0x80020000; // D17: Analog Video Lock Status - public static final int PU_CONTRAST_AUTO = 0x80040000; // D18: Contrast, Auto - - // uvc_status_class from libuvc.h - public static final int STATUS_CLASS_CONTROL = 0x10; - public static final int STATUS_CLASS_CONTROL_CAMERA = 0x11; - public static final int STATUS_CLASS_CONTROL_PROCESSING = 0x12; - - // uvc_status_attribute from libuvc.h - public static final int STATUS_ATTRIBUTE_VALUE_CHANGE = 0x00; - public static final int STATUS_ATTRIBUTE_INFO_CHANGE = 0x01; - public static final int STATUS_ATTRIBUTE_FAILURE_CHANGE = 0x02; - public static final int STATUS_ATTRIBUTE_UNKNOWN = 0xff; - - private static boolean isLoaded; - static { - if (!isLoaded) { - System.loadLibrary("jpeg-turbo1500"); - System.loadLibrary("usb100"); - System.loadLibrary("uvc"); - System.loadLibrary("UVCCamera"); - isLoaded = true; - } - } - - private UsbControlBlock mCtrlBlock; - protected long mControlSupports; // カメラコントロールでサポートしている機能フラグ - protected long mProcSupports; // プロセッシングユニットでサポートしている機能フラグ - protected int mCurrentFrameFormat = FRAME_FORMAT_MJPEG; - protected int mCurrentWidth = DEFAULT_PREVIEW_WIDTH, mCurrentHeight = DEFAULT_PREVIEW_HEIGHT; - protected float mCurrentBandwidthFactor = DEFAULT_BANDWIDTH; - protected String mSupportedSize; - protected List mCurrentSizeList; - // these fields from here are accessed from native code and do not change name and remove - protected long mNativePtr; - protected int mScanningModeMin, mScanningModeMax, mScanningModeDef; - protected int mExposureModeMin, mExposureModeMax, mExposureModeDef; - protected int mExposurePriorityMin, mExposurePriorityMax, mExposurePriorityDef; - protected int mExposureMin, mExposureMax, mExposureDef; - protected int mAutoFocusMin, mAutoFocusMax, mAutoFocusDef; - protected int mFocusMin, mFocusMax, mFocusDef; - protected int mFocusRelMin, mFocusRelMax, mFocusRelDef; - protected int mFocusSimpleMin, mFocusSimpleMax, mFocusSimpleDef; - protected int mIrisMin, mIrisMax, mIrisDef; - protected int mIrisRelMin, mIrisRelMax, mIrisRelDef; - protected int mPanMin, mPanMax, mPanDef; - protected int mTiltMin, mTiltMax, mTiltDef; - protected int mRollMin, mRollMax, mRollDef; - protected int mPanRelMin, mPanRelMax, mPanRelDef; - protected int mTiltRelMin, mTiltRelMax, mTiltRelDef; - protected int mRollRelMin, mRollRelMax, mRollRelDef; - protected int mPrivacyMin, mPrivacyMax, mPrivacyDef; - protected int mAutoWhiteBlanceMin, mAutoWhiteBlanceMax, mAutoWhiteBlanceDef; - protected int mAutoWhiteBlanceCompoMin, mAutoWhiteBlanceCompoMax, mAutoWhiteBlanceCompoDef; - protected int mWhiteBlanceMin, mWhiteBlanceMax, mWhiteBlanceDef; - protected int mWhiteBlanceCompoMin, mWhiteBlanceCompoMax, mWhiteBlanceCompoDef; - protected int mWhiteBlanceRelMin, mWhiteBlanceRelMax, mWhiteBlanceRelDef; - protected int mBacklightCompMin, mBacklightCompMax, mBacklightCompDef; - protected int mBrightnessMin, mBrightnessMax, mBrightnessDef; - protected int mContrastMin, mContrastMax, mContrastDef; - protected int mSharpnessMin, mSharpnessMax, mSharpnessDef; - protected int mGainMin, mGainMax, mGainDef; - protected int mGammaMin, mGammaMax, mGammaDef; - protected int mSaturationMin, mSaturationMax, mSaturationDef; - protected int mHueMin, mHueMax, mHueDef; - protected int mZoomMin, mZoomMax, mZoomDef; - protected int mZoomRelMin, mZoomRelMax, mZoomRelDef; - protected int mPowerlineFrequencyMin, mPowerlineFrequencyMax, mPowerlineFrequencyDef; - protected int mMultiplierMin, mMultiplierMax, mMultiplierDef; - protected int mMultiplierLimitMin, mMultiplierLimitMax, mMultiplierLimitDef; - protected int mAnalogVideoStandardMin, mAnalogVideoStandardMax, mAnalogVideoStandardDef; - protected int mAnalogVideoLockStateMin, mAnalogVideoLockStateMax, mAnalogVideoLockStateDef; - // until here - /** - * the sonctructor of this class should be call within the thread that has a looper - * (UI thread or a thread that called Looper.prepare) - */ - public UVCCamera() { - mNativePtr = nativeCreate(); - mSupportedSize = null; - } - - /** - * connect to a UVC camera - * USB permission is necessary before this method is called - * @param ctrlBlock - */ - public synchronized void open(final UsbControlBlock ctrlBlock) { - int result; - try { - mCtrlBlock = ctrlBlock.clone(); - result = nativeConnect(mNativePtr, - mCtrlBlock.getVenderId(), mCtrlBlock.getProductId(), - mCtrlBlock.getFileDescriptor(), - mCtrlBlock.getBusNum(), - mCtrlBlock.getDevNum(), - getUSBFSName(mCtrlBlock)); - } catch (final Exception e) { - Log.w(TAG, e); - result = -1; - } - if (result != 0) { - throw new UnsupportedOperationException("open failed:result=" + result); - } - if (mNativePtr != 0 && TextUtils.isEmpty(mSupportedSize)) { - mSupportedSize = nativeGetSupportedSize(mNativePtr); - } - nativeSetPreviewSize(mNativePtr, DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT, - DEFAULT_PREVIEW_MIN_FPS, DEFAULT_PREVIEW_MAX_FPS, DEFAULT_PREVIEW_MODE, DEFAULT_BANDWIDTH); - } - - /** - * set status callback - * @param callback - */ - public void setStatusCallback(final IStatusCallback callback) { - if (mNativePtr != 0) { - nativeSetStatusCallback(mNativePtr, callback); - } - } - - /** - * set button callback - * @param callback - */ - public void setButtonCallback(final IButtonCallback callback) { - if (mNativePtr != 0) { - nativeSetButtonCallback(mNativePtr, callback); - } - } - - /** - * close and release UVC camera - */ - public synchronized void close() { - stopPreview(); - if (mNativePtr != 0) { - nativeRelease(mNativePtr); -// mNativePtr = 0; // nativeDestroyを呼ぶのでここでクリアしちゃダメ - } - if (mCtrlBlock != null) { - mCtrlBlock.close(); - mCtrlBlock = null; - } - mControlSupports = mProcSupports = 0; - mCurrentFrameFormat = -1; - mCurrentBandwidthFactor = 0; - mSupportedSize = null; - mCurrentSizeList = null; - if (DEBUG) Log.v(TAG, "close:finished"); - } - - public UsbDevice getDevice() { - return mCtrlBlock != null ? mCtrlBlock.getDevice() : null; - } - - public String getDeviceName(){ - return mCtrlBlock != null ? mCtrlBlock.getDeviceName() : null; - } - - public UsbControlBlock getUsbControlBlock() { - return mCtrlBlock; - } - - public synchronized String getSupportedSize() { - return !TextUtils.isEmpty(mSupportedSize) ? mSupportedSize : (mSupportedSize = nativeGetSupportedSize(mNativePtr)); - } - - public Size getPreviewSize() { - Size result = null; - final List list = getSupportedSizeList(); - for (final Size sz: list) { - if ((sz.width == mCurrentWidth) - || (sz.height == mCurrentHeight)) { - result =sz; - break; - } - } - return result; - } - - /** - * Set preview size and preview mode - * @param width - @param height - */ - public void setPreviewSize(final int width, final int height) { - setPreviewSize(width, height, DEFAULT_PREVIEW_MIN_FPS, DEFAULT_PREVIEW_MAX_FPS, mCurrentFrameFormat, mCurrentBandwidthFactor); - } - - /** - * Set preview size and preview mode - * @param width - * @param height - * @param frameFormat either FRAME_FORMAT_YUYV(0) or FRAME_FORMAT_MJPEG(1) - */ - public void setPreviewSize(final int width, final int height, final int frameFormat) { - setPreviewSize(width, height, DEFAULT_PREVIEW_MIN_FPS, DEFAULT_PREVIEW_MAX_FPS, frameFormat, mCurrentBandwidthFactor); - } - - /** - * Set preview size and preview mode - * @param width - @param height - @param frameFormat either FRAME_FORMAT_YUYV(0) or FRAME_FORMAT_MJPEG(1) - @param bandwidth [0.0f,1.0f] - */ - public void setPreviewSize(final int width, final int height, final int frameFormat, final float bandwidth) { - setPreviewSize(width, height, DEFAULT_PREVIEW_MIN_FPS, DEFAULT_PREVIEW_MAX_FPS, frameFormat, bandwidth); - } - - /** - * Set preview size and preview mode - * @param width - * @param height - * @param min_fps - * @param max_fps - * @param frameFormat either FRAME_FORMAT_YUYV(0) or FRAME_FORMAT_MJPEG(1) - * @param bandwidthFactor - */ - public void setPreviewSize(final int width, final int height, final int min_fps, final int max_fps, final int frameFormat, final float bandwidthFactor) { - if ((width == 0) || (height == 0)) - throw new IllegalArgumentException("invalid preview size"); - if (mNativePtr != 0) { - final int result = nativeSetPreviewSize(mNativePtr, width, height, min_fps, max_fps, frameFormat, bandwidthFactor); - if (result != 0) - throw new IllegalArgumentException("Failed to set preview size"); - mCurrentFrameFormat = frameFormat; - mCurrentWidth = width; - mCurrentHeight = height; - mCurrentBandwidthFactor = bandwidthFactor; - } - } - - public List getSupportedSizeList() { - final int type = (mCurrentFrameFormat > 0) ? 6 : 4; - return getSupportedSize(type, mSupportedSize); - } - - public static List getSupportedSize(final int type, final String supportedSize) { - final List result = new ArrayList(); - if (!TextUtils.isEmpty(supportedSize)) - try { - final JSONObject json = new JSONObject(supportedSize); - final JSONArray formats = json.getJSONArray("formats"); - final int format_nums = formats.length(); - for (int i = 0; i < format_nums; i++) { - final JSONObject format = formats.getJSONObject(i); - if(format.has("type") && format.has("size")) { - final int format_type = format.getInt("type"); - if ((format_type == type) || (type == -1)) { - addSize(format, format_type, 0, result); - } - } - } - } catch (final JSONException e) { - e.printStackTrace(); - } - return result; - } - - private static final void addSize(final JSONObject format, final int formatType, final int frameType, final List size_list) throws JSONException { - final JSONArray size = format.getJSONArray("size"); - final int size_nums = size.length(); - for (int j = 0; j < size_nums; j++) { - final String[] sz = size.getString(j).split("x"); - try { - size_list.add(new Size(formatType, frameType, j, Integer.parseInt(sz[0]), Integer.parseInt(sz[1]))); - } catch (final Exception e) { - break; - } - } - } - - /** - * set preview surface with SurfaceHolder
- * you can use SurfaceHolder came from SurfaceView/GLSurfaceView - * @param holder - */ - public synchronized void setPreviewDisplay(final SurfaceHolder holder) { - nativeSetPreviewDisplay(mNativePtr, holder.getSurface()); - } - - /** - * set preview surface with SurfaceTexture. - * this method require API >= 14 - * @param texture - */ - public synchronized void setPreviewTexture(final SurfaceTexture texture) { // API >= 11 - final Surface surface = new Surface(texture); // XXX API >= 14 - nativeSetPreviewDisplay(mNativePtr, surface); - } - - /** - * set preview surface with Surface - * @param surface - */ - public synchronized void setPreviewDisplay(final Surface surface) { - nativeSetPreviewDisplay(mNativePtr, surface); - } - - /** - * set frame callback - * @param callback - * @param pixelFormat - */ - public void setFrameCallback(final IFrameCallback callback, final int pixelFormat) { - if (mNativePtr != 0) { - nativeSetFrameCallback(mNativePtr, callback, pixelFormat); - } - } - - /** - * start preview - */ - public synchronized void startPreview() { - if (mCtrlBlock != null) { - nativeStartPreview(mNativePtr); - } - } - - /** - * stop preview - */ - public synchronized void stopPreview() { - setFrameCallback(null, 0); - if (mCtrlBlock != null) { - nativeStopPreview(mNativePtr); - } - } - - /** - * destroy UVCCamera object - */ - public synchronized void destroy() { - close(); - if (mNativePtr != 0) { - nativeDestroy(mNativePtr); - mNativePtr = 0; - } - } - - // wrong result may return when you call this just after camera open. - // it is better to wait several hundreads millseconds. - public boolean checkSupportFlag(final long flag) { - updateCameraParams(); - if ((flag & 0x80000000) == 0x80000000) - return ((mProcSupports & flag) == (flag & 0x7ffffffF)); - else - return (mControlSupports & flag) == flag; - } - -//================================================================================ - public synchronized void setAutoFocus(final boolean autoFocus) { - if (mNativePtr != 0) { - nativeSetAutoFocus(mNativePtr, autoFocus); - } - } - - public synchronized boolean getAutoFocus() { - boolean result = true; - if (mNativePtr != 0) { - result = nativeGetAutoFocus(mNativePtr) > 0; - } - return result; - } -//================================================================================ - /** - * @param focus [%] - */ - public synchronized void setFocus(final int focus) { - if (mNativePtr != 0) { - final float range = Math.abs(mFocusMax - mFocusMin); - if (range > 0) - nativeSetFocus(mNativePtr, (int)(focus / 100.f * range) + mFocusMin); - } - } - - /** - * @param focus_abs - * @return focus[%] - */ - public synchronized int getFocus(final int focus_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateFocusLimit(mNativePtr); - final float range = Math.abs(mFocusMax - mFocusMin); - if (range > 0) { - result = (int)((focus_abs - mFocusMin) * 100.f / range); - } - } - return result; - } - - /** - * @return focus[%] - */ - public synchronized int getFocus() { - return getFocus(nativeGetFocus(mNativePtr)); - } - - public synchronized void resetFocus() { - if (mNativePtr != 0) { - nativeSetFocus(mNativePtr, mFocusDef); - } - } - -//================================================================================ - public synchronized void setAutoWhiteBlance(final boolean autoWhiteBlance) { - if (mNativePtr != 0) { - nativeSetAutoWhiteBlance(mNativePtr, autoWhiteBlance); - } - } - - public synchronized boolean getAutoWhiteBlance() { - boolean result = true; - if (mNativePtr != 0) { - result = nativeGetAutoWhiteBlance(mNativePtr) > 0; - } - return result; - } - -//================================================================================ - /** - * @param whiteBlance [%] - */ - public synchronized void setWhiteBlance(final int whiteBlance) { - if (mNativePtr != 0) { - final float range = Math.abs(mWhiteBlanceMax - mWhiteBlanceMin); - if (range > 0) - nativeSetWhiteBlance(mNativePtr, (int)(whiteBlance / 100.f * range) + mWhiteBlanceMin); - } - } - - /** - * @param whiteBlance_abs - * @return whiteBlance[%] - */ - public synchronized int getWhiteBlance(final int whiteBlance_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateWhiteBlanceLimit(mNativePtr); - final float range = Math.abs(mWhiteBlanceMax - mWhiteBlanceMin); - if (range > 0) { - result = (int)((whiteBlance_abs - mWhiteBlanceMin) * 100.f / range); - } - } - return result; - } - - /** - * @return white blance[%] - */ - public synchronized int getWhiteBlance() { - return getFocus(nativeGetWhiteBlance(mNativePtr)); - } - - public synchronized void resetWhiteBlance() { - if (mNativePtr != 0) { - nativeSetWhiteBlance(mNativePtr, mWhiteBlanceDef); - } - } -//================================================================================ - /** - * @param brightness [%] - */ - public synchronized void setBrightness(final int brightness) { - if (mNativePtr != 0) { - final float range = Math.abs(mBrightnessMax - mBrightnessMin); - if (range > 0) - nativeSetBrightness(mNativePtr, (int)(brightness / 100.f * range) + mBrightnessMin); - } - } - - /** - * @param brightness_abs - * @return brightness[%] - */ - public synchronized int getBrightness(final int brightness_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateBrightnessLimit(mNativePtr); - final float range = Math.abs(mBrightnessMax - mBrightnessMin); - if (range > 0) { - result = (int)((brightness_abs - mBrightnessMin) * 100.f / range); - } - } - return result; - } - - /** - * @return brightness[%] - */ - public synchronized int getBrightness() { - return getBrightness(nativeGetBrightness(mNativePtr)); - } - - public synchronized void resetBrightness() { - if (mNativePtr != 0) { - nativeSetBrightness(mNativePtr, mBrightnessDef); - } - } - -//================================================================================ - /** - * @param contrast [%] - */ - public synchronized void setContrast(final int contrast) { - if (mNativePtr != 0) { - nativeUpdateContrastLimit(mNativePtr); - final float range = Math.abs(mContrastMax - mContrastMin); - if (range > 0) - nativeSetContrast(mNativePtr, (int)(contrast / 100.f * range) + mContrastMin); - } - } - - /** - * @param contrast_abs - * @return contrast[%] - */ - public synchronized int getContrast(final int contrast_abs) { - int result = 0; - if (mNativePtr != 0) { - final float range = Math.abs(mContrastMax - mContrastMin); - if (range > 0) { - result = (int)((contrast_abs - mContrastMin) * 100.f / range); - } - } - return result; - } - - /** - * @return contrast[%] - */ - public synchronized int getContrast() { - return getContrast(nativeGetContrast(mNativePtr)); - } - - public synchronized void resetContrast() { - if (mNativePtr != 0) { - nativeSetContrast(mNativePtr, mContrastDef); - } - } - -//================================================================================ - /** - * @param sharpness [%] - */ - public synchronized void setSharpness(final int sharpness) { - if (mNativePtr != 0) { - final float range = Math.abs(mSharpnessMax - mSharpnessMin); - if (range > 0) - nativeSetSharpness(mNativePtr, (int)(sharpness / 100.f * range) + mSharpnessMin); - } - } - - /** - * @param sharpness_abs - * @return sharpness[%] - */ - public synchronized int getSharpness(final int sharpness_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateSharpnessLimit(mNativePtr); - final float range = Math.abs(mSharpnessMax - mSharpnessMin); - if (range > 0) { - result = (int)((sharpness_abs - mSharpnessMin) * 100.f / range); - } - } - return result; - } - - /** - * @return sharpness[%] - */ - public synchronized int getSharpness() { - return getSharpness(nativeGetSharpness(mNativePtr)); - } - - public synchronized void resetSharpness() { - if (mNativePtr != 0) { - nativeSetSharpness(mNativePtr, mSharpnessDef); - } - } -//================================================================================ - /** - * @param gain [%] - */ - public synchronized void setGain(final int gain) { - if (mNativePtr != 0) { - final float range = Math.abs(mGainMax - mGainMin); - if (range > 0) - nativeSetGain(mNativePtr, (int)(gain / 100.f * range) + mGainMin); - } - } - - /** - * @param gain_abs - * @return gain[%] - */ - public synchronized int getGain(final int gain_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateGainLimit(mNativePtr); - final float range = Math.abs(mGainMax - mGainMin); - if (range > 0) { - result = (int)((gain_abs - mGainMin) * 100.f / range); - } - } - return result; - } - - /** - * @return gain[%] - */ - public synchronized int getGain() { - return getGain(nativeGetGain(mNativePtr)); - } - - public synchronized void resetGain() { - if (mNativePtr != 0) { - nativeSetGain(mNativePtr, mGainDef); - } - } - -//================================================================================ - /** - * @param gamma [%] - */ - public synchronized void setGamma(final int gamma) { - if (mNativePtr != 0) { - final float range = Math.abs(mGammaMax - mGammaMin); - if (range > 0) - nativeSetGamma(mNativePtr, (int)(gamma / 100.f * range) + mGammaMin); - } - } - - /** - * @param gamma_abs - * @return gamma[%] - */ - public synchronized int getGamma(final int gamma_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateGammaLimit(mNativePtr); - final float range = Math.abs(mGammaMax - mGammaMin); - if (range > 0) { - result = (int)((gamma_abs - mGammaMin) * 100.f / range); - } - } - return result; - } - - /** - * @return gamma[%] - */ - public synchronized int getGamma() { - return getGamma(nativeGetGamma(mNativePtr)); - } - - public synchronized void resetGamma() { - if (mNativePtr != 0) { - nativeSetGamma(mNativePtr, mGammaDef); - } - } - -//================================================================================ - /** - * @param saturation [%] - */ - public synchronized void setSaturation(final int saturation) { - if (mNativePtr != 0) { - final float range = Math.abs(mSaturationMax - mSaturationMin); - if (range > 0) - nativeSetSaturation(mNativePtr, (int)(saturation / 100.f * range) + mSaturationMin); - } - } - - /** - * @param saturation_abs - * @return saturation[%] - */ - public synchronized int getSaturation(final int saturation_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateSaturationLimit(mNativePtr); - final float range = Math.abs(mSaturationMax - mSaturationMin); - if (range > 0) { - result = (int)((saturation_abs - mSaturationMin) * 100.f / range); - } - } - return result; - } - - /** - * @return saturation[%] - */ - public synchronized int getSaturation() { - return getSaturation(nativeGetSaturation(mNativePtr)); - } - - public synchronized void resetSaturation() { - if (mNativePtr != 0) { - nativeSetSaturation(mNativePtr, mSaturationDef); - } - } -//================================================================================ - /** - * @param hue [%] - */ - public synchronized void setHue(final int hue) { - if (mNativePtr != 0) { - final float range = Math.abs(mHueMax - mHueMin); - if (range > 0) - nativeSetHue(mNativePtr, (int)(hue / 100.f * range) + mHueMin); - } - } - - /** - * @param hue_abs - * @return hue[%] - */ - public synchronized int getHue(final int hue_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateHueLimit(mNativePtr); - final float range = Math.abs(mHueMax - mHueMin); - if (range > 0) { - result = (int)((hue_abs - mHueMin) * 100.f / range); - } - } - return result; - } - - /** - * @return hue[%] - */ - public synchronized int getHue() { - return getHue(nativeGetHue(mNativePtr)); - } - - public synchronized void resetHue() { - if (mNativePtr != 0) { - nativeSetHue(mNativePtr, mSaturationDef); - } - } - -//================================================================================ - public void setPowerlineFrequency(final int frequency) { - if (mNativePtr != 0) - nativeSetPowerlineFrequency(mNativePtr, frequency); - } - - public int getPowerlineFrequency() { - return nativeGetPowerlineFrequency(mNativePtr); - } - -//================================================================================ - /** - * this may not work well with some combination of camera and device - * @param zoom [%] - */ - public synchronized void setZoom(final int zoom) { - if (mNativePtr != 0) { - final float range = Math.abs(mZoomMax - mZoomMin); - if (range > 0) { - final int z = (int)(zoom / 100.f * range) + mZoomMin; -// Log.d(TAG, "setZoom:zoom=" + zoom + " ,value=" + z); - nativeSetZoom(mNativePtr, z); - } - } - } - - /** - * @param zoom_abs - * @return zoom[%] - */ - public synchronized int getZoom(final int zoom_abs) { - int result = 0; - if (mNativePtr != 0) { - nativeUpdateZoomLimit(mNativePtr); - final float range = Math.abs(mZoomMax - mZoomMin); - if (range > 0) { - result = (int)((zoom_abs - mZoomMin) * 100.f / range); - } - } - return result; - } - - /** - * @return zoom[%] - */ - public synchronized int getZoom() { - return getZoom(nativeGetZoom(mNativePtr)); - } - - public synchronized void resetZoom() { - if (mNativePtr != 0) { - nativeSetZoom(mNativePtr, mZoomDef); - } - } - -//================================================================================ - public synchronized void updateCameraParams() { - if (mNativePtr != 0) { - if ((mControlSupports == 0) || (mProcSupports == 0)) { - // サポートしている機能フラグを取得 - if (mControlSupports == 0) - mControlSupports = nativeGetCtrlSupports(mNativePtr); - if (mProcSupports == 0) - mProcSupports = nativeGetProcSupports(mNativePtr); - // 設定値を取得 - if ((mControlSupports != 0) && (mProcSupports != 0)) { - nativeUpdateBrightnessLimit(mNativePtr); - nativeUpdateContrastLimit(mNativePtr); - nativeUpdateSharpnessLimit(mNativePtr); - nativeUpdateGainLimit(mNativePtr); - nativeUpdateGammaLimit(mNativePtr); - nativeUpdateSaturationLimit(mNativePtr); - nativeUpdateHueLimit(mNativePtr); - nativeUpdateZoomLimit(mNativePtr); - nativeUpdateWhiteBlanceLimit(mNativePtr); - nativeUpdateFocusLimit(mNativePtr); - } - if (DEBUG) { - dumpControls(mControlSupports); - dumpProc(mProcSupports); - Log.v(TAG, String.format("Brightness:min=%d,max=%d,def=%d", mBrightnessMin, mBrightnessMax, mBrightnessDef)); - Log.v(TAG, String.format("Contrast:min=%d,max=%d,def=%d", mContrastMin, mContrastMax, mContrastDef)); - Log.v(TAG, String.format("Sharpness:min=%d,max=%d,def=%d", mSharpnessMin, mSharpnessMax, mSharpnessDef)); - Log.v(TAG, String.format("Gain:min=%d,max=%d,def=%d", mGainMin, mGainMax, mGainDef)); - Log.v(TAG, String.format("Gamma:min=%d,max=%d,def=%d", mGammaMin, mGammaMax, mGammaDef)); - Log.v(TAG, String.format("Saturation:min=%d,max=%d,def=%d", mSaturationMin, mSaturationMax, mSaturationDef)); - Log.v(TAG, String.format("Hue:min=%d,max=%d,def=%d", mHueMin, mHueMax, mHueDef)); - Log.v(TAG, String.format("Zoom:min=%d,max=%d,def=%d", mZoomMin, mZoomMax, mZoomDef)); - Log.v(TAG, String.format("WhiteBlance:min=%d,max=%d,def=%d", mWhiteBlanceMin, mWhiteBlanceMax, mWhiteBlanceDef)); - Log.v(TAG, String.format("Focus:min=%d,max=%d,def=%d", mFocusMin, mFocusMax, mFocusDef)); - } - } - } else { - mControlSupports = mProcSupports = 0; - } - } - - private static final String[] SUPPORTS_CTRL = { - "D0: Scanning Mode", - "D1: Auto-Exposure Mode", - "D2: Auto-Exposure Priority", - "D3: Exposure Time (Absolute)", - "D4: Exposure Time (Relative)", - "D5: Focus (Absolute)", - "D6: Focus (Relative)", - "D7: Iris (Absolute)", - "D8: Iris (Relative)", - "D9: Zoom (Absolute)", - "D10: Zoom (Relative)", - "D11: PanTilt (Absolute)", - "D12: PanTilt (Relative)", - "D13: Roll (Absolute)", - "D14: Roll (Relative)", - "D15: Reserved", - "D16: Reserved", - "D17: Focus, Auto", - "D18: Privacy", - "D19: Focus, Simple", - "D20: Window", - "D21: Region of Interest", - "D22: Reserved, set to zero", - "D23: Reserved, set to zero", - }; - - private static final String[] SUPPORTS_PROC = { - "D0: Brightness", - "D1: Contrast", - "D2: Hue", - "D3: Saturation", - "D4: Sharpness", - "D5: Gamma", - "D6: White Balance Temperature", - "D7: White Balance Component", - "D8: Backlight Compensation", - "D9: Gain", - "D10: Power Line Frequency", - "D11: Hue, Auto", - "D12: White Balance Temperature, Auto", - "D13: White Balance Component, Auto", - "D14: Digital Multiplier", - "D15: Digital Multiplier Limit", - "D16: Analog Video Standard", - "D17: Analog Video Lock Status", - "D18: Contrast, Auto", - "D19: Reserved. Set to zero", - "D20: Reserved. Set to zero", - "D21: Reserved. Set to zero", - "D22: Reserved. Set to zero", - "D23: Reserved. Set to zero", - }; - - private static final void dumpControls(final long controlSupports) { - Log.i(TAG, String.format("controlSupports=%x", controlSupports)); - for (int i = 0; i < SUPPORTS_CTRL.length; i++) { - Log.i(TAG, SUPPORTS_CTRL[i] + ((controlSupports & (0x1 << i)) != 0 ? "=enabled" : "=disabled")); - } - } - - private static final void dumpProc(final long procSupports) { - Log.i(TAG, String.format("procSupports=%x", procSupports)); - for (int i = 0; i < SUPPORTS_PROC.length; i++) { - Log.i(TAG, SUPPORTS_PROC[i] + ((procSupports & (0x1 << i)) != 0 ? "=enabled" : "=disabled")); - } - } - - private final String getUSBFSName(final UsbControlBlock ctrlBlock) { - String result = null; - final String name = ctrlBlock.getDeviceName(); - final String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null; - if ((v != null) && (v.length > 2)) { - final StringBuilder sb = new StringBuilder(v[0]); - for (int i = 1; i < v.length - 2; i++) - sb.append("/").append(v[i]); - result = sb.toString(); - } - if (TextUtils.isEmpty(result)) { - Log.w(TAG, "failed to get USBFS path, try to use default path:" + name); - result = DEFAULT_USBFS; - } - return result; - } - - // #nativeCreate and #nativeDestroy are not static methods. - private final native long nativeCreate(); - private final native void nativeDestroy(final long id_camera); - - private final native int nativeConnect(long id_camera, int venderId, int productId, int fileDescriptor, int busNum, int devAddr, String usbfs); - private static final native int nativeRelease(final long id_camera); - - private static final native int nativeSetStatusCallback(final long mNativePtr, final IStatusCallback callback); - private static final native int nativeSetButtonCallback(final long mNativePtr, final IButtonCallback callback); - - private static final native int nativeSetPreviewSize(final long id_camera, final int width, final int height, final int min_fps, final int max_fps, final int mode, final float bandwidth); - private static final native String nativeGetSupportedSize(final long id_camera); - private static final native int nativeStartPreview(final long id_camera); - private static final native int nativeStopPreview(final long id_camera); - private static final native int nativeSetPreviewDisplay(final long id_camera, final Surface surface); - private static final native int nativeSetFrameCallback(final long mNativePtr, final IFrameCallback callback, final int pixelFormat); - -//********************************************************************** - /** - * start movie capturing(this should call while previewing) - * @param surface - */ - public void startCapture(final Surface surface) { - if (mCtrlBlock != null && surface != null) { - nativeSetCaptureDisplay(mNativePtr, surface); - } else - throw new NullPointerException("startCapture"); - } - - /** - * stop movie capturing - */ - public void stopCapture() { - if (mCtrlBlock != null) { - nativeSetCaptureDisplay(mNativePtr, null); - } - } - private static final native int nativeSetCaptureDisplay(final long id_camera, final Surface surface); - - private static final native long nativeGetCtrlSupports(final long id_camera); - private static final native long nativeGetProcSupports(final long id_camera); - - private final native int nativeUpdateScanningModeLimit(final long id_camera); - private static final native int nativeSetScanningMode(final long id_camera, final int scanning_mode); - private static final native int nativeGetScanningMode(final long id_camera); - - private final native int nativeUpdateExposureModeLimit(final long id_camera); - private static final native int nativeSetExposureMode(final long id_camera, final int exposureMode); - private static final native int nativeGetExposureMode(final long id_camera); - - private final native int nativeUpdateExposurePriorityLimit(final long id_camera); - private static final native int nativeSetExposurePriority(final long id_camera, final int priority); - private static final native int nativeGetExposurePriority(final long id_camera); - - private final native int nativeUpdateExposureLimit(final long id_camera); - private static final native int nativeSetExposure(final long id_camera, final int exposure); - private static final native int nativeGetExposure(final long id_camera); - - private final native int nativeUpdateExposureRelLimit(final long id_camera); - private static final native int nativeSetExposureRel(final long id_camera, final int exposure_rel); - private static final native int nativeGetExposureRel(final long id_camera); - - private final native int nativeUpdateAutoFocusLimit(final long id_camera); - private static final native int nativeSetAutoFocus(final long id_camera, final boolean autofocus); - private static final native int nativeGetAutoFocus(final long id_camera); - - private final native int nativeUpdateFocusLimit(final long id_camera); - private static final native int nativeSetFocus(final long id_camera, final int focus); - private static final native int nativeGetFocus(final long id_camera); - - private final native int nativeUpdateFocusRelLimit(final long id_camera); - private static final native int nativeSetFocusRel(final long id_camera, final int focus_rel); - private static final native int nativeGetFocusRel(final long id_camera); - - private final native int nativeUpdateIrisLimit(final long id_camera); - private static final native int nativeSetIris(final long id_camera, final int iris); - private static final native int nativeGetIris(final long id_camera); - - private final native int nativeUpdateIrisRelLimit(final long id_camera); - private static final native int nativeSetIrisRel(final long id_camera, final int iris_rel); - private static final native int nativeGetIrisRel(final long id_camera); - - private final native int nativeUpdatePanLimit(final long id_camera); - private static final native int nativeSetPan(final long id_camera, final int pan); - private static final native int nativeGetPan(final long id_camera); - - private final native int nativeUpdatePanRelLimit(final long id_camera); - private static final native int nativeSetPanRel(final long id_camera, final int pan_rel); - private static final native int nativeGetPanRel(final long id_camera); - - private final native int nativeUpdateTiltLimit(final long id_camera); - private static final native int nativeSetTilt(final long id_camera, final int tilt); - private static final native int nativeGetTilt(final long id_camera); - - private final native int nativeUpdateTiltRelLimit(final long id_camera); - private static final native int nativeSetTiltRel(final long id_camera, final int tilt_rel); - private static final native int nativeGetTiltRel(final long id_camera); - - private final native int nativeUpdateRollLimit(final long id_camera); - private static final native int nativeSetRoll(final long id_camera, final int roll); - private static final native int nativeGetRoll(final long id_camera); - - private final native int nativeUpdateRollRelLimit(final long id_camera); - private static final native int nativeSetRollRel(final long id_camera, final int roll_rel); - private static final native int nativeGetRollRel(final long id_camera); - - private final native int nativeUpdateAutoWhiteBlanceLimit(final long id_camera); - private static final native int nativeSetAutoWhiteBlance(final long id_camera, final boolean autoWhiteBlance); - private static final native int nativeGetAutoWhiteBlance(final long id_camera); - - private final native int nativeUpdateAutoWhiteBlanceCompoLimit(final long id_camera); - private static final native int nativeSetAutoWhiteBlanceCompo(final long id_camera, final boolean autoWhiteBlanceCompo); - private static final native int nativeGetAutoWhiteBlanceCompo(final long id_camera); - - private final native int nativeUpdateWhiteBlanceLimit(final long id_camera); - private static final native int nativeSetWhiteBlance(final long id_camera, final int whiteBlance); - private static final native int nativeGetWhiteBlance(final long id_camera); - - private final native int nativeUpdateWhiteBlanceCompoLimit(final long id_camera); - private static final native int nativeSetWhiteBlanceCompo(final long id_camera, final int whiteBlance_compo); - private static final native int nativeGetWhiteBlanceCompo(final long id_camera); - - private final native int nativeUpdateBacklightCompLimit(final long id_camera); - private static final native int nativeSetBacklightComp(final long id_camera, final int backlight_comp); - private static final native int nativeGetBacklightComp(final long id_camera); - - private final native int nativeUpdateBrightnessLimit(final long id_camera); - private static final native int nativeSetBrightness(final long id_camera, final int brightness); - private static final native int nativeGetBrightness(final long id_camera); - - private final native int nativeUpdateContrastLimit(final long id_camera); - private static final native int nativeSetContrast(final long id_camera, final int contrast); - private static final native int nativeGetContrast(final long id_camera); - - private final native int nativeUpdateAutoContrastLimit(final long id_camera); - private static final native int nativeSetAutoContrast(final long id_camera, final boolean autocontrast); - private static final native int nativeGetAutoContrast(final long id_camera); - - private final native int nativeUpdateSharpnessLimit(final long id_camera); - private static final native int nativeSetSharpness(final long id_camera, final int sharpness); - private static final native int nativeGetSharpness(final long id_camera); - - private final native int nativeUpdateGainLimit(final long id_camera); - private static final native int nativeSetGain(final long id_camera, final int gain); - private static final native int nativeGetGain(final long id_camera); - - private final native int nativeUpdateGammaLimit(final long id_camera); - private static final native int nativeSetGamma(final long id_camera, final int gamma); - private static final native int nativeGetGamma(final long id_camera); - - private final native int nativeUpdateSaturationLimit(final long id_camera); - private static final native int nativeSetSaturation(final long id_camera, final int saturation); - private static final native int nativeGetSaturation(final long id_camera); - - private final native int nativeUpdateHueLimit(final long id_camera); - private static final native int nativeSetHue(final long id_camera, final int hue); - private static final native int nativeGetHue(final long id_camera); - - private final native int nativeUpdateAutoHueLimit(final long id_camera); - private static final native int nativeSetAutoHue(final long id_camera, final boolean autohue); - private static final native int nativeGetAutoHue(final long id_camera); - - private final native int nativeUpdatePowerlineFrequencyLimit(final long id_camera); - private static final native int nativeSetPowerlineFrequency(final long id_camera, final int frequency); - private static final native int nativeGetPowerlineFrequency(final long id_camera); - - private final native int nativeUpdateZoomLimit(final long id_camera); - private static final native int nativeSetZoom(final long id_camera, final int zoom); - private static final native int nativeGetZoom(final long id_camera); - - private final native int nativeUpdateZoomRelLimit(final long id_camera); - private static final native int nativeSetZoomRel(final long id_camera, final int zoom_rel); - private static final native int nativeGetZoomRel(final long id_camera); - - private final native int nativeUpdateDigitalMultiplierLimit(final long id_camera); - private static final native int nativeSetDigitalMultiplier(final long id_camera, final int multiplier); - private static final native int nativeGetDigitalMultiplier(final long id_camera); - - private final native int nativeUpdateDigitalMultiplierLimitLimit(final long id_camera); - private static final native int nativeSetDigitalMultiplierLimit(final long id_camera, final int multiplier_limit); - private static final native int nativeGetDigitalMultiplierLimit(final long id_camera); - - private final native int nativeUpdateAnalogVideoStandardLimit(final long id_camera); - private static final native int nativeSetAnalogVideoStandard(final long id_camera, final int standard); - private static final native int nativeGetAnalogVideoStandard(final long id_camera); - - private final native int nativeUpdateAnalogVideoLockStateLimit(final long id_camera); - private static final native int nativeSetAnalogVideoLoackState(final long id_camera, final int state); - private static final native int nativeGetAnalogVideoLoackState(final long id_camera); - - private final native int nativeUpdatePrivacyLimit(final long id_camera); - private static final native int nativeSetPrivacy(final long id_camera, final boolean privacy); - private static final native int nativeGetPrivacy(final long id_camera); -} diff --git a/phenolib/src/main/java/com/serenegiant/usbcameracommon/AbstractUVCCameraHandler.java b/phenolib/src/main/java/com/serenegiant/usbcameracommon/AbstractUVCCameraHandler.java deleted file mode 100644 index 4d21436b..00000000 --- a/phenolib/src/main/java/com/serenegiant/usbcameracommon/AbstractUVCCameraHandler.java +++ /dev/null @@ -1,842 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usbcameracommon; - -import android.app.Activity; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.SurfaceTexture; -import android.hardware.usb.UsbDevice; -import android.media.AudioManager; -import android.media.MediaScannerConnection; -import android.media.SoundPool; -import android.os.Environment; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.text.TextUtils; -import android.util.Log; -import android.view.Surface; -import android.view.SurfaceHolder; - -import com.serenegiant.encoder.MediaAudioEncoder; -import com.serenegiant.encoder.MediaEncoder; -import com.serenegiant.encoder.MediaMuxerWrapper; -import com.serenegiant.encoder.MediaSurfaceEncoder; -import com.serenegiant.encoder.MediaVideoBufferEncoder; -import com.serenegiant.encoder.MediaVideoEncoder; -import com.serenegiant.usb.IFrameCallback; -import com.serenegiant.usb.USBMonitor; -import com.serenegiant.usb.UVCCamera; -import com.serenegiant.widget.CameraViewInterface; - -import org.phenoapps.androidlibrary.R; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - -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); - } - - 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 final WeakReference mWeakThread; - private volatile boolean mReleased; - - 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 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 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 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"); - } - - protected 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"); - } - sendMessage(obtainMessage(MSG_PREVIEW_START, surface)); - } - - public void stopPreview() { - if (DEBUG) Log.v(TAG, "stopPreview:"); - removeMessages(MSG_PREVIEW_START); - 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"); - } - - protected void captureStill() { - checkReleased(); - sendEmptyMessage(MSG_CAPTURE_STILL); - } - - protected void captureStill(final String path) { - checkReleased(); - sendMessage(obtainMessage(MSG_CAPTURE_STILL, path)); - } - - public void startRecording() { - checkReleased(); - sendEmptyMessage(MSG_CAPTURE_START); - } - - public void stopRecording() { - sendEmptyMessage(MSG_CAPTURE_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: - thread.handleCaptureStill((String)msg.obj); - break; - case MSG_CAPTURE_START: - thread.handleStartRecording(); - break; - case MSG_CAPTURE_STOP: - thread.handleStopRecording(); - break; - case MSG_MEDIA_UPDATE: - thread.handleUpdateMedia((String)msg.obj); - break; - case MSG_RELEASE: - thread.handleRelease(); - break; - default: - throw new RuntimeException("unsupported message:what=" + msg.what); - } - } - - 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; - /** - * shutter sound - */ - private SoundPool mSoundPool; - private int mSoundId; - private AbstractUVCCameraHandler mHandler; - /** - * for accessing UVC camera - */ - private UVCCamera mUVCCamera; - /** - * muxer for audio/video recording - */ - private MediaMuxerWrapper mMuxer; - private MediaVideoBufferEncoder mVideoEncoder; - - /** - * - * @param clazz Class extends AbstractUVCCameraHandler - * @param parent parent Activity - * @param cameraView for still capturing - * @param encoderType 0: use MediaSurfaceEncoder, 1: use MediaVideoEncoder, 2: use MediaVideoBufferEncoder - * @param width - * @param height - * @param format either FRAME_FORMAT_YUYV(0) or FRAME_FORMAT_MJPEG(1) - * @param 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); - } - } - - 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); - } 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(); - } - 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(); - // 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, ".png") - : new File(path); - final BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile)); - try { - try { - bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); - os.flush(); - mHandler.sendMessage(mHandler.obtainMessage(MSG_MEDIA_UPDATE, outputFile.getPath())); - } catch (final IOException e) { - } - } finally { - os.close(); - } - } catch (final Exception e) { - callOnError(e); - } - } - - public void handleStartRecording() { - if (DEBUG) Log.v(TAG_THREAD, "handleStartRecording:"); - try { - if ((mUVCCamera == null) || (mMuxer != null)) return; - final MediaMuxerWrapper muxer = new MediaMuxerWrapper(".mp4"); // if you record audio only, ".m4a" is also OK. - MediaVideoBufferEncoder videoEncoder = null; - switch (mEncoderType) { - case 1: // for video capturing using MediaVideoEncoder - new MediaVideoEncoder(muxer, getWidth(), getHeight(), mMediaEncoderListener); - break; - case 2: // for video capturing using MediaVideoBufferEncoder - videoEncoder = new MediaVideoBufferEncoder(muxer, getWidth(), getHeight(), mMediaEncoderListener); - break; - // case 0: // for video capturing using MediaSurfaceEncoder - default: - new MediaSurfaceEncoder(muxer, getWidth(), getHeight(), mMediaEncoderListener); - break; - } - if (true) { - // for audio capturing - new MediaAudioEncoder(muxer, mMediaEncoderListener); - } - muxer.prepare(); - muxer.startRecording(); - if (videoEncoder != null) { - mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21); - } - synchronized (mSync) { - mMuxer = muxer; - mVideoEncoder = videoEncoder; - } - callOnStartRecording(); - } catch (final IOException e) { - callOnError(e); - Log.e(TAG, "startCapture:", e); - } - } - - public void handleStopRecording() { - if (DEBUG) Log.v(TAG_THREAD, "handleStopRecording:mMuxer=" + mMuxer); - final MediaMuxerWrapper muxer; - synchronized (mSync) { - muxer = mMuxer; - mMuxer = null; - mVideoEncoder = null; - if (mUVCCamera != null) { - mUVCCamera.stopCapture(); - } - } - try { - mWeakCameraView.get().setVideoEncoder(null); - } catch (final Exception e) { - // ignore - } - if (muxer != null) { - muxer.stopRecording(); - mUVCCamera.setFrameCallback(null, 0); - // you should not wait here - callOnStopRecording(); - } - } - - private final IFrameCallback mIFrameCallback = new IFrameCallback() { - @Override - public void onFrame(final ByteBuffer frame) { - final MediaVideoBufferEncoder videoEncoder; - synchronized (mSync) { - videoEncoder = mVideoEncoder; - } - if (videoEncoder != null) { - videoEncoder.frameAvailableSoon(); - videoEncoder.encode(frame); - } - } - }; - - 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"); - } - - 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); - } - } - - @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); - } - } - }; - - /** - * 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; - try { - final Class audioSystemClass = Class.forName("android.media.AudioSystem"); - final Field sseField = audioSystemClass.getDeclaredField("STREAM_SYSTEM_ENFORCED"); - streamType = sseField.getInt(null); - } catch (final Exception e) { - streamType = AudioManager.STREAM_SYSTEM; // set appropriate according to your app policy - } - if (mSoundPool != null) { - try { - mSoundPool.release(); - } catch (final Exception e) { - } - mSoundPool = null; - } - // load shutter sound from resource - mSoundPool = new SoundPool(2, streamType, 0); - 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(); - 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); - } - } - } - } -} diff --git a/phenolib/src/main/java/com/serenegiant/usbcameracommon/UVCCameraHandler.java b/phenolib/src/main/java/com/serenegiant/usbcameracommon/UVCCameraHandler.java deleted file mode 100644 index d48cb5bc..00000000 --- a/phenolib/src/main/java/com/serenegiant/usbcameracommon/UVCCameraHandler.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usbcameracommon; - -import android.app.Activity; - -import com.serenegiant.usb.UVCCamera; -import com.serenegiant.widget.CameraViewInterface; - -public class UVCCameraHandler extends AbstractUVCCameraHandler { - - /** - * create UVCCameraHandler, use MediaVideoEncoder, try MJPEG, default bandwidth - * @param parent - * @param cameraView - * @param width - * @param height - * @return - */ - public static final UVCCameraHandler createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int width, final int height) { - - return createHandler(parent, cameraView, 1, width, height, UVCCamera.FRAME_FORMAT_MJPEG, UVCCamera.DEFAULT_BANDWIDTH); - } - - /** - * create UVCCameraHandler, use MediaVideoEncoder, try MJPEG - * @param parent - * @param cameraView - * @param width - * @param height - * @param bandwidthFactor - * @return - */ - public static final UVCCameraHandler createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int width, final int height, final float bandwidthFactor) { - - return createHandler(parent, cameraView, 1, width, height, UVCCamera.FRAME_FORMAT_MJPEG, bandwidthFactor); - } - - /** - * create UVCCameraHandler, try MJPEG, default bandwidth - * @param parent - * @param cameraView - * @param encoderType 0: use MediaSurfaceEncoder, 1: use MediaVideoEncoder, 2: use MediaVideoBufferEncoder - * @param width - * @param height - * @return - */ - public static final UVCCameraHandler createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int encoderType, final int width, final int height) { - - return createHandler(parent, cameraView, encoderType, width, height, UVCCamera.FRAME_FORMAT_MJPEG, UVCCamera.DEFAULT_BANDWIDTH); - } - - /** - * create UVCCameraHandler, default bandwidth - * @param parent - * @param cameraView - * @param encoderType 0: use MediaSurfaceEncoder, 1: use MediaVideoEncoder, 2: use MediaVideoBufferEncoder - * @param width - * @param height - * @param format either UVCCamera.FRAME_FORMAT_YUYV(0) or UVCCamera.FRAME_FORMAT_MJPEG(1) - * @return - */ - public static final UVCCameraHandler createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int encoderType, final int width, final int height, final int format) { - - return createHandler(parent, cameraView, encoderType, width, height, format, UVCCamera.DEFAULT_BANDWIDTH); - } - - /** - * create UVCCameraHandler - * @param parent - * @param cameraView - * @param encoderType 0: use MediaSurfaceEncoder, 1: use MediaVideoEncoder, 2: use MediaVideoBufferEncoder - * @param width - * @param height - * @param format either UVCCamera.FRAME_FORMAT_YUYV(0) or UVCCamera.FRAME_FORMAT_MJPEG(1) - * @param bandwidthFactor - * @return - */ - public static final UVCCameraHandler createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int encoderType, final int width, final int height, final int format, final float bandwidthFactor) { - - final CameraThread thread = new CameraThread(UVCCameraHandler.class, parent, cameraView, encoderType, width, height, format, bandwidthFactor); - thread.start(); - return (UVCCameraHandler)thread.getHandler(); - } - - protected UVCCameraHandler(final CameraThread thread) { - super(thread); - } - - @Override - public void startPreview(final Object surface) { - super.startPreview(surface); - } - - @Override - public void captureStill() { - super.captureStill(); - } - - @Override - public void captureStill(final String path) { - super.captureStill(path); - } -} diff --git a/phenolib/src/main/java/com/serenegiant/usbcameracommon/UVCCameraHandlerMultiSurface.java b/phenolib/src/main/java/com/serenegiant/usbcameracommon/UVCCameraHandlerMultiSurface.java deleted file mode 100644 index 166794a5..00000000 --- a/phenolib/src/main/java/com/serenegiant/usbcameracommon/UVCCameraHandlerMultiSurface.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.usbcameracommon; - -import android.app.Activity; -import android.view.Surface; - -import com.serenegiant.glutils.RendererHolder; -import com.serenegiant.usb.UVCCamera; -import com.serenegiant.widget.CameraViewInterface; - -public class UVCCameraHandlerMultiSurface extends AbstractUVCCameraHandler { - /** - * create UVCCameraHandlerMultiSurface, use MediaVideoEncoder, try MJPEG, default bandwidth - * @param parent - * @param cameraView - * @param width - * @param height - * @return - */ - public static final UVCCameraHandlerMultiSurface createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int width, final int height) { - - return createHandler(parent, cameraView, 1, width, height, UVCCamera.FRAME_FORMAT_MJPEG, UVCCamera.DEFAULT_BANDWIDTH); - } - - /** - * create UVCCameraHandlerMultiSurface, use MediaVideoEncoder, try MJPEG - * @param parent - * @param cameraView - * @param width - * @param height - * @param bandwidthFactor - * @return - */ - public static final UVCCameraHandlerMultiSurface createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int width, final int height, final float bandwidthFactor) { - - return createHandler(parent, cameraView, 1, width, height, UVCCamera.FRAME_FORMAT_MJPEG, bandwidthFactor); - } - - /** - * create UVCCameraHandlerMultiSurface, try MJPEG, default bandwidth - * @param parent - * @param cameraView - * @param encoderType - * @param width - * @param height - * @return - */ - public static final UVCCameraHandlerMultiSurface createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int encoderType, final int width, final int height) { - - return createHandler(parent, cameraView, encoderType, width, height, UVCCamera.FRAME_FORMAT_MJPEG, UVCCamera.DEFAULT_BANDWIDTH); - } - - /** - * create UVCCameraHandlerMultiSurface, default bandwidth - * @param parent - * @param cameraView - * @param encoderType - * @param width - * @param height - * @param format - * @return - */ - public static final UVCCameraHandlerMultiSurface createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int encoderType, final int width, final int height, final int format) { - - return createHandler(parent, cameraView, encoderType, width, height, format, UVCCamera.DEFAULT_BANDWIDTH); - } - - /** - * create UVCCameraHandlerMultiSurface - * @param parent - * @param cameraView - * @param encoderType 0: use MediaSurfaceEncoder, 1: use MediaVideoEncoder, 2: use MediaVideoBufferEncoder - * @param width - * @param height - * @param format either UVCCamera.FRAME_FORMAT_YUYV(0) or UVCCamera.FRAME_FORMAT_MJPEG(1) - * @param bandwidthFactor - * @return - */ - public static final UVCCameraHandlerMultiSurface createHandler( - final Activity parent, final CameraViewInterface cameraView, - final int encoderType, final int width, final int height, final int format, final float bandwidthFactor) { - - final CameraThread thread = new CameraThread(UVCCameraHandlerMultiSurface.class, parent, cameraView, encoderType, width, height, format, bandwidthFactor); - thread.start(); - return (UVCCameraHandlerMultiSurface)thread.getHandler(); - } - - private RendererHolder mRendererHolder; - protected UVCCameraHandlerMultiSurface(final CameraThread thread) { - super(thread); - mRendererHolder = new RendererHolder(thread.getWidth(), thread.getHeight(), null); - } - - public synchronized void release() { - if (mRendererHolder != null) { - mRendererHolder.release(); - mRendererHolder = null; - } - super.release(); - } - - public synchronized void resize(final int width, final int height) { - super.resize(width, height); - if (mRendererHolder != null) { - mRendererHolder.resize(width, height); - } - } - - public synchronized void startPreview() { - checkReleased(); - if (mRendererHolder != null) { - super.startPreview(mRendererHolder.getSurface()); - } else { - throw new IllegalStateException(); - } - } - - public synchronized void addSurface(final int surfaceId, final Surface surface, final boolean isRecordable) { - checkReleased(); - mRendererHolder.addSurface(surfaceId, surface, isRecordable); - } - - public synchronized void removeSurface(final int surfaceId) { - if (mRendererHolder != null) { - mRendererHolder.removeSurface(surfaceId); - } - } - - @Override - public void captureStill() { - checkReleased(); - super.captureStill(); - } - - @Override - public void captureStill(final String path) { - checkReleased(); - post(new Runnable() { - @Override - public void run() { - synchronized (UVCCameraHandlerMultiSurface.this) { - if (mRendererHolder != null) { - mRendererHolder.captureStill(path); - updateMedia(path); - } - } - } - }); - } -} diff --git a/phenolib/src/main/java/com/serenegiant/widget/AspectRatioTextureView.java b/phenolib/src/main/java/com/serenegiant/widget/AspectRatioTextureView.java deleted file mode 100644 index acace03a..00000000 --- a/phenolib/src/main/java/com/serenegiant/widget/AspectRatioTextureView.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.widget; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.TextureView; - -/** - * change the view size with keeping the specified aspect ratio. - * if you set this view with in a FrameLayout and set property "android:layout_gravity="center", - * you can show this view in the center of screen and keep the aspect ratio of content - * XXX it is better that can set the aspect ratio as xml property - */ -public class AspectRatioTextureView extends TextureView // API >= 14 - implements IAspectRatioView { - - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "AbstractCameraView"; - - private double mRequestedAspect = -1.0; - private CameraViewInterface.Callback mCallback; - - public AspectRatioTextureView(final Context context) { - this(context, null, 0); - } - - public AspectRatioTextureView(final Context context, final AttributeSet attrs) { - this(context, attrs, 0); - } - - public AspectRatioTextureView(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public void setAspectRatio(final double aspectRatio) { - if (aspectRatio < 0) { - throw new IllegalArgumentException(); - } - if (mRequestedAspect != aspectRatio) { - mRequestedAspect = aspectRatio; - requestLayout(); - } - } - - @Override - public void setAspectRatio(final int width, final int height) { - setAspectRatio(width / (double)height); - } - - @Override - public double getAspectRatio() { - return mRequestedAspect; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - - if (mRequestedAspect > 0) { - int initialWidth = MeasureSpec.getSize(widthMeasureSpec); - int initialHeight = MeasureSpec.getSize(heightMeasureSpec); - - final int horizPadding = getPaddingLeft() + getPaddingRight(); - final int vertPadding = getPaddingTop() + getPaddingBottom(); - initialWidth -= horizPadding; - initialHeight -= vertPadding; - - final double viewAspectRatio = (double)initialWidth / initialHeight; - final double aspectDiff = mRequestedAspect / viewAspectRatio - 1; - - if (Math.abs(aspectDiff) > 0.01) { - if (aspectDiff > 0) { - // width priority decision - initialHeight = (int) (initialWidth / mRequestedAspect); - } else { - // height priority decision - initialWidth = (int) (initialHeight * mRequestedAspect); - } - initialWidth += horizPadding; - initialHeight += vertPadding; - widthMeasureSpec = MeasureSpec.makeMeasureSpec(initialWidth, MeasureSpec.EXACTLY); - heightMeasureSpec = MeasureSpec.makeMeasureSpec(initialHeight, MeasureSpec.EXACTLY); - } - } - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - -} diff --git a/phenolib/src/main/java/com/serenegiant/widget/CameraViewInterface.java b/phenolib/src/main/java/com/serenegiant/widget/CameraViewInterface.java deleted file mode 100644 index 8d4b1888..00000000 --- a/phenolib/src/main/java/com/serenegiant/widget/CameraViewInterface.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.widget; - -import android.graphics.Bitmap; -import android.graphics.SurfaceTexture; -import android.view.Surface; - -import com.serenegiant.encoder.IVideoEncoder; - -public interface CameraViewInterface extends IAspectRatioView { - public interface Callback { - public void onSurfaceCreated(CameraViewInterface view, Surface surface); - public void onSurfaceChanged(CameraViewInterface view, Surface surface, int width, int height); - public void onSurfaceDestroy(CameraViewInterface view, Surface surface); - } - public void onPause(); - public void onResume(); - public void setCallback(Callback callback); - public SurfaceTexture getSurfaceTexture(); - public Surface getSurface(); - public boolean hasSurface(); - public void setVideoEncoder(final IVideoEncoder encoder); - public Bitmap captureStillImage(); -} diff --git a/phenolib/src/main/java/com/serenegiant/widget/UVCCameraTextureView.java b/phenolib/src/main/java/com/serenegiant/widget/UVCCameraTextureView.java deleted file mode 100644 index e92d4fb9..00000000 --- a/phenolib/src/main/java/com/serenegiant/widget/UVCCameraTextureView.java +++ /dev/null @@ -1,595 +0,0 @@ -/* - * UVCCamera - * library and sample to access to UVC web camera on non-rooted Android device - * - * Copyright (c) 2014-2017 saki t_saki@serenegiant.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * All files in the folder are under this Apache License, Version 2.0. - * Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder - * may have a different license, see the respective files. - */ - -package com.serenegiant.widget; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.SurfaceTexture; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Surface; -import android.view.TextureView; - -import com.serenegiant.encoder.IVideoEncoder; -import com.serenegiant.encoder.MediaEncoder; -import com.serenegiant.encoder.MediaVideoEncoder; -import com.serenegiant.glutils.EGLBase; -import com.serenegiant.glutils.GLDrawer2D; -import com.serenegiant.glutils.es1.GLHelper; -import com.serenegiant.utils.FpsCounter; - -/** - * change the view size with keeping the specified aspect ratio. - * if you set this view with in a FrameLayout and set property "android:layout_gravity="center", - * you can show this view in the center of screen and keep the aspect ratio of content - * XXX it is better that can set the aspect ratio as xml property - */ -public class UVCCameraTextureView extends AspectRatioTextureView // API >= 14 - implements TextureView.SurfaceTextureListener, CameraViewInterface { - - private static final boolean DEBUG = true; // TODO set false on release - private static final String TAG = "UVCCameraTextureView"; - - private boolean mHasSurface; - private RenderHandler mRenderHandler; - private final Object mCaptureSync = new Object(); - private Bitmap mTempBitmap; - private boolean mReqesutCaptureStillImage; - private Callback mCallback; - /** for calculation of frame rate */ - private final FpsCounter mFpsCounter = new FpsCounter(); - - public UVCCameraTextureView(final Context context) { - this(context, null, 0); - } - - public UVCCameraTextureView(final Context context, final AttributeSet attrs) { - this(context, attrs, 0); - } - - public UVCCameraTextureView(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - setSurfaceTextureListener(this); - } - - @Override - public void onResume() { - if (DEBUG) Log.v(TAG, "onResume:"); - if (mHasSurface) { - mRenderHandler = RenderHandler.createHandler(mFpsCounter, super.getSurfaceTexture(), getWidth(), getHeight()); - } - } - - @Override - public void onPause() { - if (DEBUG) Log.v(TAG, "onPause:"); - if (mRenderHandler != null) { - mRenderHandler.release(); - mRenderHandler = null; - } - if (mTempBitmap != null) { - mTempBitmap.recycle(); - mTempBitmap = null; - } - } - - @Override - public void onSurfaceTextureAvailable(final SurfaceTexture surface, final int width, final int height) { - if (DEBUG) Log.v(TAG, "onSurfaceTextureAvailable:" + surface); - if (mRenderHandler == null) { - mRenderHandler = RenderHandler.createHandler(mFpsCounter, surface, width, height); - } else { - mRenderHandler.resize(width, height); - } - mHasSurface = true; - if (mCallback != null) { - mCallback.onSurfaceCreated(this, getSurface()); - } - } - - @Override - public void onSurfaceTextureSizeChanged(final SurfaceTexture surface, final int width, final int height) { - if (DEBUG) Log.v(TAG, "onSurfaceTextureSizeChanged:" + surface); - if (mRenderHandler != null) { - mRenderHandler.resize(width, height); - } - if (mCallback != null) { - mCallback.onSurfaceChanged(this, getSurface(), width, height); - } - } - - @Override - public boolean onSurfaceTextureDestroyed(final SurfaceTexture surface) { - if (DEBUG) Log.v(TAG, "onSurfaceTextureDestroyed:" + surface); - if (mRenderHandler != null) { - mRenderHandler.release(); - mRenderHandler = null; - } - mHasSurface = false; - if (mCallback != null) { - mCallback.onSurfaceDestroy(this, getSurface()); - } - if (mPreviewSurface != null) { - mPreviewSurface.release(); - mPreviewSurface = null; - } - return true; - } - - @Override - public void onSurfaceTextureUpdated(final SurfaceTexture surface) { - synchronized (mCaptureSync) { - if (mReqesutCaptureStillImage) { - mReqesutCaptureStillImage = false; - if (mTempBitmap == null) - mTempBitmap = getBitmap(); - else - getBitmap(mTempBitmap); - mCaptureSync.notifyAll(); - } - } - } - - @Override - public boolean hasSurface() { - return mHasSurface; - } - - /** - * capture preview image as a bitmap - * this method blocks current thread until bitmap is ready - * if you call this method at almost same time from different thread, - * the returned bitmap will be changed while you are processing the bitmap - * (because we return same instance of bitmap on each call for memory saving) - * if you need to call this method from multiple thread, - * you should change this method(copy and return) - */ - @Override - public Bitmap captureStillImage() { - synchronized (mCaptureSync) { - mReqesutCaptureStillImage = true; - try { - mCaptureSync.wait(); - } catch (final InterruptedException e) { - } - return mTempBitmap; - } - } - - @Override - public SurfaceTexture getSurfaceTexture() { - return mRenderHandler != null ? mRenderHandler.getPreviewTexture() : null; - } - - private Surface mPreviewSurface; - @Override - public Surface getSurface() { - if (DEBUG) Log.v(TAG, "getSurface:hasSurface=" + mHasSurface); - if (mPreviewSurface == null) { - final SurfaceTexture st = getSurfaceTexture(); - if (st != null) { - mPreviewSurface = new Surface(st); - } - } - return mPreviewSurface; - } - - @Override - public void setVideoEncoder(final IVideoEncoder encoder) { - if (mRenderHandler != null) - mRenderHandler.setVideoEncoder(encoder); - } - - @Override - public void setCallback(final Callback callback) { - mCallback = callback; - } - - public void resetFps() { - mFpsCounter.reset(); - } - - /** update frame rate of image processing */ - public void updateFps() { - mFpsCounter.update(); - } - - /** - * get current frame rate of image processing - * @return - */ - public float getFps() { - return mFpsCounter.getFps(); - } - - /** - * get total frame rate from start - * @return - */ - public float getTotalFps() { - return mFpsCounter.getTotalFps(); - } - - /** - * render camera frames on this view on a private thread - * @author saki - * - */ - private static final class RenderHandler extends Handler - implements SurfaceTexture.OnFrameAvailableListener { - - private static final int MSG_REQUEST_RENDER = 1; - private static final int MSG_SET_ENCODER = 2; - private static final int MSG_CREATE_SURFACE = 3; - private static final int MSG_RESIZE = 4; - private static final int MSG_TERMINATE = 9; - - private RenderThread mThread; - private boolean mIsActive = true; - private final FpsCounter mFpsCounter; - - public static final RenderHandler createHandler(final FpsCounter counter, - final SurfaceTexture surface, final int width, final int height) { - - final RenderThread thread = new RenderThread(counter, surface, width, height); - thread.start(); - return thread.getHandler(); - } - - private RenderHandler(final FpsCounter counter, final RenderThread thread) { - mThread = thread; - mFpsCounter = counter; - } - - public final void setVideoEncoder(final IVideoEncoder encoder) { - if (DEBUG) Log.v(TAG, "setVideoEncoder:"); - if (mIsActive) - sendMessage(obtainMessage(MSG_SET_ENCODER, encoder)); - } - - public final SurfaceTexture getPreviewTexture() { - if (DEBUG) Log.v(TAG, "getPreviewTexture:"); - if (mIsActive) { - synchronized (mThread.mSync) { - sendEmptyMessage(MSG_CREATE_SURFACE); - try { - mThread.mSync.wait(); - } catch (final InterruptedException e) { - } - return mThread.mPreviewSurface; - } - } else { - return null; - } - } - - public void resize(final int width, final int height) { - if (DEBUG) Log.v(TAG, "resize:"); - if (mIsActive) { - synchronized (mThread.mSync) { - sendMessage(obtainMessage(MSG_RESIZE, width, height)); - try { - mThread.mSync.wait(); - } catch (final InterruptedException e) { - } - } - } - } - - public final void release() { - if (DEBUG) Log.v(TAG, "release:"); - if (mIsActive) { - mIsActive = false; - removeMessages(MSG_REQUEST_RENDER); - removeMessages(MSG_SET_ENCODER); - sendEmptyMessage(MSG_TERMINATE); - } - } - - @Override - public final void onFrameAvailable(final SurfaceTexture surfaceTexture) { - if (mIsActive) { - mFpsCounter.count(); - sendEmptyMessage(MSG_REQUEST_RENDER); - } - } - - @Override - public final void handleMessage(final Message msg) { - if (mThread == null) return; - switch (msg.what) { - case MSG_REQUEST_RENDER: - mThread.onDrawFrame(); - break; - case MSG_SET_ENCODER: - mThread.setEncoder((MediaEncoder)msg.obj); - break; - case MSG_CREATE_SURFACE: - mThread.updatePreviewSurface(); - break; - case MSG_RESIZE: - mThread.resize(msg.arg1, msg.arg2); - break; - case MSG_TERMINATE: - Looper.myLooper().quit(); - mThread = null; - break; - default: - super.handleMessage(msg); - } - } - - private static final class RenderThread extends Thread { - private final Object mSync = new Object(); - private final SurfaceTexture mSurface; - private RenderHandler mHandler; - private EGLBase mEgl; - /** IEglSurface instance related to this TextureView */ - private EGLBase.IEglSurface mEglSurface; - private GLDrawer2D mDrawer; - private int mTexId = -1; - /** SurfaceTexture instance to receive video images */ - private SurfaceTexture mPreviewSurface; - private final float[] mStMatrix = new float[16]; - private MediaEncoder mEncoder; - private int mViewWidth, mViewHeight; - private final FpsCounter mFpsCounter; - - /** - * constructor - * @param surface: drawing surface came from TexureView - */ - public RenderThread(final FpsCounter fpsCounter, final SurfaceTexture surface, final int width, final int height) { - mFpsCounter = fpsCounter; - mSurface = surface; - mViewWidth = width; - mViewHeight = height; - setName("RenderThread"); - } - - public final RenderHandler getHandler() { - if (DEBUG) Log.v(TAG, "RenderThread#getHandler:"); - synchronized (mSync) { - // create rendering thread - if (mHandler == null) - try { - mSync.wait(); - } catch (final InterruptedException e) { - } - } - return mHandler; - } - - public void resize(final int width, final int height) { - if (((width > 0) && (width != mViewWidth)) || ((height > 0) && (height != mViewHeight))) { - mViewWidth = width; - mViewHeight = height; - updatePreviewSurface(); - } else { - synchronized (mSync) { - mSync.notifyAll(); - } - } - } - - public final void updatePreviewSurface() { - if (DEBUG) Log.i(TAG, "RenderThread#updatePreviewSurface:"); - synchronized (mSync) { - if (mPreviewSurface != null) { - if (DEBUG) Log.d(TAG, "updatePreviewSurface:release mPreviewSurface"); - mPreviewSurface.setOnFrameAvailableListener(null); - mPreviewSurface.release(); - mPreviewSurface = null; - } - mEglSurface.makeCurrent(); - if (mTexId >= 0) { - mDrawer.deleteTex(mTexId); - } - // create texture and SurfaceTexture for input from camera - mTexId = mDrawer.initTex(); - if (DEBUG) Log.v(TAG, "updatePreviewSurface:tex_id=" + mTexId); - mPreviewSurface = new SurfaceTexture(mTexId); - mPreviewSurface.setDefaultBufferSize(mViewWidth, mViewHeight); - mPreviewSurface.setOnFrameAvailableListener(mHandler); - // notify to caller thread that previewSurface is ready - mSync.notifyAll(); - } - } - - public final void setEncoder(final MediaEncoder encoder) { - if (DEBUG) Log.v(TAG, "RenderThread#setEncoder:encoder=" + encoder); - if (encoder != null && (encoder instanceof MediaVideoEncoder)) { - ((MediaVideoEncoder)encoder).setEglContext(mEglSurface.getContext(), mTexId); - } - mEncoder = encoder; - } - -/* - * Now you can get frame data as ByteBuffer(as YUV/RGB565/RGBX/NV21 pixel format) using IFrameCallback interface - * with UVCCamera#setFrameCallback instead of using following code samples. - */ -/* // for part1 - private static final int BUF_NUM = 1; - private static final int BUF_STRIDE = 640 * 480; - private static final int BUF_SIZE = BUF_STRIDE * BUF_NUM; - int cnt = 0; - int offset = 0; - final int pixels[] = new int[BUF_SIZE]; - final IntBuffer buffer = IntBuffer.wrap(pixels); */ -/* // for part2 - private ByteBuffer buf = ByteBuffer.allocateDirect(640 * 480 * 4); - */ - /** - * draw a frame (and request to draw for video capturing if it is necessary) - */ - public final void onDrawFrame() { - mEglSurface.makeCurrent(); - // update texture(came from camera) - mPreviewSurface.updateTexImage(); - // get texture matrix - mPreviewSurface.getTransformMatrix(mStMatrix); - // notify video encoder if it exist - if (mEncoder != null) { - // notify to capturing thread that the camera frame is available. - if (mEncoder instanceof MediaVideoEncoder) - ((MediaVideoEncoder)mEncoder).frameAvailableSoon(mStMatrix); - else - mEncoder.frameAvailableSoon(); - } - // draw to preview screen - mDrawer.draw(mTexId, mStMatrix, 0); - mEglSurface.swap(); -/* // sample code to read pixels into Buffer and save as a Bitmap (part1) - buffer.position(offset); - GLES20.glReadPixels(0, 0, 640, 480, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer); - if (++cnt == 100) { // save as a Bitmap, only once on this sample code - // if you save every frame as a Bitmap, app will crash by Out of Memory exception... - Log.i(TAG, "Capture image using glReadPixels:offset=" + offset); - final Bitmap bitmap = createBitmap(pixels,offset, 640, 480); - final File outputFile = MediaMuxerWrapper.getCaptureFile(Environment.DIRECTORY_DCIM, ".png"); - try { - final BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile)); - try { - try { - bitmap.compress(CompressFormat.PNG, 100, os); - os.flush(); - bitmap.recycle(); - } catch (IOException e) { - } - } finally { - os.close(); - } - } catch (FileNotFoundException e) { - } catch (IOException e) { - } - } - offset = (offset + BUF_STRIDE) % BUF_SIZE; -*/ -/* // sample code to read pixels into Buffer and save as a Bitmap (part2) - buf.order(ByteOrder.LITTLE_ENDIAN); // it is enough to call this only once. - GLES20.glReadPixels(0, 0, 640, 480, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf); - buf.rewind(); - if (++cnt == 100) { // save as a Bitmap, only once on this sample code - // if you save every frame as a Bitmap, app will crash by Out of Memory exception... - final File outputFile = MediaMuxerWrapper.getCaptureFile(Environment.DIRECTORY_DCIM, ".png"); - BufferedOutputStream os = null; - try { - try { - os = new BufferedOutputStream(new FileOutputStream(outputFile)); - Bitmap bmp = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888); - bmp.copyPixelsFromBuffer(buf); - bmp.compress(Bitmap.CompressFormat.PNG, 90, os); - bmp.recycle(); - } finally { - if (os != null) os.close(); - } - } catch (FileNotFoundException e) { - } catch (IOException e) { - } - } -*/ - } - -/* // sample code to read pixels into IntBuffer and save as a Bitmap (part1) - private static Bitmap createBitmap(final int[] pixels, final int offset, final int width, final int height) { - final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); - paint.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(new float[] { - 0, 0, 1, 0, 0, - 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, - 0, 0, 0, 1, 0 - }))); - - final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(bitmap); - - final Matrix matrix = new Matrix(); - matrix.postScale(1.0f, -1.0f); - matrix.postTranslate(0, height); - canvas.concat(matrix); - - canvas.drawBitmap(pixels, offset, width, 0, 0, width, height, false, paint); - - return bitmap; - } */ - - @Override - public final void run() { - Log.d(TAG, getName() + " started"); - init(); - Looper.prepare(); - synchronized (mSync) { - mHandler = new RenderHandler(mFpsCounter, this); - mSync.notify(); - } - - Looper.loop(); - - Log.d(TAG, getName() + " finishing"); - release(); - synchronized (mSync) { - mHandler = null; - mSync.notify(); - } - } - - private final void init() { - if (DEBUG) Log.v(TAG, "RenderThread#init:"); - // create EGLContext for this thread - mEgl = EGLBase.createFrom(null, false, false); - mEglSurface = mEgl.createFromSurface(mSurface); - mEglSurface.makeCurrent(); - // create drawing object - mDrawer = new GLDrawer2D(true); - } - - private final void release() { - if (DEBUG) Log.v(TAG, "RenderThread#release:"); - if (mDrawer != null) { - mDrawer.release(); - mDrawer = null; - } - if (mPreviewSurface != null) { - mPreviewSurface.release(); - mPreviewSurface = null; - } - if (mTexId >= 0) { - GLHelper.deleteTex(mTexId); - mTexId = -1; - } - if (mEglSurface != null) { - mEglSurface.release(); - mEglSurface = null; - } - if (mEgl != null) { - mEgl.release(); - mEgl = null; - } - } - } - } -} diff --git a/phenolib/src/main/java/org/phenoapps/fragments/examples/PhenoLibIndexHomeFragment.kt b/phenolib/src/main/java/org/phenoapps/fragments/examples/PhenoLibIndexHomeFragment.kt index 33a83b86..40227a35 100644 --- a/phenolib/src/main/java/org/phenoapps/fragments/examples/PhenoLibIndexHomeFragment.kt +++ b/phenolib/src/main/java/org/phenoapps/fragments/examples/PhenoLibIndexHomeFragment.kt @@ -88,11 +88,6 @@ class PhenoLibIndexHomeFragment( .actionFromIndexToTts()) } - val usbCameraButton = view.findViewById