OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.media; | 5 package org.chromium.media; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.graphics.ImageFormat; | 8 import android.graphics.ImageFormat; |
9 import android.hardware.Camera; | 9 import android.hardware.Camera; |
10 import android.util.Log; | 10 import android.util.Log; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 if (id == DEPTH_CAMERA_ID) { | 63 if (id == DEPTH_CAMERA_ID) { |
64 formatList.add(new CaptureFormat(320, 180, 5, ImageFormat.YV12)); | 64 formatList.add(new CaptureFormat(320, 180, 5, ImageFormat.YV12)); |
65 } else if (id == FISHEYE_CAMERA_ID) { | 65 } else if (id == FISHEYE_CAMERA_ID) { |
66 formatList.add(new CaptureFormat(640, 480, 30, ImageFormat.YV12)); | 66 formatList.add(new CaptureFormat(640, 480, 30, ImageFormat.YV12)); |
67 } else if (id == FOURMP_CAMERA_ID) { | 67 } else if (id == FOURMP_CAMERA_ID) { |
68 formatList.add(new CaptureFormat(1280, 720, 20, ImageFormat.YV12)); | 68 formatList.add(new CaptureFormat(1280, 720, 20, ImageFormat.YV12)); |
69 } | 69 } |
70 return formatList.toArray(new CaptureFormat[formatList.size()]); | 70 return formatList.toArray(new CaptureFormat[formatList.size()]); |
71 } | 71 } |
72 | 72 |
73 VideoCaptureTango(Context context, | 73 VideoCaptureTango(Context context, int id, long nativeVideoCaptureDeviceAndr
oid) { |
74 int id, | 74 // All Tango cameras are like the back facing one for the generic VideoC
apture code. |
75 long nativeVideoCaptureDeviceAndroid) { | |
76 // All Tango cameras are like the back facing one for the generic | |
77 // VideoCapture code. | |
78 super(context, 0, nativeVideoCaptureDeviceAndroid); | 75 super(context, 0, nativeVideoCaptureDeviceAndroid); |
79 mTangoCameraId = id; | 76 mTangoCameraId = id; |
80 } | 77 } |
81 | 78 |
82 @Override | 79 @Override |
83 protected void setCaptureParameters( | 80 protected void setCaptureParameters(int width, int height, int frameRate, |
84 int width, | |
85 int height, | |
86 int frameRate, | |
87 Camera.Parameters cameraParameters) { | 81 Camera.Parameters cameraParameters) { |
88 mCaptureFormat = new CaptureFormat(CAM_PARAMS[mTangoCameraId].mWidth, | 82 mCaptureFormat = new CaptureFormat(CAM_PARAMS[mTangoCameraId].mWidth, |
89 CAM_PARAMS[mTangoCameraId].mHeight, | 83 CAM_PARAMS[mTangoCameraId].mHeight, |
90 frameRate, | 84 frameRate, |
91 ImageFormat.YV12); | 85 ImageFormat.YV12); |
92 // Connect Tango SuperFrame mode. Available sf modes are "all", | 86 // Connect Tango SuperFrame mode. Available sf modes are "all", |
93 // "big-rgb", "small-rgb", "depth", "ir". | 87 // "big-rgb", "small-rgb", "depth", "ir". |
94 cameraParameters.set("sf-mode", "all"); | 88 cameraParameters.set("sf-mode", "all"); |
95 } | 89 } |
96 | 90 |
97 @Override | 91 @Override |
98 protected void allocateBuffers() { | 92 protected void allocateBuffers() { |
99 mFrameBuffer = ByteBuffer.allocateDirect( | 93 mFrameBuffer = ByteBuffer.allocateDirect( |
100 mCaptureFormat.mWidth * mCaptureFormat.mHeight * 3 / 2); | 94 mCaptureFormat.mWidth * mCaptureFormat.mHeight * 3 / 2); |
101 // Prefill Chroma to their zero-equivalent for the cameras that only | 95 // Prefill Chroma to their zero-equivalent for the cameras that only |
102 // provide Luma component. | 96 // provide Luma component. |
103 Arrays.fill(mFrameBuffer.array(), CHROMA_ZERO_LEVEL); | 97 Arrays.fill(mFrameBuffer.array(), CHROMA_ZERO_LEVEL); |
104 } | 98 } |
105 | 99 |
106 @Override | 100 @Override |
107 protected void setPreviewCallback(Camera.PreviewCallback cb) { | 101 protected void setPreviewCallback(Camera.PreviewCallback cb) { |
108 mCamera.setPreviewCallback(cb); | 102 mCamera.setPreviewCallback(cb); |
109 } | 103 } |
110 | 104 |
111 @Override | 105 @Override |
112 public void onPreviewFrame(byte[] data, Camera camera) { | 106 public void onPreviewFrame(byte[] data, Camera camera) { |
113 mPreviewBufferLock.lock(); | 107 mPreviewBufferLock.lock(); |
114 try { | 108 try { |
115 if (!mIsRunning) { | 109 if (!mIsRunning) return; |
116 return; | 110 |
117 } | |
118 if (data.length == SF_WIDTH * SF_FULL_HEIGHT) { | 111 if (data.length == SF_WIDTH * SF_FULL_HEIGHT) { |
119 int rotation = getDeviceOrientation(); | 112 int rotation = getDeviceOrientation(); |
120 if (rotation != mDeviceOrientation) { | 113 if (rotation != mDeviceOrientation) { |
121 mDeviceOrientation = rotation; | 114 mDeviceOrientation = rotation; |
122 } | 115 } |
123 if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) { | 116 if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) { |
124 rotation = 360 - rotation; | 117 rotation = 360 - rotation; |
125 } | 118 } |
126 rotation = (mCameraOrientation + rotation) % 360; | 119 rotation = (mCameraOrientation + rotation) % 360; |
127 | 120 |
128 if (mTangoCameraId == DEPTH_CAMERA_ID) { | 121 if (mTangoCameraId == DEPTH_CAMERA_ID) { |
129 int sizeY = SF_WIDTH * SF_LINES_DEPTH; | 122 int sizeY = SF_WIDTH * SF_LINES_DEPTH; |
130 int startY = | 123 int startY = |
131 SF_WIDTH * (SF_LINES_HEADER + SF_LINES_FISHEYE + | 124 SF_WIDTH * (SF_LINES_HEADER + SF_LINES_FISHEYE + SF_
LINES_RESERVED); |
132 SF_LINES_RESERVED); | |
133 // Depth is composed of 16b samples in which only 12b are | 125 // Depth is composed of 16b samples in which only 12b are |
134 // used. Throw away lowest 4 resolution bits. Android | 126 // used. Throw away lowest 4 resolution bits. Android |
135 // platforms are big endian, LSB in lowest address. In this | 127 // platforms are big endian, LSB in lowest address. In this |
136 // case Chroma components are unused. No need to write them | 128 // case Chroma components are unused. No need to write them |
137 // explicitly since they're filled to 128 on creation. | 129 // explicitly since they're filled to 128 on creation. |
138 byte depthsample; | 130 byte depthsample; |
139 for (int j = startY; j < startY + 2 * sizeY; j += 2) { | 131 for (int j = startY; j < startY + 2 * sizeY; j += 2) { |
140 depthsample = (byte)((data[j + 1] << 4) | | 132 depthsample = (byte) ((data[j + 1] << 4) | ((data[j] & 0
xF0) >> 4)); |
141 ((data[j] & 0xF0) >> 4)); | |
142 mFrameBuffer.put(depthsample); | 133 mFrameBuffer.put(depthsample); |
143 } | 134 } |
144 for (int j = 0; | 135 for (int j = 0; j < mCaptureFormat.mWidth * mCaptureFormat.m
Height - sizeY; |
145 j < mCaptureFormat.mWidth * mCaptureFormat.mHeight - | 136 ++j) { |
146 sizeY; | 137 mFrameBuffer.put((byte) 0); |
147 ++j) | 138 } |
148 mFrameBuffer.put((byte)0); | |
149 } else if (mTangoCameraId == FISHEYE_CAMERA_ID) { | 139 } else if (mTangoCameraId == FISHEYE_CAMERA_ID) { |
150 int sizeY = SF_WIDTH * SF_LINES_FISHEYE; | 140 int sizeY = SF_WIDTH * SF_LINES_FISHEYE; |
151 int startY = SF_WIDTH * SF_LINES_HEADER; | 141 int startY = SF_WIDTH * SF_LINES_HEADER; |
152 // Fisheye is black and white so Chroma components are | 142 // Fisheye is black and white so Chroma components are unuse
d. No need to write |
153 // unused. No need to write them explicitly since they're | 143 // them explicitly since they're filled to 128 on creation. |
154 // filled to 128 on creation. | 144 ByteBuffer.wrap(data, startY, sizeY).get(mFrameBuffer.array(
), 0, sizeY); |
155 ByteBuffer.wrap(data, startY, sizeY) | |
156 .get(mFrameBuffer.array(), 0, sizeY); | |
157 } else if (mTangoCameraId == FOURMP_CAMERA_ID) { | 145 } else if (mTangoCameraId == FOURMP_CAMERA_ID) { |
158 int startY = | 146 int startY = SF_WIDTH * (SF_LINES_HEADER + SF_LINES_FISHEYE
+ |
159 SF_WIDTH * (SF_LINES_HEADER + SF_LINES_FISHEYE + | |
160 SF_LINES_RESERVED + SF_LINES_DEPTH_PADDED); | 147 SF_LINES_RESERVED + SF_LINES_DEPTH_PADDED); |
161 int sizeY = SF_WIDTH * SF_LINES_BIGIMAGE; | 148 int sizeY = SF_WIDTH * SF_LINES_BIGIMAGE; |
162 | 149 |
163 // The spec is completely inaccurate on the location, sizes | 150 // The spec is completely inaccurate on the location, sizes |
164 // and format of these channels. | 151 // and format of these channels. |
165 int startU = SF_WIDTH * (SF_HEIGHT + SF_OFFSET_4MP_CHROMA); | 152 int startU = SF_WIDTH * (SF_HEIGHT + SF_OFFSET_4MP_CHROMA); |
166 int sizeU = SF_WIDTH * SF_LINES_BIGIMAGE / 4; | 153 int sizeU = SF_WIDTH * SF_LINES_BIGIMAGE / 4; |
167 int startV = (SF_WIDTH * SF_HEIGHT * 5 / 4) + | 154 int startV = (SF_WIDTH * SF_HEIGHT * 5 / 4) + SF_WIDTH * SF_
OFFSET_4MP_CHROMA; |
168 SF_WIDTH * SF_OFFSET_4MP_CHROMA; | |
169 int sizeV = SF_WIDTH * SF_LINES_BIGIMAGE / 4; | 155 int sizeV = SF_WIDTH * SF_LINES_BIGIMAGE / 4; |
170 | 156 |
171 // Equivalent to the following |for| loop but much faster: | 157 // Equivalent to the following |for| loop but much faster: |
172 // for (int i = START; i < START + SIZE; ++i) | 158 // for (int i = START; i < START + SIZE; ++i) |
173 // mFrameBuffer.put(data[i]); | 159 // mFrameBuffer.put(data[i]); |
174 ByteBuffer.wrap(data, startY, sizeY) | 160 ByteBuffer.wrap(data, startY, sizeY) |
175 .get(mFrameBuffer.array(), 0, sizeY); | 161 .get(mFrameBuffer.array(), 0, sizeY); |
176 ByteBuffer.wrap(data, startU, sizeU) | 162 ByteBuffer.wrap(data, startU, sizeU) |
177 .get(mFrameBuffer.array(), sizeY, sizeU); | 163 .get(mFrameBuffer.array(), sizeY, sizeU); |
178 ByteBuffer.wrap(data, startV, sizeV) | 164 ByteBuffer.wrap(data, startV, sizeV) |
179 .get(mFrameBuffer.array(), sizeY + sizeU, sizeV); | 165 .get(mFrameBuffer.array(), sizeY + sizeU, sizeV); |
180 } else { | 166 } else { |
181 Log.e(TAG, "Unknown camera, #id: " + mTangoCameraId); | 167 Log.e(TAG, "Unknown camera, #id: " + mTangoCameraId); |
182 return; | 168 return; |
183 } | 169 } |
184 mFrameBuffer.rewind(); // Important! | 170 mFrameBuffer.rewind(); // Important! |
185 nativeOnFrameAvailable(mNativeVideoCaptureDeviceAndroid, | 171 nativeOnFrameAvailable(mNativeVideoCaptureDeviceAndroid, mFrameB
uffer.array(), |
186 mFrameBuffer.array(), | 172 mFrameBuffer.capacity(), rotation); |
187 mFrameBuffer.capacity(), | |
188 rotation); | |
189 } | 173 } |
190 } finally { | 174 } finally { |
191 mPreviewBufferLock.unlock(); | 175 mPreviewBufferLock.unlock(); |
192 } | 176 } |
193 } | 177 } |
194 } | 178 } |
OLD | NEW |