Merge lp:~morphis/platform-api/add-hybris-compat-layer into lp:platform-api
- add-hybris-compat-layer
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~morphis/platform-api/add-hybris-compat-layer |
Merge into: | lp:platform-api |
Diff against target: |
14700 lines (+14058/-22) 95 files modified
CMakeLists.txt (+4/-5) android/compat/Android.common.mk (+10/-0) android/compat/camera/Android.mk (+58/-0) android/compat/camera/camera_compatibility_layer.cpp (+1016/-0) android/compat/camera/direct_camera_test.cpp (+683/-0) android/compat/input/Android.mk (+77/-0) android/compat/input/direct_input_test.cpp (+85/-0) android/compat/input/input_compatibility_layer.cpp (+384/-0) android/compat/media/Android.mk (+187/-0) android/compat/media/SimplePlayer.cpp (+777/-0) android/compat/media/SimplePlayer.h (+120/-0) android/compat/media/camera_service.cpp (+52/-0) android/compat/media/codec.cpp (+433/-0) android/compat/media/decoding_service.cpp (+366/-0) android/compat/media/decoding_service_priv.h (+208/-0) android/compat/media/direct_media_test.cpp (+417/-0) android/compat/media/direct_media_test.h (+58/-0) android/compat/media/media_codec_layer.cpp (+879/-0) android/compat/media/media_codec_list.cpp (+281/-0) android/compat/media/media_compatibility_layer.cpp (+693/-0) android/compat/media/media_format_layer.cpp (+245/-0) android/compat/media/media_format_layer_priv.cpp (+50/-0) android/compat/media/media_format_layer_priv.h (+68/-0) android/compat/media/media_recorder.cpp (+747/-0) android/compat/media/media_recorder.h (+269/-0) android/compat/media/media_recorder_client.cpp (+333/-0) android/compat/media/media_recorder_client.h (+81/-0) android/compat/media/media_recorder_factory.cpp (+133/-0) android/compat/media/media_recorder_factory.h (+72/-0) android/compat/media/media_recorder_layer.cpp (+506/-0) android/compat/media/media_recorder_observer.cpp (+127/-0) android/compat/media/media_recorder_observer.h (+97/-0) android/compat/media/surface_texture_client_hybris.cpp (+466/-0) android/compat/media/surface_texture_client_hybris_priv.h (+138/-0) android/compat/surface_flinger/Android.mk (+45/-0) android/compat/surface_flinger/direct_sf_test.cpp (+233/-0) android/compat/surface_flinger/surface_flinger_compatibility_layer.cpp (+366/-0) android/compat/ui/Android.mk (+26/-0) android/compat/ui/ui_compatibility_layer.cpp (+144/-0) debian/control (+50/-11) debian/libandroid-compat-dev.install (+10/-0) debian/libandroid-compat1.install (+5/-0) debian/libmedia-dev.install (+3/-0) debian/libmedia1.install (+1/-0) include/CMakeLists.txt (+1/-0) include/hybris/CMakeLists.txt (+5/-0) include/hybris/camera/CMakeLists.txt (+6/-0) include/hybris/camera/camera_compatibility_layer.h (+156/-0) include/hybris/camera/camera_compatibility_layer_capabilities.h (+160/-0) include/hybris/camera/camera_compatibility_layer_configuration_translator.h (+186/-0) include/hybris/input/CMakeLists.txt (+8/-0) include/hybris/input/input_stack_compatibility_layer.h (+127/-0) include/hybris/input/input_stack_compatibility_layer_codes_key.h (+266/-0) include/hybris/input/input_stack_compatibility_layer_flags.h (+72/-0) include/hybris/input/input_stack_compatibility_layer_flags_key.h (+190/-0) include/hybris/input/input_stack_compatibility_layer_flags_motion.h (+149/-0) include/hybris/media/CMakeLists.txt (+11/-0) include/hybris/media/decoding_service.h (+39/-0) include/hybris/media/media_codec_layer.h (+102/-0) include/hybris/media/media_codec_list.h (+56/-0) include/hybris/media/media_compatibility_layer.h (+75/-0) include/hybris/media/media_format_layer.h (+58/-0) include/hybris/media/media_recorder_layer.h (+141/-0) include/hybris/media/recorder_compatibility_layer.h (+126/-0) include/hybris/media/surface_texture_client_hybris.h (+78/-0) include/hybris/surface_flinger/CMakeLists.txt (+4/-0) include/hybris/surface_flinger/surface_flinger_compatibility_layer.h (+85/-0) include/hybris/ui/CMakeLists.txt (+4/-0) include/hybris/ui/ui_compatibility_layer.h (+64/-0) src/CMakeLists.txt (+1/-0) src/compat/CMakeLists.txt (+6/-0) src/compat/camera/CMakeLists.txt (+17/-0) src/compat/camera/camera.c (+144/-0) src/compat/camera/libcamera.pc.in (+10/-0) src/compat/input/CMakeLists.txt (+17/-0) src/compat/input/Makefile.am (+17/-0) src/compat/input/is.c (+44/-0) src/compat/input/libis.pc.in (+10/-0) src/compat/media/CMakeLists.txt (+17/-0) src/compat/media/Makefile.am (+17/-0) src/compat/media/libmedia.pc.in (+10/-0) src/compat/media/media.c (+302/-0) src/compat/sf/CMakeLists.txt (+17/-0) src/compat/sf/Makefile.am (+17/-0) src/compat/sf/libsf.pc.in (+10/-0) src/compat/sf/sf.c (+59/-0) src/compat/ui/CMakeLists.txt (+13/-0) src/compat/ui/ui.c (+58/-0) src/compat/wifi/CMakeLists.txt (+17/-0) src/compat/wifi/Makefile.am (+17/-0) src/compat/wifi/libwifi.pc.in (+10/-0) src/compat/wifi/wifi.c (+51/-0) src/ubuntu/application/CMakeLists.txt (+2/-3) src/ubuntu/hardware/CMakeLists.txt (+1/-1) src/ubuntu/hardware/alarms/CMakeLists.txt (+2/-2) |
To merge this branch: | bzr merge lp:~morphis/platform-api/add-hybris-compat-layer |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+281987@code.launchpad.net |
Commit message
Adding Android compatibility from libhybris which should not be part of libhybris anymore as its Ubuntu specific and already dropped upstream.
Description of the change
Adding Android compatibility from libhybris which should not be part of libhybris anymore as its Ubuntu specific and already dropped upstream.
PS Jenkins bot (ps-jenkins) wrote : | # |
Simon Fels (morphis) wrote : | # |
CI must fail as this depends on newer libhybris/
- 318. By Simon Fels
-
Add necessary debian packaging
- 319. By Simon Fels
-
Correct pkgconfig file references
- 320. By Simon Fels
-
Add temporary build-dep on libhybris-dev
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:320
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 321. By Simon Fels
-
Only depend on hybris for platforms its available on
- 322. By Simon Fels
-
Check correct variable to find out if hybris is available or not
- 323. By Simon Fels
-
Add arch specifier for android-headers too
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:323
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 324. By Simon Fels
-
Correct android-headers dependency
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:324
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 325. By Simon Fels
-
debian: only build on platforms we support
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:325
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
- 325. By Simon Fels
-
debian: only build on platforms we support
- 324. By Simon Fels
-
Correct android-headers dependency
- 323. By Simon Fels
-
Add arch specifier for android-headers too
- 322. By Simon Fels
-
Check correct variable to find out if hybris is available or not
- 321. By Simon Fels
-
Only depend on hybris for platforms its available on
- 320. By Simon Fels
-
Add temporary build-dep on libhybris-dev
- 319. By Simon Fels
-
Correct pkgconfig file references
- 318. By Simon Fels
-
Add necessary debian packaging
- 317. By Simon Fels
-
Integrate libhybris compatibility layer
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-03-25 23:01:58 +0000 |
3 | +++ CMakeLists.txt 2016-01-11 14:31:46 +0000 |
4 | @@ -60,16 +60,15 @@ |
5 | find_package(PkgConfig) |
6 | pkg_check_modules(MIRCLIENT REQUIRED mirclient) |
7 | |
8 | -# Try to find hybris, and disable hybris from build if not found |
9 | -find_library(Hybris |
10 | - NAMES hybris-common |
11 | -) |
12 | +pkg_check_modules(HYBRIS_COMMON hybris-common) |
13 | |
14 | -if(NOT Hybris) |
15 | +if(NOT HYBRIS_COMMON_FOUND) |
16 | message(STATUS "Notice: libhybris-common.so not found, disabling hybris support") |
17 | set(ENABLE_HYBRIS_IMPLEMENTATION OFF) |
18 | endif() |
19 | |
20 | +pkg_check_modules(ANDROID_HEADERS android-headers) |
21 | + |
22 | include_directories(include) |
23 | include_directories(android/include) |
24 | include_directories( |
25 | |
26 | === added directory 'android/compat' |
27 | === added file 'android/compat/Android.common.mk' |
28 | --- android/compat/Android.common.mk 1970-01-01 00:00:00 +0000 |
29 | +++ android/compat/Android.common.mk 2016-01-11 14:31:46 +0000 |
30 | @@ -0,0 +1,10 @@ |
31 | +# define ANDROID_VERSION MAJOR, MINOR and PATCH |
32 | + |
33 | +ANDROID_VERSION_MAJOR := $(word 1, $(subst ., , $(PLATFORM_VERSION))) |
34 | +ANDROID_VERSION_MINOR := $(word 2, $(subst ., , $(PLATFORM_VERSION))) |
35 | +ANDROID_VERSION_PATCH := $(word 3, $(subst ., , $(PLATFORM_VERSION))) |
36 | + |
37 | +LOCAL_CFLAGS += \ |
38 | + -DANDROID_VERSION_MAJOR=$(ANDROID_VERSION_MAJOR) \ |
39 | + -DANDROID_VERSION_MINOR=$(ANDROID_VERSION_MINOR) \ |
40 | + -DANDROID_VERSION_PATCH=$(ANDROID_VERSION_PATCH) |
41 | |
42 | === added directory 'android/compat/camera' |
43 | === added file 'android/compat/camera/Android.mk' |
44 | --- android/compat/camera/Android.mk 1970-01-01 00:00:00 +0000 |
45 | +++ android/compat/camera/Android.mk 2016-01-11 14:31:46 +0000 |
46 | @@ -0,0 +1,58 @@ |
47 | +LOCAL_PATH:= $(call my-dir) |
48 | +include $(CLEAR_VARS) |
49 | +include $(LOCAL_PATH)/../Android.common.mk |
50 | + |
51 | +HYBRIS_PATH := $(LOCAL_PATH)/../../hybris |
52 | + |
53 | +LOCAL_SRC_FILES := camera_compatibility_layer.cpp |
54 | + |
55 | +LOCAL_MODULE := libcamera_compat_layer |
56 | +LOCAL_MODULE_TAGS := optional |
57 | + |
58 | +LOCAL_C_INCLUDES := \ |
59 | + $(HYBRIS_PATH)/include |
60 | + |
61 | +LOCAL_SHARED_LIBRARIES := \ |
62 | + libcutils \ |
63 | + libcamera_client \ |
64 | + libutils \ |
65 | + libbinder \ |
66 | + libhardware \ |
67 | + libui \ |
68 | + libgui |
69 | + |
70 | +include $(BUILD_SHARED_LIBRARY) |
71 | + |
72 | +include $(CLEAR_VARS) |
73 | + |
74 | +HYBRIS_PATH := $(LOCAL_PATH)/../../hybris |
75 | + |
76 | +LOCAL_SRC_FILES := direct_camera_test.cpp |
77 | + |
78 | +LOCAL_MODULE := direct_camera_test |
79 | +LOCAL_MODULE_TAGS := optional |
80 | + |
81 | +LOCAL_C_INCLUDES := \ |
82 | + $(HYBRIS_PATH)/include \ |
83 | + bionic \ |
84 | + bionic/libstdc++/include \ |
85 | + external/gtest/include \ |
86 | + external/stlport/stlport \ |
87 | + external/skia/include/core \ |
88 | + |
89 | +LOCAL_SHARED_LIBRARIES := \ |
90 | + libis_compat_layer \ |
91 | + libsf_compat_layer \ |
92 | + libcamera_compat_layer \ |
93 | + libmedia_compat_layer \ |
94 | + libcutils \ |
95 | + libcamera_client \ |
96 | + libutils \ |
97 | + libbinder \ |
98 | + libhardware \ |
99 | + libui \ |
100 | + libgui \ |
101 | + libEGL \ |
102 | + libGLESv2 |
103 | + |
104 | +include $(BUILD_EXECUTABLE) |
105 | |
106 | === added file 'android/compat/camera/camera_compatibility_layer.cpp' |
107 | --- android/compat/camera/camera_compatibility_layer.cpp 1970-01-01 00:00:00 +0000 |
108 | +++ android/compat/camera/camera_compatibility_layer.cpp 2016-01-11 14:31:46 +0000 |
109 | @@ -0,0 +1,1016 @@ |
110 | +/* |
111 | + * Copyright (C) 2013-2014 Canonical Ltd |
112 | + * |
113 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
114 | + * you may not use this file except in compliance with the License. |
115 | + * You may obtain a copy of the License at |
116 | + * |
117 | + * http://www.apache.org/licenses/LICENSE-2.0 |
118 | + * |
119 | + * Unless required by applicable law or agreed to in writing, software |
120 | + * distributed under the License is distributed on an "AS IS" BASIS, |
121 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
122 | + * See the License for the specific language governing permissions and |
123 | + * limitations under the License. |
124 | + * |
125 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
126 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> |
127 | + * Jim Hodapp <jim.hodapp@canonical.com> |
128 | + */ |
129 | + |
130 | +//#define LOG_NDEBUG 0 |
131 | + |
132 | +#include <hybris/internal/camera_control.h> |
133 | +#include <hybris/camera/camera_compatibility_layer.h> |
134 | +#include <hybris/camera/camera_compatibility_layer_capabilities.h> |
135 | +#include <hybris/camera/camera_compatibility_layer_configuration_translator.h> |
136 | + |
137 | +#include <hybris/internal/surface_flinger_compatibility_layer_internal.h> |
138 | + |
139 | +#include <binder/ProcessState.h> |
140 | +#include <camera/Camera.h> |
141 | +#include <camera/CameraParameters.h> |
142 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
143 | +#include <gui/SurfaceTexture.h> |
144 | +#else |
145 | +#include <gui/GLConsumer.h> |
146 | +#endif |
147 | +#if ANDROID_VERSION_MAJOR==5 |
148 | +#include <gui/IGraphicBufferProducer.h> |
149 | +#endif |
150 | +#include <ui/GraphicBuffer.h> |
151 | + |
152 | +#include <GLES2/gl2.h> |
153 | +#include <GLES2/gl2ext.h> |
154 | + |
155 | +#undef LOG_TAG |
156 | +#define LOG_TAG "CameraCompatibilityLayer" |
157 | +#include <utils/Debug.h> |
158 | +#include <utils/Errors.h> |
159 | +#include <utils/KeyedVector.h> |
160 | +#include <utils/Log.h> |
161 | +#include <utils/String16.h> |
162 | + |
163 | +#include <gui/NativeBufferAlloc.h> |
164 | + |
165 | +#include <cstring> |
166 | + |
167 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) |
168 | + |
169 | +using android::CompileTimeAssert; // So COMPILE_TIME_ASSERT works |
170 | + |
171 | +// From android::GLConsumer::FrameAvailableListener |
172 | +#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 |
173 | + void CameraControl::onFrameAvailable(const android::BufferItem& item) |
174 | +#else |
175 | + void CameraControl::onFrameAvailable() |
176 | +#endif |
177 | +{ |
178 | + REPORT_FUNCTION(); |
179 | + if (listener) |
180 | + listener->on_preview_texture_needs_update_cb(listener->context); |
181 | +} |
182 | + |
183 | +// From android::CameraListener |
184 | +void CameraControl::notify(int32_t msg_type, int32_t ext1, int32_t ext2) |
185 | +{ |
186 | + REPORT_FUNCTION(); |
187 | + printf("\text1: %d, ext2: %d \n", ext1, ext2); |
188 | + |
189 | + if (!listener) |
190 | + return; |
191 | + |
192 | + switch (msg_type) { |
193 | + case CAMERA_MSG_ERROR: |
194 | + if (listener->on_msg_error_cb) |
195 | + listener->on_msg_error_cb(listener->context); |
196 | + break; |
197 | + case CAMERA_MSG_SHUTTER: |
198 | + if (listener->on_msg_shutter_cb) |
199 | + listener->on_msg_shutter_cb(listener->context); |
200 | + break; |
201 | + case CAMERA_MSG_ZOOM: |
202 | + if (listener->on_msg_zoom_cb) |
203 | + listener->on_msg_zoom_cb(listener->context, ext1); |
204 | + break; |
205 | + case CAMERA_MSG_FOCUS: |
206 | + if (listener->on_msg_focus_cb) |
207 | + listener->on_msg_focus_cb(listener->context); |
208 | + break; |
209 | + default: |
210 | + break; |
211 | + } |
212 | +} |
213 | + |
214 | +void CameraControl::postData( |
215 | + int32_t msg_type, |
216 | + const android::sp<android::IMemory>& data, |
217 | + camera_frame_metadata_t* metadata) |
218 | +{ |
219 | + REPORT_FUNCTION(); |
220 | + |
221 | + if (!listener) |
222 | + return; |
223 | + |
224 | + switch (msg_type) { |
225 | + case CAMERA_MSG_RAW_IMAGE: |
226 | + if (listener->on_data_raw_image_cb) |
227 | + listener->on_data_raw_image_cb(data->pointer(), data->size(), listener->context); |
228 | + break; |
229 | + case CAMERA_MSG_COMPRESSED_IMAGE: |
230 | + if (listener->on_data_compressed_image_cb) |
231 | + listener->on_data_compressed_image_cb(data->pointer(), data->size(), listener->context); |
232 | + break; |
233 | + case CAMERA_MSG_PREVIEW_FRAME: |
234 | + if (listener->on_preview_frame_cb) |
235 | + listener->on_preview_frame_cb(data->pointer(), data->size(), listener->context); |
236 | + default: |
237 | + break; |
238 | + } |
239 | +} |
240 | + |
241 | +void CameraControl::postDataTimestamp( |
242 | + nsecs_t timestamp, |
243 | + int32_t msg_type, |
244 | + const android::sp<android::IMemory>& data) |
245 | +{ |
246 | + REPORT_FUNCTION(); |
247 | + (void) timestamp; |
248 | + (void) msg_type; |
249 | + (void) data; |
250 | +} |
251 | + |
252 | +namespace android |
253 | +{ |
254 | +NativeBufferAlloc::NativeBufferAlloc() { |
255 | +} |
256 | + |
257 | +NativeBufferAlloc::~NativeBufferAlloc() { |
258 | +} |
259 | + |
260 | +sp<GraphicBuffer> NativeBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, |
261 | + PixelFormat format, uint32_t usage, status_t* error) { |
262 | + sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); |
263 | + status_t err = graphicBuffer->initCheck(); |
264 | + *error = err; |
265 | + if (err != 0 || graphicBuffer->handle == 0) { |
266 | + if (err == NO_MEMORY) { |
267 | + GraphicBuffer::dumpAllocationsToSystemLog(); |
268 | + } |
269 | + ALOGI("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " |
270 | + "failed (%s), handle=%p", |
271 | + w, h, strerror(-err), graphicBuffer->handle); |
272 | + return 0; |
273 | + } |
274 | + return graphicBuffer; |
275 | +} |
276 | +} |
277 | + |
278 | +int android_camera_get_number_of_devices() |
279 | +{ |
280 | + REPORT_FUNCTION(); |
281 | + return android::Camera::getNumberOfCameras(); |
282 | +} |
283 | + |
284 | +int android_camera_get_device_info(int32_t camera_id, int* facing, int* orientation) |
285 | +{ |
286 | + REPORT_FUNCTION(); |
287 | + |
288 | + if (!facing || !orientation) |
289 | + return android::BAD_VALUE; |
290 | + |
291 | + COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CAMERA_FACING_BACK == static_cast<int>(BACK_FACING_CAMERA_TYPE)); |
292 | + COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CAMERA_FACING_FRONT == static_cast<int>(FRONT_FACING_CAMERA_TYPE)); |
293 | + |
294 | + android::CameraInfo ci; |
295 | + |
296 | + int rv = android::Camera::getCameraInfo(camera_id, &ci); |
297 | + if (rv != android::OK) |
298 | + return rv; |
299 | + |
300 | + *facing = ci.facing; |
301 | + *orientation = ci.orientation; |
302 | + |
303 | + return android::OK; |
304 | +} |
305 | + |
306 | +CameraControl* android_camera_connect_to(CameraType camera_type, CameraControlListener* listener) |
307 | +{ |
308 | + REPORT_FUNCTION(); |
309 | + |
310 | + const int32_t camera_count = android::Camera::getNumberOfCameras(); |
311 | + |
312 | + for (int32_t camera_id = 0; camera_id < camera_count; camera_id++) { |
313 | + android::CameraInfo ci; |
314 | + android::Camera::getCameraInfo(camera_id, &ci); |
315 | + |
316 | + if (ci.facing != camera_type) |
317 | + continue; |
318 | + |
319 | + return android_camera_connect_by_id(camera_id, listener); |
320 | + } |
321 | + |
322 | + return NULL; |
323 | +} |
324 | + |
325 | +CameraControl* android_camera_connect_by_id(int32_t camera_id, struct CameraControlListener* listener) |
326 | +{ |
327 | + if (camera_id < 0 || camera_id >= android::Camera::getNumberOfCameras()) |
328 | + return NULL; |
329 | + |
330 | + android::sp<CameraControl> cc = new CameraControl(); |
331 | + cc->listener = listener; |
332 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=3 || ANDROID_VERSION_MAJOR==5 |
333 | + cc->camera = android::Camera::connect(camera_id, android::String16("hybris"), android::Camera::USE_CALLING_UID); |
334 | +#else |
335 | + cc->camera = android::Camera::connect(camera_id); |
336 | +#endif |
337 | + |
338 | + if (cc->camera == NULL) |
339 | + return NULL; |
340 | + |
341 | + cc->camera_parameters = android::CameraParameters(cc->camera->getParameters()); |
342 | + |
343 | + // android::Camera holds a strong reference to the listener, keeping |
344 | + // |cc| alive |
345 | + cc->camera->setListener(cc); |
346 | + cc->camera->lock(); |
347 | + |
348 | + // TODO: Move this to a more generic component |
349 | + android::ProcessState::self()->startThreadPool(); |
350 | + |
351 | + return cc.get(); |
352 | +} |
353 | + |
354 | +void android_camera_disconnect(CameraControl* control) |
355 | +{ |
356 | + REPORT_FUNCTION(); |
357 | + assert(control); |
358 | + |
359 | + android::Mutex::Autolock al(control->guard); |
360 | + |
361 | + if (control->preview_texture != NULL) |
362 | + control->preview_texture->abandon(); |
363 | + |
364 | + control->camera->disconnect(); |
365 | + control->camera->unlock(); |
366 | +} |
367 | + |
368 | +int android_camera_lock(CameraControl* control) |
369 | +{ |
370 | + android::Mutex::Autolock al(control->guard); |
371 | + return control->camera->lock(); |
372 | +} |
373 | + |
374 | +int android_camera_unlock(CameraControl* control) |
375 | +{ |
376 | + android::Mutex::Autolock al(control->guard); |
377 | + return control->camera->unlock(); |
378 | +} |
379 | + |
380 | +void android_camera_delete(CameraControl* control) |
381 | +{ |
382 | + android::sp<android::Camera> camera = control->camera; |
383 | + control->camera.clear(); |
384 | + camera.clear(); |
385 | +} |
386 | + |
387 | +void android_camera_dump_parameters(CameraControl* control) |
388 | +{ |
389 | + REPORT_FUNCTION(); |
390 | + assert(control); |
391 | + |
392 | + printf("%s \n", control->camera->getParameters().string()); |
393 | +} |
394 | + |
395 | +void android_camera_set_flash_mode(CameraControl* control, FlashMode mode) |
396 | +{ |
397 | + REPORT_FUNCTION(); |
398 | + assert(control); |
399 | + |
400 | + android::Mutex::Autolock al(control->guard); |
401 | + control->camera_parameters.set( |
402 | + android::CameraParameters::KEY_FLASH_MODE, |
403 | + flash_modes[mode]); |
404 | + control->camera->setParameters(control->camera_parameters.flatten()); |
405 | +} |
406 | + |
407 | +void android_camera_get_flash_mode(CameraControl* control, FlashMode* mode) |
408 | +{ |
409 | + REPORT_FUNCTION(); |
410 | + assert(control); |
411 | + |
412 | + android::Mutex::Autolock al(control->guard); |
413 | + static const char* flash_mode = control->camera_parameters.get( |
414 | + android::CameraParameters::KEY_FLASH_MODE); |
415 | + if (flash_mode) |
416 | + *mode = flash_modes_lut.valueFor(android::String8(flash_mode)); |
417 | + else |
418 | + *mode = FLASH_MODE_OFF; |
419 | +} |
420 | + |
421 | +void android_camera_enumerate_supported_flash_modes(CameraControl* control, flash_mode_callback cb, void* ctx) |
422 | +{ |
423 | + REPORT_FUNCTION(); |
424 | + assert(control); |
425 | + |
426 | + android::Mutex::Autolock al(control->guard); |
427 | + android::String8 raw_modes; |
428 | + raw_modes = android::String8( |
429 | + control->camera_parameters.get( |
430 | + android::CameraParameters::KEY_SUPPORTED_FLASH_MODES)); |
431 | + |
432 | + const char delimiter[2] = ","; |
433 | + char *token; |
434 | + android::String8 mode; |
435 | + char *raw_modes_mutable = strdup(raw_modes.string()); |
436 | + |
437 | + token = strtok(raw_modes_mutable, delimiter); |
438 | + |
439 | + while (token != NULL) { |
440 | + uint32_t index = flash_modes_lut.indexOfKey(mode); |
441 | + |
442 | + mode = android::String8(token); |
443 | + if (flash_modes_lut.indexOfKey(mode) >= 0) { |
444 | + cb(ctx, flash_modes_lut.valueFor(mode)); |
445 | + } |
446 | + token = strtok(NULL, delimiter); |
447 | + } |
448 | +} |
449 | + |
450 | +void android_camera_set_white_balance_mode(CameraControl* control, WhiteBalanceMode mode) |
451 | +{ |
452 | + REPORT_FUNCTION(); |
453 | + assert(control); |
454 | + |
455 | + android::Mutex::Autolock al(control->guard); |
456 | + |
457 | + control->camera_parameters.set( |
458 | + android::CameraParameters::KEY_WHITE_BALANCE, |
459 | + white_balance_modes[mode]); |
460 | + control->camera->setParameters(control->camera_parameters.flatten()); |
461 | +} |
462 | + |
463 | +void android_camera_get_white_balance_mode(CameraControl* control, WhiteBalanceMode* mode) |
464 | +{ |
465 | + REPORT_FUNCTION(); |
466 | + assert(control); |
467 | + |
468 | + android::Mutex::Autolock al(control->guard); |
469 | + |
470 | + *mode = white_balance_modes_lut.valueFor( |
471 | + android::String8( |
472 | + control->camera_parameters.get( |
473 | + android::CameraParameters::KEY_WHITE_BALANCE))); |
474 | +} |
475 | + |
476 | +void android_camera_set_scene_mode(CameraControl* control, SceneMode mode) |
477 | +{ |
478 | + REPORT_FUNCTION(); |
479 | + assert(control); |
480 | + |
481 | + android::Mutex::Autolock al(control->guard); |
482 | + |
483 | + control->camera_parameters.set( |
484 | + android::CameraParameters::KEY_SCENE_MODE, |
485 | + scene_modes[mode]); |
486 | + control->camera->setParameters(control->camera_parameters.flatten()); |
487 | +} |
488 | + |
489 | +void android_camera_enumerate_supported_scene_modes(CameraControl* control, scene_mode_callback cb, void* ctx) |
490 | +{ |
491 | + REPORT_FUNCTION(); |
492 | + assert(control); |
493 | + |
494 | + android::Mutex::Autolock al(control->guard); |
495 | + android::String8 raw_modes; |
496 | + raw_modes = android::String8( |
497 | + control->camera_parameters.get( |
498 | + android::CameraParameters::KEY_SUPPORTED_SCENE_MODES)); |
499 | + |
500 | + const char delimiter[2] = ","; |
501 | + char *token; |
502 | + android::String8 mode; |
503 | + char *raw_modes_mutable = strdup(raw_modes.string()); |
504 | + |
505 | + token = strtok(raw_modes_mutable, delimiter); |
506 | + |
507 | + while (token != NULL) { |
508 | + mode = android::String8(token); |
509 | + cb(ctx, scene_modes_lut.valueFor(mode)); |
510 | + token = strtok(NULL, delimiter); |
511 | + } |
512 | +} |
513 | + |
514 | +void android_camera_get_scene_mode(CameraControl* control, SceneMode* mode) |
515 | +{ |
516 | + REPORT_FUNCTION(); |
517 | + assert(control); |
518 | + |
519 | + android::Mutex::Autolock al(control->guard); |
520 | + |
521 | + *mode = scene_modes_lut.valueFor( |
522 | + android::String8( |
523 | + control->camera_parameters.get( |
524 | + android::CameraParameters::KEY_SCENE_MODE))); |
525 | +} |
526 | + |
527 | +void android_camera_set_auto_focus_mode(CameraControl* control, AutoFocusMode mode) |
528 | +{ |
529 | + REPORT_FUNCTION(); |
530 | + assert(control); |
531 | + |
532 | + android::Mutex::Autolock al(control->guard); |
533 | + |
534 | + control->camera_parameters.set( |
535 | + android::CameraParameters::KEY_FOCUS_MODE, |
536 | + auto_focus_modes[mode]); |
537 | + control->camera->setParameters(control->camera_parameters.flatten()); |
538 | +} |
539 | + |
540 | +void android_camera_get_auto_focus_mode(CameraControl* control, AutoFocusMode* mode) |
541 | +{ |
542 | + REPORT_FUNCTION(); |
543 | + assert(control); |
544 | + |
545 | + android::Mutex::Autolock al(control->guard); |
546 | + |
547 | + *mode = auto_focus_modes_lut.valueFor( |
548 | + android::String8( |
549 | + control->camera_parameters.get( |
550 | + android::CameraParameters::KEY_FOCUS_MODE))); |
551 | +} |
552 | + |
553 | + |
554 | +void android_camera_set_effect_mode(CameraControl* control, EffectMode mode) |
555 | +{ |
556 | + REPORT_FUNCTION(); |
557 | + assert(control); |
558 | + |
559 | + android::Mutex::Autolock al(control->guard); |
560 | + |
561 | + control->camera_parameters.set( |
562 | + android::CameraParameters::KEY_EFFECT, |
563 | + effect_modes[mode]); |
564 | + control->camera->setParameters(control->camera_parameters.flatten()); |
565 | +} |
566 | + |
567 | +void android_camera_get_effect_mode(CameraControl* control, EffectMode* mode) |
568 | +{ |
569 | + REPORT_FUNCTION(); |
570 | + assert(control); |
571 | + |
572 | + android::Mutex::Autolock al(control->guard); |
573 | + |
574 | + *mode = effect_modes_lut.valueFor( |
575 | + android::String8( |
576 | + control->camera_parameters.get( |
577 | + android::CameraParameters::KEY_EFFECT))); |
578 | +} |
579 | + |
580 | +void android_camera_get_preview_fps_range(CameraControl* control, int* min, int* max) |
581 | +{ |
582 | + REPORT_FUNCTION(); |
583 | + assert(control); |
584 | + |
585 | + android::Mutex::Autolock al(control->guard); |
586 | + |
587 | + control->camera_parameters.getPreviewFpsRange(min, max); |
588 | +} |
589 | + |
590 | +void android_camera_set_preview_fps(CameraControl* control, int fps) |
591 | +{ |
592 | + REPORT_FUNCTION(); |
593 | + assert(control); |
594 | + |
595 | + android::Mutex::Autolock al(control->guard); |
596 | + control->camera_parameters.setPreviewFrameRate(fps); |
597 | + control->camera->setParameters(control->camera_parameters.flatten()); |
598 | +} |
599 | + |
600 | +void android_camera_get_preview_fps(CameraControl* control, int* fps) |
601 | +{ |
602 | + REPORT_FUNCTION(); |
603 | + assert(control); |
604 | + |
605 | + android::Mutex::Autolock al(control->guard); |
606 | + *fps = control->camera_parameters.getPreviewFrameRate(); |
607 | +} |
608 | + |
609 | +void android_camera_enumerate_supported_preview_sizes(CameraControl* control, size_callback cb, void* ctx) |
610 | +{ |
611 | + REPORT_FUNCTION(); |
612 | + assert(control); |
613 | + |
614 | + android::Mutex::Autolock al(control->guard); |
615 | + android::Vector<android::Size> sizes; |
616 | + control->camera_parameters.getSupportedPreviewSizes(sizes); |
617 | + |
618 | + for (unsigned int i = 0; i < sizes.size(); i++) { |
619 | + cb(ctx, sizes[i].width, sizes[i].height); |
620 | + } |
621 | +} |
622 | + |
623 | +void android_camera_enumerate_supported_picture_sizes(CameraControl* control, size_callback cb, void* ctx) |
624 | +{ |
625 | + REPORT_FUNCTION(); |
626 | + assert(control); |
627 | + |
628 | + android::Mutex::Autolock al(control->guard); |
629 | + android::Vector<android::Size> sizes; |
630 | + control->camera_parameters.getSupportedPictureSizes(sizes); |
631 | + |
632 | + for (unsigned int i = 0; i < sizes.size(); i++) { |
633 | + cb(ctx, sizes[i].width, sizes[i].height); |
634 | + } |
635 | +} |
636 | + |
637 | +void android_camera_get_preview_size(CameraControl* control, int* width, int* height) |
638 | +{ |
639 | + REPORT_FUNCTION(); |
640 | + assert(control); |
641 | + |
642 | + android::Mutex::Autolock al(control->guard); |
643 | + |
644 | + control->camera_parameters.getPreviewSize(width, height); |
645 | +} |
646 | + |
647 | +void android_camera_set_preview_size(CameraControl* control, int width, int height) |
648 | +{ |
649 | + REPORT_FUNCTION(); |
650 | + assert(control); |
651 | + |
652 | + android::Mutex::Autolock al(control->guard); |
653 | + |
654 | + control->camera_parameters.setPreviewSize(width, height); |
655 | + control->camera->setParameters(control->camera_parameters.flatten()); |
656 | +} |
657 | + |
658 | +void android_camera_get_picture_size(CameraControl* control, int* width, int* height) |
659 | +{ |
660 | + REPORT_FUNCTION(); |
661 | + assert(control); |
662 | + |
663 | + android::Mutex::Autolock al(control->guard); |
664 | + |
665 | + control->camera_parameters.getPictureSize(width, height); |
666 | +} |
667 | + |
668 | +void android_camera_set_thumbnail_size(struct CameraControl* control, int width, int height) |
669 | +{ |
670 | + REPORT_FUNCTION(); |
671 | + assert(control); |
672 | + |
673 | + android::Mutex::Autolock al(control->guard); |
674 | + |
675 | + control->camera_parameters.set( |
676 | + android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, |
677 | + width); |
678 | + control->camera_parameters.set( |
679 | + android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, |
680 | + height); |
681 | + control->camera->setParameters(control->camera_parameters.flatten()); |
682 | +} |
683 | + |
684 | +void android_camera_get_thumbnail_size(struct CameraControl* control, int* width, int* height) |
685 | +{ |
686 | + REPORT_FUNCTION(); |
687 | + assert(control); |
688 | + |
689 | + android::Mutex::Autolock al(control->guard); |
690 | + |
691 | + *width = atoi(control->camera_parameters.get(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH)); |
692 | + *height = atoi(control->camera_parameters.get(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT)); |
693 | +} |
694 | + |
695 | +void android_camera_enumerate_supported_thumbnail_sizes(struct CameraControl* control, size_callback cb, void* ctx) |
696 | +{ |
697 | + REPORT_FUNCTION(); |
698 | + assert(control); |
699 | + |
700 | + android::Mutex::Autolock al(control->guard); |
701 | + // e.g. 800x600,320x240 |
702 | + android::String8 sizes = android::String8( |
703 | + control->camera_parameters.get( |
704 | + android::CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES)); |
705 | + |
706 | + const char delimiter[2] = ","; |
707 | + const char size_delimiter[2] = "x"; |
708 | + char *token, *save_ptr, *save_ptr1; |
709 | + int height = 0, width = 0; |
710 | + char *sizes_mutable = strdup(sizes.string()); |
711 | + |
712 | + ALOGD("Supported thumbnail sizes: %s", sizes.string()); |
713 | + // Get the first <width>x<height to the left of ',' |
714 | + token = strtok_r(sizes_mutable, delimiter, &save_ptr); |
715 | + |
716 | + while (token != NULL) { |
717 | + // Parse <width>x<height> token |
718 | + char *w = strtok_r(token, size_delimiter, &save_ptr1); |
719 | + char *h = strtok_r(NULL, size_delimiter, &save_ptr1); |
720 | + width = atoi(w); |
721 | + height = atoi(h); |
722 | + if (width > 0 && height > 0) |
723 | + cb(ctx, width, height); |
724 | + // Get the next <width>x<height> pair |
725 | + token = strtok_r(NULL, delimiter, &save_ptr); |
726 | + } |
727 | +} |
728 | + |
729 | +void android_camera_set_picture_size(CameraControl* control, int width, int height) |
730 | +{ |
731 | + REPORT_FUNCTION(); |
732 | + assert(control); |
733 | + |
734 | + android::Mutex::Autolock al(control->guard); |
735 | + |
736 | + control->camera_parameters.setPictureSize(width, height); |
737 | + control->camera->setParameters(control->camera_parameters.flatten()); |
738 | +} |
739 | + |
740 | +void android_camera_get_current_zoom(CameraControl* control, int* zoom) |
741 | +{ |
742 | + REPORT_FUNCTION(); |
743 | + assert(control); |
744 | + |
745 | + android::Mutex::Autolock al(control->guard); |
746 | + |
747 | + *zoom = control->camera_parameters.getInt(android::CameraParameters::KEY_ZOOM); |
748 | +} |
749 | + |
750 | +void android_camera_get_max_zoom(CameraControl* control, int* zoom) |
751 | +{ |
752 | + REPORT_FUNCTION(); |
753 | + assert(control); |
754 | + |
755 | + android::Mutex::Autolock al(control->guard); |
756 | + |
757 | + *zoom = control->camera_parameters.getInt(android::CameraParameters::KEY_MAX_ZOOM); |
758 | +} |
759 | + |
760 | +void android_camera_set_display_orientation(CameraControl* control, int32_t clockwise_rotation_degree) |
761 | +{ |
762 | + REPORT_FUNCTION(); |
763 | + assert(control); |
764 | + |
765 | + android::Mutex::Autolock al(control->guard); |
766 | + static const int32_t ignored_parameter = 0; |
767 | + control->camera->sendCommand(CAMERA_CMD_SET_DISPLAY_ORIENTATION, clockwise_rotation_degree, ignored_parameter); |
768 | +} |
769 | + |
770 | +void android_camera_get_preview_texture_transformation(CameraControl* control, float m[16]) |
771 | +{ |
772 | + REPORT_FUNCTION(); |
773 | + assert(control); |
774 | + |
775 | + if (control->preview_texture == NULL) |
776 | + return; |
777 | + |
778 | + control->preview_texture->getTransformMatrix(m); |
779 | +} |
780 | + |
781 | +void android_camera_update_preview_texture(CameraControl* control) |
782 | +{ |
783 | + REPORT_FUNCTION(); |
784 | + assert(control); |
785 | + |
786 | + control->preview_texture->updateTexImage(); |
787 | +} |
788 | + |
789 | +void android_camera_set_preview_texture(CameraControl* control, int texture_id) |
790 | +{ |
791 | + REPORT_FUNCTION(); |
792 | + assert(control); |
793 | + |
794 | + static const bool allow_synchronous_mode = false; |
795 | + static const bool is_controlled_by_app = true; |
796 | + |
797 | + android::sp<android::NativeBufferAlloc> native_alloc( |
798 | + new android::NativeBufferAlloc() |
799 | + ); |
800 | + |
801 | +#if ANDROID_VERSION_MAJOR==5 |
802 | + android::sp<android::IGraphicBufferProducer> producer; |
803 | + android::sp<android::IGraphicBufferConsumer> consumer; |
804 | + android::BufferQueue::createBufferQueue(&producer, &consumer); |
805 | +#else |
806 | + android::sp<android::BufferQueue> buffer_queue( |
807 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 |
808 | + new android::BufferQueue(false, NULL, native_alloc) |
809 | +#else |
810 | + new android::BufferQueue(NULL) |
811 | +#endif |
812 | + ); |
813 | +#endif |
814 | + |
815 | + if (control->preview_texture == NULL) { |
816 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
817 | + control->preview_texture = android::sp<android::SurfaceTexture>( |
818 | + new android::SurfaceTexture( |
819 | +#else |
820 | + control->preview_texture = android::sp<android::GLConsumer>( |
821 | + new android::GLConsumer( |
822 | +#endif |
823 | +#if ANDROID_VERSION_MAJOR==5 |
824 | + consumer, |
825 | + texture_id, |
826 | + GL_TEXTURE_EXTERNAL_OES, |
827 | + true, |
828 | + is_controlled_by_app)); |
829 | +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 |
830 | + texture_id, |
831 | + allow_synchronous_mode, |
832 | + GL_TEXTURE_EXTERNAL_OES, |
833 | + true, |
834 | + buffer_queue)); |
835 | +#else |
836 | + buffer_queue, |
837 | + texture_id, |
838 | + GL_TEXTURE_EXTERNAL_OES, |
839 | + true, |
840 | + is_controlled_by_app)); |
841 | +#endif |
842 | + } |
843 | + |
844 | + control->preview_texture->setFrameAvailableListener( |
845 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
846 | + android::sp<android::SurfaceTexture::FrameAvailableListener>(control)); |
847 | +#else |
848 | + android::sp<android::GLConsumer::FrameAvailableListener>(control)); |
849 | +#endif |
850 | + |
851 | +#if ANDROID_VERSION_MAJOR==5 |
852 | + control->camera->setPreviewTarget(producer); |
853 | +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 |
854 | + control->camera->setPreviewTexture(control->preview_texture->getBufferQueue()); |
855 | +#else |
856 | + control->camera->setPreviewTarget(buffer_queue); |
857 | +#endif |
858 | +} |
859 | + |
860 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
861 | +void android_camera_set_preview_surface(CameraControl* control, SfSurface* surface) |
862 | +{ |
863 | + REPORT_FUNCTION(); |
864 | + assert(control); |
865 | + assert(surface); |
866 | + |
867 | + android::Mutex::Autolock al(control->guard); |
868 | + control->camera->setPreviewDisplay(surface->surface); |
869 | +} |
870 | +#endif |
871 | + |
872 | +void android_camera_start_preview(CameraControl* control) |
873 | +{ |
874 | + REPORT_FUNCTION(); |
875 | + assert(control); |
876 | + |
877 | + android::Mutex::Autolock al(control->guard); |
878 | + control->camera->startPreview(); |
879 | +} |
880 | + |
881 | +void android_camera_stop_preview(CameraControl* control) |
882 | +{ |
883 | + REPORT_FUNCTION(); |
884 | + assert(control); |
885 | + |
886 | + android::Mutex::Autolock al(control->guard); |
887 | + control->camera->stopPreview(); |
888 | +} |
889 | + |
890 | +void android_camera_start_autofocus(CameraControl* control) |
891 | +{ |
892 | + REPORT_FUNCTION(); |
893 | + assert(control); |
894 | + |
895 | + android::Mutex::Autolock al(control->guard); |
896 | + control->camera->autoFocus(); |
897 | +} |
898 | + |
899 | +void android_camera_stop_autofocus(CameraControl* control) |
900 | +{ |
901 | + REPORT_FUNCTION(); |
902 | + assert(control); |
903 | + |
904 | + android::Mutex::Autolock al(control->guard); |
905 | + control->camera->cancelAutoFocus(); |
906 | +} |
907 | + |
908 | +void android_camera_start_zoom(CameraControl* control, int32_t zoom) |
909 | +{ |
910 | + REPORT_FUNCTION(); |
911 | + assert(control); |
912 | + |
913 | + static const int ignored_argument = 0; |
914 | + |
915 | + android::Mutex::Autolock al(control->guard); |
916 | + control->camera->sendCommand(CAMERA_CMD_START_SMOOTH_ZOOM, |
917 | + zoom, |
918 | + ignored_argument); |
919 | +} |
920 | + |
921 | +// Adjust the zoom level immediately as opposed to smoothly zoomin gin. |
922 | +void android_camera_set_zoom(CameraControl* control, int32_t zoom) |
923 | +{ |
924 | + REPORT_FUNCTION(); |
925 | + assert(control); |
926 | + |
927 | + android::Mutex::Autolock al(control->guard); |
928 | + |
929 | + control->camera_parameters.set( |
930 | + android::CameraParameters::KEY_ZOOM, |
931 | + zoom); |
932 | + |
933 | + control->camera->setParameters(control->camera_parameters.flatten()); |
934 | +} |
935 | + |
936 | +void android_camera_stop_zoom(CameraControl* control) |
937 | +{ |
938 | + REPORT_FUNCTION(); |
939 | + assert(control); |
940 | + |
941 | + static const int ignored_argument = 0; |
942 | + |
943 | + android::Mutex::Autolock al(control->guard); |
944 | + control->camera->sendCommand(CAMERA_CMD_STOP_SMOOTH_ZOOM, |
945 | + ignored_argument, |
946 | + ignored_argument); |
947 | +} |
948 | + |
949 | +void android_camera_take_snapshot(CameraControl* control) |
950 | +{ |
951 | + REPORT_FUNCTION(); |
952 | + assert(control); |
953 | + android::Mutex::Autolock al(control->guard); |
954 | + control->camera->takePicture(CAMERA_MSG_SHUTTER | CAMERA_MSG_COMPRESSED_IMAGE); |
955 | +} |
956 | + |
957 | +int android_camera_set_preview_callback_mode(CameraControl* control, PreviewCallbackMode mode) |
958 | +{ |
959 | + REPORT_FUNCTION(); |
960 | + |
961 | + if (!control) |
962 | + return android::BAD_VALUE; |
963 | + |
964 | + android::Mutex::Autolock al(control->guard); |
965 | + |
966 | + control->camera->setPreviewCallbackFlags( |
967 | + mode == PREVIEW_CALLBACK_ENABLED ? |
968 | + CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER : CAMERA_FRAME_CALLBACK_FLAG_NOOP); |
969 | + |
970 | + return android::OK; |
971 | +} |
972 | + |
973 | +void android_camera_set_preview_format(CameraControl* control, CameraPixelFormat pf) |
974 | +{ |
975 | + REPORT_FUNCTION(); |
976 | + assert(control); |
977 | + |
978 | + android::Mutex::Autolock al(control->guard); |
979 | + |
980 | + control->camera_parameters.set( |
981 | + android::CameraParameters::KEY_PREVIEW_FORMAT, |
982 | + camera_pixel_formats[pf]); |
983 | + |
984 | + control->camera->setParameters(control->camera_parameters.flatten()); |
985 | +} |
986 | + |
987 | +void android_camera_get_preview_format(CameraControl* control, CameraPixelFormat* pf) |
988 | +{ |
989 | + REPORT_FUNCTION(); |
990 | + assert(control); |
991 | + |
992 | + android::Mutex::Autolock al(control->guard); |
993 | + |
994 | + *pf = pixel_formats_lut.valueFor( |
995 | + android::String8( |
996 | + control->camera_parameters.get( |
997 | + android::CameraParameters::KEY_PREVIEW_FORMAT))); |
998 | +} |
999 | + |
1000 | +void android_camera_set_focus_region( |
1001 | + CameraControl* control, |
1002 | + FocusRegion* region) |
1003 | +{ |
1004 | + REPORT_FUNCTION(); |
1005 | + assert(control); |
1006 | + |
1007 | + android::Mutex::Autolock al(control->guard); |
1008 | + static const char* focus_region_pattern = "(%d,%d,%d,%d,%d)"; |
1009 | + static char focus_region[256]; |
1010 | + snprintf(focus_region, |
1011 | + sizeof(focus_region), |
1012 | + focus_region_pattern, |
1013 | + region->left, |
1014 | + region->top, |
1015 | + region->right, |
1016 | + region->bottom, |
1017 | + region->weight); |
1018 | + |
1019 | + control->camera_parameters.set( |
1020 | + android::CameraParameters::KEY_FOCUS_AREAS, |
1021 | + focus_region); |
1022 | + |
1023 | + control->camera->setParameters(control->camera_parameters.flatten()); |
1024 | +} |
1025 | + |
1026 | +void android_camera_reset_focus_region(CameraControl* control) |
1027 | +{ |
1028 | + static FocusRegion region = { 0, 0, 0, 0, 0 }; |
1029 | + |
1030 | + android_camera_set_focus_region(control, ®ion); |
1031 | +} |
1032 | + |
1033 | +void android_camera_set_rotation(CameraControl* control, int rotation) |
1034 | +{ |
1035 | + REPORT_FUNCTION(); |
1036 | + assert(control); |
1037 | + |
1038 | + android::Mutex::Autolock al(control->guard); |
1039 | + control->camera_parameters.set( |
1040 | + android::CameraParameters::KEY_ROTATION, |
1041 | + rotation); |
1042 | + control->camera->setParameters(control->camera_parameters.flatten()); |
1043 | +} |
1044 | + |
1045 | +void android_camera_set_location(CameraControl* control, const float* latitude, const float* longitude, const float* altitude, int timestamp, const char* method) |
1046 | +{ |
1047 | + REPORT_FUNCTION(); |
1048 | + assert(control); |
1049 | + |
1050 | + android::Mutex::Autolock al(control->guard); |
1051 | + control->camera_parameters.setFloat( |
1052 | + android::CameraParameters::KEY_GPS_LATITUDE, |
1053 | + *latitude); |
1054 | + control->camera_parameters.setFloat( |
1055 | + android::CameraParameters::KEY_GPS_LONGITUDE, |
1056 | + *longitude); |
1057 | + control->camera_parameters.setFloat( |
1058 | + android::CameraParameters::KEY_GPS_ALTITUDE, |
1059 | + *altitude); |
1060 | + control->camera_parameters.set( |
1061 | + android::CameraParameters::KEY_GPS_TIMESTAMP, |
1062 | + timestamp); |
1063 | + control->camera_parameters.set( |
1064 | + android::CameraParameters::KEY_GPS_PROCESSING_METHOD, |
1065 | + method); |
1066 | + control->camera->setParameters(control->camera_parameters.flatten()); |
1067 | +} |
1068 | + |
1069 | +void android_camera_enumerate_supported_video_sizes(CameraControl* control, size_callback cb, void* ctx) |
1070 | +{ |
1071 | + REPORT_FUNCTION(); |
1072 | + assert(control); |
1073 | + assert(cb); |
1074 | + |
1075 | + android::Mutex::Autolock al(control->guard); |
1076 | + android::Vector<android::Size> sizes; |
1077 | + control->camera_parameters.getSupportedVideoSizes(sizes); |
1078 | + |
1079 | + for (unsigned int i = 0; i < sizes.size(); i++) { |
1080 | + cb(ctx, sizes[i].width, sizes[i].height); |
1081 | + } |
1082 | +} |
1083 | + |
1084 | +void android_camera_get_video_size(CameraControl* control, int* width, int* height) |
1085 | +{ |
1086 | + REPORT_FUNCTION(); |
1087 | + assert(control); |
1088 | + |
1089 | + android::Mutex::Autolock al(control->guard); |
1090 | + |
1091 | + control->camera_parameters.getVideoSize(width, height); |
1092 | +} |
1093 | + |
1094 | +void android_camera_set_video_size(CameraControl* control, int width, int height) |
1095 | +{ |
1096 | + REPORT_FUNCTION(); |
1097 | + assert(control); |
1098 | + |
1099 | + android::Mutex::Autolock al(control->guard); |
1100 | + |
1101 | + control->camera_parameters.setVideoSize(width, height); |
1102 | + control->camera->setParameters(control->camera_parameters.flatten()); |
1103 | +} |
1104 | + |
1105 | +void android_camera_set_jpeg_quality(CameraControl* control, int quality) |
1106 | +{ |
1107 | + REPORT_FUNCTION(); |
1108 | + assert(control); |
1109 | + |
1110 | + android::Mutex::Autolock al(control->guard); |
1111 | + control->camera_parameters.set( |
1112 | + android::CameraParameters::KEY_JPEG_QUALITY, |
1113 | + quality); |
1114 | + control->camera->setParameters(control->camera_parameters.flatten()); |
1115 | +} |
1116 | + |
1117 | +void android_camera_get_jpeg_quality(CameraControl* control, int* quality) |
1118 | +{ |
1119 | + REPORT_FUNCTION(); |
1120 | + assert(control); |
1121 | + |
1122 | + android::Mutex::Autolock al(control->guard); |
1123 | + *quality = atoi(control->camera_parameters.get( |
1124 | + android::CameraParameters::KEY_JPEG_QUALITY)); |
1125 | +} |
1126 | |
1127 | === added file 'android/compat/camera/direct_camera_test.cpp' |
1128 | --- android/compat/camera/direct_camera_test.cpp 1970-01-01 00:00:00 +0000 |
1129 | +++ android/compat/camera/direct_camera_test.cpp 2016-01-11 14:31:46 +0000 |
1130 | @@ -0,0 +1,683 @@ |
1131 | +/* |
1132 | + * Copyright (C) 2013-2014 Canonical Ltd |
1133 | + * |
1134 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
1135 | + * you may not use this file except in compliance with the License. |
1136 | + * You may obtain a copy of the License at |
1137 | + * |
1138 | + * http://www.apache.org/licenses/LICENSE-2.0 |
1139 | + * |
1140 | + * Unless required by applicable law or agreed to in writing, software |
1141 | + * distributed under the License is distributed on an "AS IS" BASIS, |
1142 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
1143 | + * See the License for the specific language governing permissions and |
1144 | + * limitations under the License. |
1145 | + * |
1146 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1147 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> |
1148 | + * Jim Hodapp <jim.hodapp@canonical.com> |
1149 | + */ |
1150 | + |
1151 | +#include <hybris/camera/camera_compatibility_layer.h> |
1152 | +#include <hybris/camera/camera_compatibility_layer_capabilities.h> |
1153 | +#include <hybris/media/media_recorder_layer.h> |
1154 | + |
1155 | +#include <hybris/input/input_stack_compatibility_layer.h> |
1156 | +#include <hybris/input/input_stack_compatibility_layer_codes_key.h> |
1157 | +#include <hybris/input/input_stack_compatibility_layer_flags_key.h> |
1158 | +#include <hybris/input/input_stack_compatibility_layer_flags_motion.h> |
1159 | + |
1160 | +#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h> |
1161 | + |
1162 | +#include <gui/ISurfaceComposer.h> |
1163 | + |
1164 | +#include <GLES2/gl2.h> |
1165 | +#include <GLES2/gl2ext.h> |
1166 | + |
1167 | +#include <sys/stat.h> |
1168 | +#include <sys/types.h> |
1169 | +#include <fcntl.h> |
1170 | +#include <unistd.h> |
1171 | + |
1172 | +#include <cassert> |
1173 | +#include <cstdio> |
1174 | +#include <cstdlib> |
1175 | +#include <cstring> |
1176 | + |
1177 | +int shot_counter = 1; |
1178 | +int32_t current_zoom_level = 1; |
1179 | +bool new_camera_frame_available = true; |
1180 | +static CameraControl* camera_control = NULL; |
1181 | +int camera_width = 0, camera_height = 0; |
1182 | +int thumbnail_width = 0, thumbnail_height = 0; |
1183 | +static MediaRecorderWrapper *recorder = NULL; |
1184 | +bool recording = false; |
1185 | + |
1186 | +EffectMode next_effect() |
1187 | +{ |
1188 | + static EffectMode current_effect = EFFECT_MODE_NONE; |
1189 | + |
1190 | + EffectMode next = current_effect; |
1191 | + |
1192 | + switch (current_effect) { |
1193 | + case EFFECT_MODE_NONE: |
1194 | + next = EFFECT_MODE_MONO; |
1195 | + break; |
1196 | + case EFFECT_MODE_MONO: |
1197 | + next = EFFECT_MODE_NEGATIVE; |
1198 | + break; |
1199 | + case EFFECT_MODE_NEGATIVE: |
1200 | + next = EFFECT_MODE_SOLARIZE; |
1201 | + break; |
1202 | + case EFFECT_MODE_SOLARIZE: |
1203 | + next = EFFECT_MODE_SEPIA; |
1204 | + break; |
1205 | + case EFFECT_MODE_SEPIA: |
1206 | + next = EFFECT_MODE_POSTERIZE; |
1207 | + break; |
1208 | + case EFFECT_MODE_POSTERIZE: |
1209 | + next = EFFECT_MODE_WHITEBOARD; |
1210 | + break; |
1211 | + case EFFECT_MODE_WHITEBOARD: |
1212 | + next = EFFECT_MODE_BLACKBOARD; |
1213 | + break; |
1214 | + case EFFECT_MODE_BLACKBOARD: |
1215 | + next = EFFECT_MODE_AQUA; |
1216 | + break; |
1217 | + case EFFECT_MODE_AQUA: |
1218 | + next = EFFECT_MODE_NONE; |
1219 | + break; |
1220 | + } |
1221 | + |
1222 | + current_effect = next; |
1223 | + return next; |
1224 | +} |
1225 | + |
1226 | +void error_msg_cb(void* context) |
1227 | +{ |
1228 | + printf("%s \n", __PRETTY_FUNCTION__); |
1229 | +} |
1230 | + |
1231 | +void shutter_msg_cb(void* context) |
1232 | +{ |
1233 | + printf("%s \n", __PRETTY_FUNCTION__); |
1234 | +} |
1235 | + |
1236 | +void zoom_msg_cb(void* context, int32_t new_zoom_level) |
1237 | +{ |
1238 | + printf("%s \n", __PRETTY_FUNCTION__); |
1239 | + |
1240 | + CameraControl* cc = static_cast<CameraControl*>(context); |
1241 | + static int zoom; |
1242 | + android_camera_get_current_zoom(cc, &zoom); |
1243 | + printf("\t Current zoom: %d\n", zoom); |
1244 | + current_zoom_level = new_zoom_level; |
1245 | +} |
1246 | + |
1247 | +void autofocus_msg_cb(void* context) |
1248 | +{ |
1249 | + printf("%s \n", __PRETTY_FUNCTION__); |
1250 | +} |
1251 | + |
1252 | +void raw_data_cb(void* data, uint32_t data_size, void* context) |
1253 | +{ |
1254 | + printf("%s: %d \n", __PRETTY_FUNCTION__, data_size); |
1255 | +} |
1256 | + |
1257 | +void jpeg_data_cb(void* data, uint32_t data_size, void* context) |
1258 | +{ |
1259 | + printf("%s: %d \n", __PRETTY_FUNCTION__, data_size); |
1260 | + |
1261 | + char fn[256]; |
1262 | + sprintf(fn, "/cache/shot_%d.jpeg", shot_counter); |
1263 | + int fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); |
1264 | + write(fd, data, data_size); |
1265 | + close(fd); |
1266 | + shot_counter++; |
1267 | + |
1268 | + CameraControl* cc = static_cast<CameraControl*>(context); |
1269 | + android_camera_start_preview(cc); |
1270 | +} |
1271 | + |
1272 | +void size_cb(void* ctx, int width, int height) |
1273 | +{ |
1274 | + printf("Supported size: [%d,%d]\n", width, height); |
1275 | + if (width == 1024 && height == 768) { |
1276 | + camera_width = 1024; |
1277 | + camera_height = 768; |
1278 | + } |
1279 | +} |
1280 | + |
1281 | +void thumbnail_size_cb(void* ctx, int width, int height) |
1282 | +{ |
1283 | + static bool do_once = true; |
1284 | + printf("Supported thumbnail size: [%d,%d]\n", width, height); |
1285 | + if (do_once) { |
1286 | + printf("Selecting thumbnail size: [%dx%d]\n", width, height); |
1287 | + thumbnail_width = width; |
1288 | + thumbnail_height = height; |
1289 | + } |
1290 | +} |
1291 | + |
1292 | +struct RenderData |
1293 | +{ |
1294 | + static const char* vertex_shader() |
1295 | + { |
1296 | + return |
1297 | + "#extension GL_OES_EGL_image_external : require \n" |
1298 | + "attribute vec4 a_position; \n" |
1299 | + "attribute vec2 a_texCoord; \n" |
1300 | + "uniform mat4 m_texMatrix; \n" |
1301 | + "varying vec2 v_texCoord; \n" |
1302 | + "varying float topDown; \n" |
1303 | + "void main() \n" |
1304 | + "{ \n" |
1305 | + " gl_Position = a_position; \n" |
1306 | + " v_texCoord = a_texCoord; \n" |
1307 | + // " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n" |
1308 | + //" topDown = v_texCoord.y; \n" |
1309 | + "} \n"; |
1310 | + } |
1311 | + |
1312 | + static const char* fragment_shader() |
1313 | + { |
1314 | + return |
1315 | + "#extension GL_OES_EGL_image_external : require \n" |
1316 | + "precision mediump float; \n" |
1317 | + "varying vec2 v_texCoord; \n" |
1318 | + "uniform samplerExternalOES s_texture; \n" |
1319 | + "void main() \n" |
1320 | + "{ \n" |
1321 | + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" |
1322 | + "} \n"; |
1323 | + } |
1324 | + |
1325 | + static GLuint loadShader(GLenum shaderType, const char* pSource) |
1326 | + { |
1327 | + GLuint shader = glCreateShader(shaderType); |
1328 | + |
1329 | + if (shader) { |
1330 | + glShaderSource(shader, 1, &pSource, NULL); |
1331 | + glCompileShader(shader); |
1332 | + GLint compiled = 0; |
1333 | + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); |
1334 | + |
1335 | + if (!compiled) { |
1336 | + GLint infoLen = 0; |
1337 | + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); |
1338 | + if (infoLen) { |
1339 | + char* buf = (char*) malloc(infoLen); |
1340 | + if (buf) { |
1341 | + glGetShaderInfoLog(shader, infoLen, NULL, buf); |
1342 | + fprintf(stderr, "Could not compile shader %d:\n%s\n", |
1343 | + shaderType, buf); |
1344 | + free(buf); |
1345 | + } |
1346 | + glDeleteShader(shader); |
1347 | + shader = 0; |
1348 | + } |
1349 | + } |
1350 | + } else { |
1351 | + printf("Error, during shader creation: %i\n", glGetError()); |
1352 | + } |
1353 | + |
1354 | + return shader; |
1355 | + } |
1356 | + |
1357 | + static GLuint create_program(const char* pVertexSource, const char* pFragmentSource) |
1358 | + { |
1359 | + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); |
1360 | + if (!vertexShader) { |
1361 | + printf("vertex shader not compiled\n"); |
1362 | + return 0; |
1363 | + } |
1364 | + |
1365 | + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); |
1366 | + if (!pixelShader) { |
1367 | + printf("frag shader not compiled\n"); |
1368 | + return 0; |
1369 | + } |
1370 | + |
1371 | + GLuint program = glCreateProgram(); |
1372 | + if (program) { |
1373 | + glAttachShader(program, vertexShader); |
1374 | + glAttachShader(program, pixelShader); |
1375 | + glLinkProgram(program); |
1376 | + GLint linkStatus = GL_FALSE; |
1377 | + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); |
1378 | + |
1379 | + if (linkStatus != GL_TRUE) { |
1380 | + GLint bufLength = 0; |
1381 | + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); |
1382 | + if (bufLength) { |
1383 | + char* buf = (char*) malloc(bufLength); |
1384 | + if (buf) { |
1385 | + glGetProgramInfoLog(program, bufLength, NULL, buf); |
1386 | + fprintf(stderr, "Could not link program:\n%s\n", buf); |
1387 | + free(buf); |
1388 | + } |
1389 | + } |
1390 | + glDeleteProgram(program); |
1391 | + program = 0; |
1392 | + } |
1393 | + } |
1394 | + |
1395 | + return program; |
1396 | + } |
1397 | + |
1398 | + RenderData() : program_object(create_program(vertex_shader(), fragment_shader())) |
1399 | + { |
1400 | + position_loc = glGetAttribLocation(program_object, "a_position"); |
1401 | + tex_coord_loc = glGetAttribLocation(program_object, "a_texCoord"); |
1402 | + sampler_loc = glGetUniformLocation(program_object, "s_texture"); |
1403 | + matrix_loc = glGetUniformLocation(program_object, "m_texMatrix"); |
1404 | + } |
1405 | + |
1406 | + // Handle to a program object |
1407 | + GLuint program_object; |
1408 | + // Attribute locations |
1409 | + GLint position_loc; |
1410 | + GLint tex_coord_loc; |
1411 | + // Sampler location |
1412 | + GLint sampler_loc; |
1413 | + // Matrix location |
1414 | + GLint matrix_loc; |
1415 | +}; |
1416 | + |
1417 | + |
1418 | +static RenderData render_data; |
1419 | +static EGLDisplay disp; |
1420 | +static EGLSurface surface; |
1421 | + |
1422 | +void preview_texture_needs_update_cb(void* ctx) |
1423 | +{ |
1424 | + ALOGD("Updating preview texture"); |
1425 | + new_camera_frame_available = true; |
1426 | + static GLfloat vVertices[] = { 0.0f, 0.0f, 0.0f, // Position 0 |
1427 | + 0.0f, 0.0f, // TexCoord 0 |
1428 | + 0.0f, 1.0f, 0.0f, // Position 1 |
1429 | + 0.0f, 1.0f, // TexCoord 1 |
1430 | + 1.0f, 1.0f, 0.0f, // Position 2 |
1431 | + 1.0f, 1.0f, // TexCoord 2 |
1432 | + 1.0f, 0.0f, 0.0f, // Position 3 |
1433 | + 1.0f, 0.0f // TexCoord 3 |
1434 | + }; |
1435 | + |
1436 | + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; |
1437 | + |
1438 | + // Set the viewport |
1439 | + // Clear the color buffer |
1440 | + glClear(GL_COLOR_BUFFER_BIT); |
1441 | + // Use the program object |
1442 | + glUseProgram(render_data.program_object); |
1443 | + // Enable attributes |
1444 | + glEnableVertexAttribArray(render_data.position_loc); |
1445 | + glEnableVertexAttribArray(render_data.tex_coord_loc); |
1446 | + // Load the vertex position |
1447 | + glVertexAttribPointer(render_data.position_loc, |
1448 | + 3, |
1449 | + GL_FLOAT, |
1450 | + GL_FALSE, |
1451 | + 5 * sizeof(GLfloat), |
1452 | + vVertices); |
1453 | + // Load the texture coordinate |
1454 | + glVertexAttribPointer(render_data.tex_coord_loc, |
1455 | + 2, |
1456 | + GL_FLOAT, |
1457 | + GL_FALSE, |
1458 | + 5 * sizeof(GLfloat), |
1459 | + vVertices+3); |
1460 | + |
1461 | + glActiveTexture(GL_TEXTURE0); |
1462 | + // Set the sampler texture unit to 0 |
1463 | + glUniform1i(render_data.sampler_loc, 0); |
1464 | + glUniform1i(render_data.matrix_loc, 0); |
1465 | + ALOGD("Updating the preview texture"); |
1466 | + if (camera_control != NULL) |
1467 | + android_camera_update_preview_texture(camera_control); |
1468 | + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); |
1469 | + glDisableVertexAttribArray(render_data.position_loc); |
1470 | + glDisableVertexAttribArray(render_data.tex_coord_loc); |
1471 | + |
1472 | + eglSwapBuffers(disp, surface); |
1473 | +} |
1474 | + |
1475 | +static void errorCB(void *context) |
1476 | +{ |
1477 | + ALOGE("Error while recording."); |
1478 | +} |
1479 | + |
1480 | +static MediaRecorderWrapper *start_video_recording(CameraControl *camera_control) |
1481 | +{ |
1482 | + int ret = 0; |
1483 | + struct MediaRecorderWrapper *recorder = android_media_new_recorder(); |
1484 | + android_recorder_set_error_cb(recorder, &errorCB, NULL); |
1485 | + |
1486 | + ALOGD("Unlocking camera"); |
1487 | + android_camera_unlock(camera_control); |
1488 | + if (recorder == NULL) |
1489 | + ALOGW("recorder is NULL: %d", __LINE__); |
1490 | + |
1491 | + ret = android_recorder_setCamera(recorder, camera_control); |
1492 | + if (ret < 0) { |
1493 | + ALOGE("android_recorder_setCamera() failed"); |
1494 | + return NULL; |
1495 | + } |
1496 | + ret = android_recorder_setAudioSource(recorder, ANDROID_AUDIO_SOURCE_CAMCORDER); |
1497 | + if (ret < 0) { |
1498 | + ALOGE("android_recorder_setAudioSource() failed"); |
1499 | + return NULL; |
1500 | + } |
1501 | + ret = android_recorder_setVideoSource(recorder, ANDROID_VIDEO_SOURCE_CAMERA); |
1502 | + if (ret < 0) { |
1503 | + ALOGE("android_recorder_setVideoSource() failed"); |
1504 | + return NULL; |
1505 | + } |
1506 | + ret = android_recorder_setOutputFormat(recorder, ANDROID_OUTPUT_FORMAT_MPEG_4); |
1507 | + if (ret < 0) { |
1508 | + ALOGE("android_recorder_setOutputFormat() failed"); |
1509 | + return NULL; |
1510 | + } |
1511 | + ret = android_recorder_setAudioEncoder(recorder, ANDROID_AUDIO_ENCODER_AAC); |
1512 | + if (ret < 0) { |
1513 | + ALOGE("android_recorder_setAudioEncoder() failed"); |
1514 | + return NULL; |
1515 | + } |
1516 | + ret = android_recorder_setVideoEncoder(recorder, ANDROID_VIDEO_ENCODER_H264); |
1517 | + if (ret < 0) { |
1518 | + ALOGE("android_recorder_setVideoEncoder() failed"); |
1519 | + return NULL; |
1520 | + } |
1521 | + int fd = -1; |
1522 | + char *out_file = "/cache/test_recording.mp4"; |
1523 | + fd = open(out_file, O_WRONLY | O_CREAT, |
1524 | + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |
1525 | + if (fd < 0) { |
1526 | + ALOGE("Couldn't open output video file for recording: %s", out_file); |
1527 | + return NULL; |
1528 | + } |
1529 | + ret = android_recorder_setOutputFile(recorder, fd); |
1530 | + if (ret < 0) { |
1531 | + ALOGE("android_recorder_setOutputFile() failed"); |
1532 | + return NULL; |
1533 | + } |
1534 | + ret = android_recorder_setVideoSize(recorder, camera_width, camera_height); |
1535 | + if (ret < 0) { |
1536 | + ALOGE("android_recorder_setVideoSize() failed"); |
1537 | + return NULL; |
1538 | + } |
1539 | + ret = android_recorder_setVideoFrameRate(recorder, 30); |
1540 | + if (ret < 0) { |
1541 | + ALOGE("android_recorder_setVideoFrameRate() failed"); |
1542 | + return NULL; |
1543 | + } |
1544 | + android_recorder_setParameters(recorder, "video-param-encoding-bitrate=5505024"); // 7*1024*768 |
1545 | + android_recorder_setParameters(recorder, "audio-param-encoding-bitrate=48000"); |
1546 | + android_recorder_setParameters(recorder, "audio-param-number-of-channels=2"); |
1547 | + android_recorder_setParameters(recorder, "audio-param-sampling-rate=96000"); |
1548 | + android_recorder_setParameters(recorder, "video-param-rotation-angle-degrees=90"); |
1549 | + ALOGD("Preparing video recording"); |
1550 | + ret = android_recorder_prepare(recorder); |
1551 | + if (ret < 0) { |
1552 | + ALOGE("android_recorder_prepare() failed"); |
1553 | + return NULL; |
1554 | + } |
1555 | + ALOGD("Starting video recording"); |
1556 | + ret = android_recorder_start(recorder); |
1557 | + if (ret < 0) { |
1558 | + ALOGE("android_recorder_start() failed"); |
1559 | + return NULL; |
1560 | + } |
1561 | + |
1562 | + return recorder; |
1563 | +} |
1564 | + |
1565 | +static void stop_video_recording(MediaRecorderWrapper *recorder) |
1566 | +{ |
1567 | + if (recording) { |
1568 | + ALOGD("Stopping video recording"); |
1569 | + android_recorder_stop(recorder); |
1570 | + android_recorder_reset(recorder); |
1571 | + android_recorder_release(recorder); |
1572 | + ALOGD("Stopped video recording"); |
1573 | + } |
1574 | +} |
1575 | + |
1576 | +void on_new_input_event(Event* event, void* context) |
1577 | +{ |
1578 | + assert(context); |
1579 | + |
1580 | + if (event->type == KEY_EVENT_TYPE && event->action == ISCL_KEY_EVENT_ACTION_UP) { |
1581 | + printf("We got a key event: %d \n", event->details.key.key_code); |
1582 | + |
1583 | + CameraControl* cc = static_cast<CameraControl*>(context); |
1584 | + |
1585 | + switch(event->details.key.key_code) { |
1586 | + case ISCL_KEYCODE_VOLUME_UP: |
1587 | + printf("Starting video recording to /cache/test_recording.mp4\n"); |
1588 | + start_video_recording(cc); |
1589 | + recording = true; |
1590 | + break; |
1591 | + case ISCL_KEYCODE_VOLUME_DOWN: |
1592 | + printf("Stopping video recording\n"); |
1593 | + stop_video_recording(recorder); |
1594 | + recording = false; |
1595 | + break; |
1596 | + case ISCL_KEYCODE_POWER: |
1597 | + printf("\tTaking a photo now.\n"); |
1598 | + android_camera_take_snapshot(cc); |
1599 | + break; |
1600 | + case ISCL_KEYCODE_HEADSETHOOK: |
1601 | + printf("\tSwitching effect.\n"); |
1602 | + android_camera_set_effect_mode(cc, next_effect()); |
1603 | + } |
1604 | + } else if (event->type == MOTION_EVENT_TYPE && |
1605 | + event->details.motion.pointer_count == 1) { |
1606 | + if ((event->action & ISCL_MOTION_EVENT_ACTION_MASK) == ISCL_MOTION_EVENT_ACTION_UP) { |
1607 | + printf("\tMotion event(Action up): (%f, %f) \n", |
1608 | + event->details.motion.pointer_coordinates[0].x, |
1609 | + event->details.motion.pointer_coordinates[0].y); |
1610 | + } |
1611 | + |
1612 | + if ((event->action & ISCL_MOTION_EVENT_ACTION_MASK) == ISCL_MOTION_EVENT_ACTION_DOWN) { |
1613 | + printf("\tMotion event(Action down): (%f, %f) \n", |
1614 | + event->details.motion.pointer_coordinates[0].x, |
1615 | + event->details.motion.pointer_coordinates[0].y); |
1616 | + } |
1617 | + } |
1618 | +} |
1619 | + |
1620 | +struct ClientWithSurface |
1621 | +{ |
1622 | + SfClient* client; |
1623 | + SfSurface* surface; |
1624 | +}; |
1625 | + |
1626 | +ClientWithSurface client_with_surface(bool setup_surface_with_egl) |
1627 | +{ |
1628 | + ClientWithSurface cs = ClientWithSurface(); |
1629 | + |
1630 | + cs.client = sf_client_create(); |
1631 | + |
1632 | + if (!cs.client) { |
1633 | + printf("Problem creating client ... aborting now."); |
1634 | + return cs; |
1635 | + } |
1636 | + |
1637 | + static const size_t primary_display = 0; |
1638 | + |
1639 | + SfSurfaceCreationParameters params = { |
1640 | + 0, |
1641 | + 0, |
1642 | + (int) sf_get_display_width(primary_display), |
1643 | + (int) sf_get_display_height(primary_display), |
1644 | + -1, //PIXEL_FORMAT_RGBA_8888, |
1645 | + 15000, |
1646 | + 0.5f, |
1647 | + setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL |
1648 | + "CameraCompatLayerTestSurface" |
1649 | + }; |
1650 | + |
1651 | + cs.surface = sf_surface_create(cs.client, ¶ms); |
1652 | + |
1653 | + if (!cs.surface) { |
1654 | + printf("Problem creating surface ... aborting now."); |
1655 | + return cs; |
1656 | + } |
1657 | + |
1658 | + sf_surface_make_current(cs.surface); |
1659 | + |
1660 | + return cs; |
1661 | +} |
1662 | + |
1663 | +#define PRINT_GLERROR() printf("GL error@%d: %x\n", __LINE__, glGetError()); |
1664 | + |
1665 | +int main(int argc, char** argv) |
1666 | +{ |
1667 | + CameraControlListener listener; |
1668 | + memset(&listener, 0, sizeof(listener)); |
1669 | + listener.on_msg_error_cb = error_msg_cb; |
1670 | + listener.on_msg_shutter_cb = shutter_msg_cb; |
1671 | + listener.on_msg_focus_cb = autofocus_msg_cb; |
1672 | + listener.on_msg_zoom_cb = zoom_msg_cb; |
1673 | + |
1674 | + listener.on_data_raw_image_cb = raw_data_cb; |
1675 | + listener.on_data_compressed_image_cb = jpeg_data_cb; |
1676 | + listener.on_preview_texture_needs_update_cb = preview_texture_needs_update_cb; |
1677 | + camera_control = android_camera_connect_to(BACK_FACING_CAMERA_TYPE, |
1678 | + &listener); |
1679 | + |
1680 | + if (camera_control == NULL) { |
1681 | + printf("Problem connecting to camera"); |
1682 | + return 1; |
1683 | + } |
1684 | + listener.context = camera_control; |
1685 | + |
1686 | + AndroidEventListener event_listener; |
1687 | + event_listener.on_new_event = on_new_input_event; |
1688 | + event_listener.context = camera_control; |
1689 | + |
1690 | + InputStackConfiguration input_configuration = { |
1691 | + enable_touch_point_visualization : true, |
1692 | + default_layer_for_touch_point_visualization : 10000, |
1693 | + input_area_width : 1024, |
1694 | + input_area_height : 1024 |
1695 | + }; |
1696 | + |
1697 | + android_input_stack_initialize(&event_listener, &input_configuration); |
1698 | + android_input_stack_start(); |
1699 | + |
1700 | + // Set the still photo size |
1701 | + android_camera_enumerate_supported_picture_sizes(camera_control, size_cb, NULL); |
1702 | + if (camera_width == 0 && camera_height == 0) { |
1703 | + camera_width = 320; |
1704 | + camera_height = 240; |
1705 | + } |
1706 | + android_camera_set_picture_size(camera_control, camera_width, camera_height); |
1707 | + |
1708 | + // Set the still photo thumbnail size |
1709 | + android_camera_enumerate_supported_thumbnail_sizes(camera_control, thumbnail_size_cb, NULL); |
1710 | + if (thumbnail_width == 0 && thumbnail_height == 0) { |
1711 | + thumbnail_width = 320; |
1712 | + thumbnail_height = 240; |
1713 | + } |
1714 | + android_camera_set_thumbnail_size(camera_control, thumbnail_width, thumbnail_height); |
1715 | + |
1716 | + AutoFocusMode af_mode; |
1717 | + android_camera_get_auto_focus_mode(camera_control, &af_mode); |
1718 | + printf("Current af mode: %d \n", af_mode); |
1719 | + |
1720 | + int zoom; |
1721 | + android_camera_set_zoom(camera_control, 0); |
1722 | + android_camera_get_max_zoom(camera_control, &zoom); |
1723 | + printf("Max zoom: %d \n", zoom); |
1724 | + |
1725 | + android_camera_enumerate_supported_video_sizes(camera_control, size_cb, NULL); |
1726 | + android_camera_enumerate_supported_preview_sizes(camera_control, size_cb, NULL); |
1727 | + android_camera_set_preview_size(camera_control, camera_width, camera_height); |
1728 | + |
1729 | + int min_fps, max_fps, current_fps; |
1730 | + android_camera_get_preview_fps_range(camera_control, &min_fps, &max_fps); |
1731 | + printf("Preview fps range: [%d,%d]\n", min_fps, max_fps); |
1732 | + android_camera_get_preview_fps(camera_control, ¤t_fps); |
1733 | + printf("Current preview fps range: %d\n", current_fps); |
1734 | + |
1735 | +#if 0 |
1736 | + android_camera_dump_parameters(camera_control); |
1737 | + |
1738 | + android_camera_set_display_orientation(camera_control, 90); |
1739 | + |
1740 | + int width, height; |
1741 | + android_camera_get_preview_size(camera_control, &width, &height); |
1742 | + printf("Current preview size: [%d,%d]\n", width, height); |
1743 | + android_camera_get_picture_size(camera_control, &width, &height); |
1744 | + printf("Current picture size: [%d,%d]\n", width, height); |
1745 | + android_camera_get_current_zoom(camera_control, &zoom); |
1746 | + printf("Current zoom: %d \n", zoom); |
1747 | + |
1748 | + EffectMode effect_mode; |
1749 | + FlashMode flash_mode; |
1750 | + WhiteBalanceMode wb_mode; |
1751 | + //SceneMode scene_mode; |
1752 | + CameraPixelFormat pixel_format; |
1753 | + android_camera_get_effect_mode(camera_control, &effect_mode); |
1754 | + printf("Current effect mode: %d \n", effect_mode); |
1755 | + android_camera_get_flash_mode(camera_control, &flash_mode); |
1756 | + printf("Current flash mode: %d \n", flash_mode); |
1757 | + android_camera_get_white_balance_mode(camera_control, &wb_mode); |
1758 | + ALOGD("Current wb mode: %d \n", wb_mode); |
1759 | +#if 0 |
1760 | + // Disabled, causes the test app to crash |
1761 | + android_camera_get_scene_mode(camera_control, &scene_mode); |
1762 | + printf("Current scene mode: %d \n", scene_mode); |
1763 | +#endif |
1764 | + android_camera_get_preview_format(camera_control, &pixel_format); |
1765 | + printf("Current preview pixel format: %d \n", pixel_format); |
1766 | + //android_camera_set_focus_region(camera_control, -200, -200, 200, 200, 300); |
1767 | +#endif |
1768 | + |
1769 | + printf("Creating client with surface"); |
1770 | + ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */); |
1771 | + |
1772 | + if (!cs.surface) { |
1773 | + printf("Problem acquiring surface for preview"); |
1774 | + return 1; |
1775 | + } |
1776 | + printf("Finished creating client with surface\n"); |
1777 | + |
1778 | + disp = sf_client_get_egl_display(cs.client); |
1779 | + surface = sf_surface_get_egl_surface(cs.surface); |
1780 | + |
1781 | + GLuint preview_texture_id; |
1782 | + printf("Getting a texture id\n"); |
1783 | + glGenTextures(1, &preview_texture_id); |
1784 | + glClearColor(1.0, 0., 0.5, 1.); |
1785 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
1786 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
1787 | + glTexParameteri( |
1788 | + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1789 | + glTexParameteri( |
1790 | + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1791 | + printf("About to set preview texture\n"); |
1792 | + android_camera_set_preview_texture(camera_control, preview_texture_id); |
1793 | +#if 0 |
1794 | + android_camera_set_effect_mode(camera_control, EFFECT_MODE_SEPIA); |
1795 | + android_camera_set_flash_mode(camera_control, FLASH_MODE_AUTO); |
1796 | + android_camera_set_auto_focus_mode(camera_control, AUTO_FOCUS_MODE_CONTINUOUS_PICTURE); |
1797 | +#endif |
1798 | + android_camera_start_preview(camera_control); |
1799 | + |
1800 | + GLfloat transformation_matrix[16]; |
1801 | + android_camera_get_preview_texture_transformation(camera_control, transformation_matrix); |
1802 | + glUniformMatrix4fv(render_data.matrix_loc, 1, GL_FALSE, transformation_matrix); |
1803 | + |
1804 | + printf("Started camera preview.\n"); |
1805 | + |
1806 | + while (1) { |
1807 | + usleep(50); |
1808 | + } |
1809 | + |
1810 | + stop_video_recording(recorder); |
1811 | + android_camera_stop_preview(camera_control); |
1812 | + android_camera_disconnect(camera_control); |
1813 | +} |
1814 | |
1815 | === added directory 'android/compat/input' |
1816 | === added file 'android/compat/input/Android.mk' |
1817 | --- android/compat/input/Android.mk 1970-01-01 00:00:00 +0000 |
1818 | +++ android/compat/input/Android.mk 2016-01-11 14:31:46 +0000 |
1819 | @@ -0,0 +1,77 @@ |
1820 | +LOCAL_PATH := $(call my-dir) |
1821 | +include $(CLEAR_VARS) |
1822 | +include $(LOCAL_PATH)/../Android.common.mk |
1823 | + |
1824 | +HYBRIS_PATH := $(LOCAL_PATH)/../../hybris |
1825 | + |
1826 | +LOCAL_CFLAGS += -std=gnu++0x |
1827 | + |
1828 | +LOCAL_SRC_FILES:= input_compatibility_layer.cpp |
1829 | + |
1830 | +LOCAL_MODULE:= libis_compat_layer |
1831 | +LOCAL_MODULE_TAGS := optional |
1832 | + |
1833 | +LOCAL_SHARED_LIBRARIES := \ |
1834 | + libinput \ |
1835 | + libcutils \ |
1836 | + libutils \ |
1837 | + libskia \ |
1838 | + libgui \ |
1839 | + libandroidfw |
1840 | + |
1841 | +LOCAL_C_INCLUDES := \ |
1842 | + $(HYBRIS_PATH)/include \ |
1843 | + external/skia/include/core |
1844 | + |
1845 | +HAS_LIBINPUTSERVICE := $(shell test $(ANDROID_VERSION_MAJOR) -eq 4 -a $(ANDROID_VERSION_MINOR) -gt 2 && echo true) |
1846 | +ifeq ($(HAS_LIBINPUTSERVICE),true) |
1847 | +LOCAL_SHARED_LIBRARIES += libinputservice |
1848 | +LOCAL_C_INCLUDES += frameworks/base/services/input |
1849 | +endif |
1850 | + |
1851 | +HAS_LIBINPUTFLINGER := $(shell test $(ANDROID_VERSION_MAJOR) -eq 5 && echo true) |
1852 | +ifeq ($(HAS_LIBINPUTFLINGER),true) |
1853 | +LOCAL_SHARED_LIBRARIES += libinputflinger libinputservice |
1854 | +LOCAL_C_INCLUDES += \ |
1855 | + frameworks/base/libs/input \ |
1856 | + frameworks/native/services |
1857 | +endif |
1858 | + |
1859 | + |
1860 | + |
1861 | + |
1862 | +include $(BUILD_SHARED_LIBRARY) |
1863 | + |
1864 | +include $(CLEAR_VARS) |
1865 | + |
1866 | +HYBRIS_PATH := $(LOCAL_PATH)/../../hybris |
1867 | + |
1868 | +LOCAL_CFLAGS += -std=gnu++0x |
1869 | + |
1870 | +LOCAL_SRC_FILES:= \ |
1871 | + direct_input_test.cpp |
1872 | + |
1873 | +LOCAL_MODULE:= direct_input_test |
1874 | +LOCAL_MODULE_TAGS := optional |
1875 | + |
1876 | +LOCAL_C_INCLUDES := \ |
1877 | + $(HYBRIS_PATH)/include \ |
1878 | + bionic \ |
1879 | + bionic/libstdc++/include \ |
1880 | + external/gtest/include \ |
1881 | + external/stlport/stlport \ |
1882 | + external/skia/include/core |
1883 | + |
1884 | +LOCAL_SHARED_LIBRARIES := \ |
1885 | + libis_compat_layer \ |
1886 | + libcutils \ |
1887 | + libutils \ |
1888 | + libskia \ |
1889 | + libgui \ |
1890 | + libandroidfw |
1891 | + |
1892 | +static_libraries := \ |
1893 | + libgtest \ |
1894 | + libgtest_main |
1895 | + |
1896 | +include $(BUILD_EXECUTABLE) |
1897 | |
1898 | === added file 'android/compat/input/direct_input_test.cpp' |
1899 | --- android/compat/input/direct_input_test.cpp 1970-01-01 00:00:00 +0000 |
1900 | +++ android/compat/input/direct_input_test.cpp 2016-01-11 14:31:46 +0000 |
1901 | @@ -0,0 +1,85 @@ |
1902 | +/* |
1903 | + * Copyright (C) 2013 Canonical Ltd |
1904 | + * |
1905 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
1906 | + * you may not use this file except in compliance with the License. |
1907 | + * You may obtain a copy of the License at |
1908 | + * |
1909 | + * http://www.apache.org/licenses/LICENSE-2.0 |
1910 | + * |
1911 | + * Unless required by applicable law or agreed to in writing, software |
1912 | + * distributed under the License is distributed on an "AS IS" BASIS, |
1913 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
1914 | + * See the License for the specific language governing permissions and |
1915 | + * limitations under the License. |
1916 | + * |
1917 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1918 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> |
1919 | + */ |
1920 | + |
1921 | +#include <hybris/input/input_stack_compatibility_layer.h> |
1922 | + |
1923 | +#include <gtest/gtest.h> |
1924 | +#include <utils/threads.h> |
1925 | + |
1926 | +#include <signal.h> |
1927 | + |
1928 | +namespace |
1929 | +{ |
1930 | + |
1931 | +bool g_stop = false; |
1932 | + |
1933 | +void signal_handler(int) |
1934 | +{ |
1935 | + g_stop = true; |
1936 | +} |
1937 | + |
1938 | +void on_new_event(Event* event, void* context) |
1939 | +{ |
1940 | + printf("%s", __PRETTY_FUNCTION__); |
1941 | + |
1942 | + printf("\tEventType: %d \n", event->type); |
1943 | + printf("\tdevice_id: %d \n", event->device_id); |
1944 | + printf("\tsource_id: %d \n", event->source_id); |
1945 | + printf("\taction: %d \n", event->action); |
1946 | + printf("\tflags: %d \n", event->flags); |
1947 | + printf("\tmeta_state: %d \n", event->meta_state); |
1948 | + |
1949 | + switch (event->type) { |
1950 | + case MOTION_EVENT_TYPE: |
1951 | + printf("\tdetails.motion.event_time: %lld\n", |
1952 | + event->details.motion.event_time); |
1953 | + printf("\tdetails.motion.pointer_coords.x: %f\n", |
1954 | + event->details.motion.pointer_coordinates[0].x); |
1955 | + printf("\tdetails.motion.pointer_coords.y: %f\n", |
1956 | + event->details.motion.pointer_coordinates[0].y); |
1957 | + break; |
1958 | + default: |
1959 | + break; |
1960 | + } |
1961 | +} |
1962 | + |
1963 | +} |
1964 | + |
1965 | +int main(int argc, char** argv) |
1966 | +{ |
1967 | + g_stop = false; |
1968 | + signal(SIGINT, signal_handler); |
1969 | + |
1970 | + AndroidEventListener listener; |
1971 | + listener.on_new_event = on_new_event; |
1972 | + listener.context = NULL; |
1973 | + |
1974 | + InputStackConfiguration config = { |
1975 | + enable_touch_point_visualization : true, |
1976 | + default_layer_for_touch_point_visualization : 10000, |
1977 | + input_area_width : 1024, |
1978 | + input_area_height : 1024 |
1979 | + }; |
1980 | + |
1981 | + android_input_stack_initialize(&listener, &config); |
1982 | + android_input_stack_start_waiting_for_flag(&g_stop); |
1983 | + |
1984 | + android_input_stack_stop(); |
1985 | + android_input_stack_shutdown(); |
1986 | +} |
1987 | |
1988 | === added file 'android/compat/input/input_compatibility_layer.cpp' |
1989 | --- android/compat/input/input_compatibility_layer.cpp 1970-01-01 00:00:00 +0000 |
1990 | +++ android/compat/input/input_compatibility_layer.cpp 2016-01-11 14:31:46 +0000 |
1991 | @@ -0,0 +1,384 @@ |
1992 | +/* |
1993 | + * Copyright (C) 2013 Canonical Ltd |
1994 | + * |
1995 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
1996 | + * you may not use this file except in compliance with the License. |
1997 | + * You may obtain a copy of the License at |
1998 | + * |
1999 | + * http://www.apache.org/licenses/LICENSE-2.0 |
2000 | + * |
2001 | + * Unless required by applicable law or agreed to in writing, software |
2002 | + * distributed under the License is distributed on an "AS IS" BASIS, |
2003 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2004 | + * See the License for the specific language governing permissions and |
2005 | + * limitations under the License. |
2006 | + * |
2007 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
2008 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> |
2009 | + */ |
2010 | + |
2011 | +#include <hybris/input/input_stack_compatibility_layer.h> |
2012 | + |
2013 | +#if ANDROID_VERSION_MAJOR<=4 |
2014 | + #include "InputListener.h" |
2015 | + #include "InputReader.h" |
2016 | +#elif ANDROID_VERSION_MAJOR==5 |
2017 | + #include "inputflinger/InputListener.h" |
2018 | + #include "inputflinger/InputReader.h" |
2019 | +#endif |
2020 | + |
2021 | +#include "PointerController.h" |
2022 | +#include "SpriteController.h" |
2023 | +#include <gui/ISurfaceComposer.h> |
2024 | +#include <gui/SurfaceComposerClient.h> |
2025 | + |
2026 | +#undef LOG_TAG |
2027 | +#define LOG_TAG "InputStackCompatibilityLayer" |
2028 | +#include <utils/Log.h> |
2029 | + |
2030 | +namespace |
2031 | +{ |
2032 | +static bool enable_verbose_function_reporting = false; |
2033 | +} |
2034 | + |
2035 | +#define REPORT_FUNCTION() ALOGV("%s\n", __PRETTY_FUNCTION__); |
2036 | + |
2037 | +namespace |
2038 | +{ |
2039 | + |
2040 | +class DefaultPointerControllerPolicy : public android::PointerControllerPolicyInterface |
2041 | +{ |
2042 | +public: |
2043 | + static const size_t bitmap_width = 64; |
2044 | + static const size_t bitmap_height = 64; |
2045 | + |
2046 | + DefaultPointerControllerPolicy() |
2047 | + { |
2048 | +#if ANDROID_VERSION_MAJOR<=4 |
2049 | + bitmap.setConfig( |
2050 | + SkBitmap::kARGB_8888_Config, |
2051 | + bitmap_width, |
2052 | + bitmap_height); |
2053 | +#elif ANDROID_VERSION_MAJOR==5 |
2054 | + SkColorType ct = SkBitmapConfigToColorType(SkBitmap::kARGB_8888_Config); |
2055 | + bitmap.setInfo( |
2056 | + SkImageInfo::Make(bitmap_width, |
2057 | + bitmap_height, |
2058 | + ct, |
2059 | + SkAlphaType::kPremul_SkAlphaType), |
2060 | + 0); |
2061 | +#endif |
2062 | + bitmap.allocPixels(); |
2063 | + |
2064 | + // Icon for spot touches |
2065 | + bitmap.eraseARGB(125, 0, 255, 0); |
2066 | + spotTouchIcon = android::SpriteIcon( |
2067 | + bitmap, |
2068 | + bitmap_width/2, |
2069 | + bitmap_height/2); |
2070 | + |
2071 | + // Icon for anchor touches |
2072 | + bitmap.eraseARGB(125, 0, 0, 255); |
2073 | + spotAnchorIcon = android::SpriteIcon( |
2074 | + bitmap, |
2075 | + bitmap_width/2, |
2076 | + bitmap_height/2); |
2077 | + |
2078 | + // Icon for hovering touches |
2079 | + bitmap.eraseARGB(125, 255, 0, 0); |
2080 | + spotHoverIcon = android::SpriteIcon( |
2081 | + bitmap, |
2082 | + bitmap_width/2, |
2083 | + bitmap_height/2); |
2084 | + } |
2085 | + |
2086 | + void loadPointerResources(android::PointerResources* outResources) |
2087 | + { |
2088 | + outResources->spotHover = spotHoverIcon.copy(); |
2089 | + outResources->spotTouch = spotTouchIcon.copy(); |
2090 | + outResources->spotAnchor = spotAnchorIcon.copy(); |
2091 | + } |
2092 | + |
2093 | + android::SpriteIcon spotHoverIcon; |
2094 | + android::SpriteIcon spotTouchIcon; |
2095 | + android::SpriteIcon spotAnchorIcon; |
2096 | + SkBitmap bitmap; |
2097 | +}; |
2098 | + |
2099 | +class DefaultInputReaderPolicyInterface : public android::InputReaderPolicyInterface |
2100 | +{ |
2101 | +public: |
2102 | + static const int32_t internal_display_id = android::ISurfaceComposer::eDisplayIdMain; |
2103 | + static const int32_t external_display_id = android::ISurfaceComposer::eDisplayIdHdmi; |
2104 | + |
2105 | + DefaultInputReaderPolicyInterface( |
2106 | + InputStackConfiguration* configuration, |
2107 | + const android::sp<android::Looper>& looper) |
2108 | + : looper(looper), |
2109 | + default_layer_for_touch_point_visualization(configuration->default_layer_for_touch_point_visualization), |
2110 | + input_area_width(configuration->input_area_width), |
2111 | + input_area_height(configuration->input_area_height) |
2112 | + { |
2113 | + default_configuration.showTouches = configuration->enable_touch_point_visualization; |
2114 | + |
2115 | + android::DisplayViewport viewport; |
2116 | + viewport.setNonDisplayViewport(input_area_width, input_area_height); |
2117 | + viewport.displayId = android::ISurfaceComposer::eDisplayIdMain; |
2118 | + default_configuration.setDisplayInfo( |
2119 | + false, /* external */ |
2120 | + viewport); |
2121 | + } |
2122 | + |
2123 | + void getReaderConfiguration(android::InputReaderConfiguration* outConfig) |
2124 | + { |
2125 | + *outConfig = default_configuration; |
2126 | + } |
2127 | + |
2128 | + android::sp<android::PointerControllerInterface> obtainPointerController(int32_t deviceId) |
2129 | + { |
2130 | + (void) deviceId; |
2131 | + |
2132 | + android::sp<android::SpriteController> sprite_controller( |
2133 | + new android::SpriteController( |
2134 | + looper, |
2135 | + default_layer_for_touch_point_visualization)); |
2136 | + android::sp<android::PointerController> pointer_controller( |
2137 | + new android::PointerController( |
2138 | + android::sp<DefaultPointerControllerPolicy>(new DefaultPointerControllerPolicy()), |
2139 | + looper, |
2140 | + sprite_controller)); |
2141 | + pointer_controller->setPresentation( |
2142 | + android::PointerControllerInterface::PRESENTATION_SPOT); |
2143 | + |
2144 | + pointer_controller->setDisplayViewport(input_area_width, input_area_height, 0); |
2145 | + return pointer_controller; |
2146 | + } |
2147 | + |
2148 | + virtual void notifyInputDevicesChanged(const android::Vector<android::InputDeviceInfo>& inputDevices) { |
2149 | + mInputDevices = inputDevices; |
2150 | + } |
2151 | + |
2152 | +#if ANDROID_VERSION_MAJOR<=4 |
2153 | + virtual android::sp<android::KeyCharacterMap> getKeyboardLayoutOverlay(const android::String8& inputDeviceDescriptor) { |
2154 | +#elif ANDROID_VERSION_MAJOR==5 |
2155 | + virtual android::sp<android::KeyCharacterMap> getKeyboardLayoutOverlay(const android::InputDeviceIdentifier& identifier) { |
2156 | +#endif |
2157 | + return NULL; |
2158 | + } |
2159 | + |
2160 | + virtual android::String8 getDeviceAlias(const android::InputDeviceIdentifier& identifier) { |
2161 | + return android::String8::empty(); |
2162 | + } |
2163 | + |
2164 | +#if ANDROID_VERSION_MAJOR==5 |
2165 | + virtual android::TouchAffineTransformation getTouchAffineTransformation(const android::String8& inputDeviceDescriptor, int32_t surfaceRotation) { |
2166 | + return android::TouchAffineTransformation(); |
2167 | + } |
2168 | +#endif |
2169 | + |
2170 | +private: |
2171 | + android::sp<android::Looper> looper; |
2172 | + int default_layer_for_touch_point_visualization; |
2173 | + android::InputReaderConfiguration default_configuration; |
2174 | + android::Vector<android::InputDeviceInfo> mInputDevices; |
2175 | + int input_area_width; |
2176 | + int input_area_height; |
2177 | +}; |
2178 | + |
2179 | +class ExportedInputListener : public android::InputListenerInterface |
2180 | +{ |
2181 | +public: |
2182 | + ExportedInputListener(AndroidEventListener* external_listener) : external_listener(external_listener) |
2183 | + { |
2184 | + } |
2185 | + |
2186 | + void notifyConfigurationChanged(const android::NotifyConfigurationChangedArgs* args) |
2187 | + { |
2188 | + REPORT_FUNCTION(); |
2189 | + (void) args; |
2190 | + } |
2191 | + |
2192 | + void notifyKey(const android::NotifyKeyArgs* args) |
2193 | + { |
2194 | + REPORT_FUNCTION(); |
2195 | + |
2196 | + current_event.type = KEY_EVENT_TYPE; |
2197 | + current_event.device_id = args->deviceId; |
2198 | + current_event.source_id = args->source; |
2199 | + current_event.action = args->action; |
2200 | + current_event.flags = args->flags; |
2201 | + current_event.meta_state = args->metaState; |
2202 | + |
2203 | + current_event.details.key.key_code = args->keyCode; |
2204 | + current_event.details.key.scan_code = args->scanCode; |
2205 | + current_event.details.key.down_time = args->downTime; |
2206 | + current_event.details.key.event_time = args->eventTime; |
2207 | + |
2208 | + current_event.details.key.is_system_key = false; |
2209 | + |
2210 | + external_listener->on_new_event(¤t_event, external_listener->context); |
2211 | + } |
2212 | + |
2213 | + void notifyMotion(const android::NotifyMotionArgs* args) |
2214 | + { |
2215 | + REPORT_FUNCTION(); |
2216 | + |
2217 | + current_event.type = MOTION_EVENT_TYPE; |
2218 | + current_event.device_id = args->deviceId; |
2219 | + current_event.source_id = args->source; |
2220 | + current_event.action = args->action; |
2221 | + current_event.flags = args->flags; |
2222 | + current_event.meta_state = args->metaState; |
2223 | + |
2224 | + current_event.details.motion.button_state = args->buttonState; |
2225 | + current_event.details.motion.down_time = args->downTime; |
2226 | + current_event.details.motion.event_time = args->eventTime; |
2227 | + current_event.details.motion.edge_flags = args->edgeFlags; |
2228 | + current_event.details.motion.x_precision = args->xPrecision; |
2229 | + current_event.details.motion.y_precision = args->yPrecision; |
2230 | + current_event.details.motion.pointer_count = args->pointerCount; |
2231 | + |
2232 | + for (unsigned int i = 0; i < current_event.details.motion.pointer_count; i++) { |
2233 | + current_event.details.motion.pointer_coordinates[i].id = args->pointerProperties[i].id; |
2234 | + current_event.details.motion.pointer_coordinates[i].x |
2235 | + = current_event.details.motion.pointer_coordinates[i].raw_x |
2236 | + = args->pointerCoords[i].getX(); |
2237 | + current_event.details.motion.pointer_coordinates[i].y |
2238 | + = current_event.details.motion.pointer_coordinates[i].raw_y |
2239 | + = args->pointerCoords[i].getY(); |
2240 | + current_event.details.motion.pointer_coordinates[i].touch_major |
2241 | + = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR); |
2242 | + current_event.details.motion.pointer_coordinates[i].touch_minor |
2243 | + = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR); |
2244 | + current_event.details.motion.pointer_coordinates[i].pressure |
2245 | + = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE); |
2246 | + current_event.details.motion.pointer_coordinates[i].size |
2247 | + = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE); |
2248 | + current_event.details.motion.pointer_coordinates[i].orientation |
2249 | + = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); |
2250 | + |
2251 | + } |
2252 | + |
2253 | + external_listener->on_new_event(¤t_event, external_listener->context); |
2254 | + } |
2255 | + |
2256 | + void notifySwitch(const android::NotifySwitchArgs* args) |
2257 | + { |
2258 | + REPORT_FUNCTION(); |
2259 | + current_event.type = HW_SWITCH_EVENT_TYPE; |
2260 | + |
2261 | + current_event.details.hw_switch.event_time = args->eventTime; |
2262 | + current_event.details.hw_switch.policy_flags = args->policyFlags; |
2263 | + current_event.details.hw_switch.switch_values = args->switchValues; |
2264 | + current_event.details.hw_switch.switch_mask = args->switchMask; |
2265 | + |
2266 | + external_listener->on_new_event(¤t_event, external_listener->context); |
2267 | + } |
2268 | + |
2269 | + void notifyDeviceReset(const android::NotifyDeviceResetArgs* args) |
2270 | + { |
2271 | + REPORT_FUNCTION(); |
2272 | + (void) args; |
2273 | + } |
2274 | + |
2275 | +private: |
2276 | + AndroidEventListener* external_listener; |
2277 | + Event current_event; |
2278 | +}; |
2279 | + |
2280 | +class LooperThread : public android::Thread |
2281 | +{ |
2282 | +public: |
2283 | + static const int default_poll_timeout_ms = -1; |
2284 | + |
2285 | + LooperThread(const android::sp<android::Looper>& looper) : looper(looper) |
2286 | + { |
2287 | + } |
2288 | + |
2289 | +private: |
2290 | + bool threadLoop() |
2291 | + { |
2292 | + if (ALOOPER_POLL_ERROR == looper->pollAll(default_poll_timeout_ms)) |
2293 | + return false; |
2294 | + return true; |
2295 | + } |
2296 | + |
2297 | + android::sp<android::Looper> looper; |
2298 | +}; |
2299 | + |
2300 | +struct State : public android::RefBase |
2301 | +{ |
2302 | + State(AndroidEventListener* listener, |
2303 | + InputStackConfiguration* configuration) |
2304 | + : looper(new android::Looper(false)), |
2305 | + looper_thread(new LooperThread(looper)), |
2306 | + event_hub(new android::EventHub()), |
2307 | + input_reader_policy(new DefaultInputReaderPolicyInterface(configuration, looper)), |
2308 | + input_listener(new ExportedInputListener(listener)), |
2309 | + input_reader(new android::InputReader( |
2310 | + event_hub, |
2311 | + input_reader_policy, |
2312 | + input_listener)), |
2313 | + input_reader_thread(new android::InputReaderThread(input_reader)) |
2314 | + { |
2315 | + } |
2316 | + |
2317 | + ~State() |
2318 | + { |
2319 | + input_reader_thread->requestExit(); |
2320 | + } |
2321 | + |
2322 | + android::sp<android::Looper> looper; |
2323 | + android::sp<LooperThread> looper_thread; |
2324 | + |
2325 | + android::sp<android::EventHubInterface> event_hub; |
2326 | + android::sp<android::InputReaderPolicyInterface> input_reader_policy; |
2327 | + android::sp<android::InputListenerInterface> input_listener; |
2328 | + android::sp<android::InputReaderInterface> input_reader; |
2329 | + android::sp<android::InputReaderThread> input_reader_thread; |
2330 | + |
2331 | + android::Condition wait_condition; |
2332 | + android::Mutex wait_guard; |
2333 | +}; |
2334 | + |
2335 | +android::sp<State> global_state; |
2336 | + |
2337 | +} |
2338 | + |
2339 | +void android_input_stack_initialize(AndroidEventListener* listener, InputStackConfiguration* config) |
2340 | +{ |
2341 | + global_state = new State(listener, config); |
2342 | +} |
2343 | + |
2344 | +void android_input_stack_loop_once() |
2345 | +{ |
2346 | + global_state->input_reader->loopOnce(); |
2347 | +} |
2348 | + |
2349 | +void android_input_stack_start() |
2350 | +{ |
2351 | + global_state->input_reader_thread->run(); |
2352 | + global_state->looper_thread->run(); |
2353 | +} |
2354 | + |
2355 | +void android_input_stack_start_waiting_for_flag(bool* flag) |
2356 | +{ |
2357 | + global_state->input_reader_thread->run(); |
2358 | + global_state->looper_thread->run(); |
2359 | + |
2360 | + while (!*flag) { |
2361 | + global_state->wait_condition.waitRelative( |
2362 | + global_state->wait_guard, |
2363 | + 10 * 1000 * 1000); |
2364 | + } |
2365 | +} |
2366 | + |
2367 | +void android_input_stack_stop() |
2368 | +{ |
2369 | + global_state->input_reader_thread->requestExit(); |
2370 | +} |
2371 | + |
2372 | +void android_input_stack_shutdown() |
2373 | +{ |
2374 | + global_state = NULL; |
2375 | +} |
2376 | |
2377 | === added directory 'android/compat/media' |
2378 | === added file 'android/compat/media/Android.mk' |
2379 | --- android/compat/media/Android.mk 1970-01-01 00:00:00 +0000 |
2380 | +++ android/compat/media/Android.mk 2016-01-11 14:31:46 +0000 |
2381 | @@ -0,0 +1,187 @@ |
2382 | +LOCAL_PATH:= $(call my-dir) |
2383 | +include $(CLEAR_VARS) |
2384 | +include $(LOCAL_PATH)/../Android.common.mk |
2385 | + |
2386 | +LOCAL_SRC_FILES := \ |
2387 | + camera_service.cpp |
2388 | + |
2389 | +LOCAL_SHARED_LIBRARIES := \ |
2390 | + libcameraservice \ |
2391 | + libmedialogservice \ |
2392 | + libcutils \ |
2393 | + libmedia \ |
2394 | + libmedia_compat_layer \ |
2395 | + libmediaplayerservice \ |
2396 | + libutils \ |
2397 | + liblog \ |
2398 | + libbinder |
2399 | + |
2400 | +LOCAL_C_INCLUDES := \ |
2401 | + frameworks/av/media/libmediaplayerservice \ |
2402 | + frameworks/av/services/medialog \ |
2403 | + frameworks/av/services/camera/libcameraservice |
2404 | + |
2405 | +IS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -eq 5 && echo true) |
2406 | +ifeq ($(IS_ANDROID_5),true) |
2407 | +LOCAL_C_INCLUDES += system/media/camera/include |
2408 | +endif |
2409 | + |
2410 | +LOCAL_MODULE := camera_service |
2411 | + |
2412 | +LOCAL_32_BIT_ONLY := true |
2413 | + |
2414 | +include $(BUILD_EXECUTABLE) |
2415 | + |
2416 | +# ------------------------------------------------- |
2417 | + |
2418 | +include $(CLEAR_VARS) |
2419 | +include $(LOCAL_PATH)/../Android.common.mk |
2420 | + |
2421 | +HYBRIS_PATH := $(LOCAL_PATH)/../../hybris |
2422 | + |
2423 | +LOCAL_CFLAGS += -std=gnu++0x |
2424 | + |
2425 | +ifeq ($(BOARD_HAS_MEDIA_PLAYER_PAUSE),true) |
2426 | +LOCAL_CFLAGS += -DBOARD_HAS_MEDIA_PLAYER_PAUSE |
2427 | +endif |
2428 | + |
2429 | +LOCAL_SRC_FILES:= \ |
2430 | + media_compatibility_layer.cpp \ |
2431 | + media_codec_layer.cpp \ |
2432 | + media_codec_list.cpp \ |
2433 | + media_format_layer.cpp \ |
2434 | + surface_texture_client_hybris.cpp \ |
2435 | + decoding_service.cpp \ |
2436 | + media_recorder_layer.cpp \ |
2437 | + media_recorder.cpp \ |
2438 | + media_recorder_client.cpp \ |
2439 | + media_recorder_factory.cpp \ |
2440 | + media_recorder_observer.cpp |
2441 | + |
2442 | +LOCAL_MODULE:= libmedia_compat_layer |
2443 | +LOCAL_MODULE_TAGS := optional |
2444 | + |
2445 | +LOCAL_SHARED_LIBRARIES := \ |
2446 | + libcutils \ |
2447 | + libcamera_client \ |
2448 | + libutils \ |
2449 | + libbinder \ |
2450 | + libhardware \ |
2451 | + libui \ |
2452 | + libgui \ |
2453 | + libstagefright \ |
2454 | + libstagefright_foundation \ |
2455 | + libEGL \ |
2456 | + libGLESv2 \ |
2457 | + libmedia \ |
2458 | + libaudioutils \ |
2459 | + libmediaplayerservice |
2460 | + |
2461 | +LOCAL_C_INCLUDES := \ |
2462 | + $(HYBRIS_PATH)/include \ |
2463 | + frameworks/base/media/libstagefright/include \ |
2464 | + frameworks/base/include/media/stagefright \ |
2465 | + frameworks/base/include/media \ |
2466 | + frameworks/av/media \ |
2467 | + frameworks/av/media/libstagefright/include \ |
2468 | + frameworks/av/include \ |
2469 | + frameworks/native/include \ |
2470 | + system/media/audio_utils/include \ |
2471 | + frameworks/av/services/camera/libcameraservice |
2472 | + |
2473 | +IS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -eq 5 && echo true) |
2474 | +ifeq ($(IS_ANDROID_5),true) |
2475 | +LOCAL_C_INCLUDES += frameworks/native/include/media/openmax |
2476 | +endif |
2477 | + |
2478 | +ifeq ($(strip $(MTK_CAMERA_BSP_SUPPORT)),yes) |
2479 | +LOCAL_C_INCLUDES += $(TOP)/mediatek/kernel/include/linux/vcodec |
2480 | +LOCAL_SHARED_LIBRARIES += \ |
2481 | + libvcodecdrv |
2482 | + |
2483 | +LOCAL_C_INCLUDES+= \ |
2484 | + $(TOP)/$(MTK_PATH_SOURCE)/frameworks-ext/av/media/libmediaplayerservice \ |
2485 | + $(TOP)/$(MTK_PATH_SOURCE)/frameworks-ext/av/include \ |
2486 | + $(TOP)/$(MTK_PATH_SOURCE)/frameworks-ext/av/media/libstagefright/include \ |
2487 | + $(TOP)/$(MTK_PATH_PLATFORM)/frameworks/libmtkplayer \ |
2488 | + $(TOP)/$(MTK_PATH_SOURCE)/frameworks/av/include |
2489 | +endif |
2490 | + |
2491 | +LOCAL_32_BIT_ONLY := true |
2492 | + |
2493 | +include $(BUILD_SHARED_LIBRARY) |
2494 | + |
2495 | +# ------------------------------------------------- |
2496 | + |
2497 | +include $(CLEAR_VARS) |
2498 | +include $(LOCAL_PATH)/../Android.common.mk |
2499 | + |
2500 | +LOCAL_SRC_FILES:= \ |
2501 | + direct_media_test.cpp |
2502 | + |
2503 | +LOCAL_MODULE:= direct_media_test |
2504 | +LOCAL_MODULE_TAGS := optional |
2505 | + |
2506 | +LOCAL_C_INCLUDES := \ |
2507 | + $(HYBRIS_PATH)/include \ |
2508 | + bionic \ |
2509 | + bionic/libstdc++/include \ |
2510 | + external/gtest/include \ |
2511 | + external/stlport/stlport \ |
2512 | + external/skia/include/core \ |
2513 | + frameworks/base/include |
2514 | + |
2515 | +LOCAL_SHARED_LIBRARIES := \ |
2516 | + libis_compat_layer \ |
2517 | + libsf_compat_layer \ |
2518 | + libmedia_compat_layer \ |
2519 | + libcutils \ |
2520 | + libutils \ |
2521 | + libbinder \ |
2522 | + libhardware \ |
2523 | + libui \ |
2524 | + libgui \ |
2525 | + libEGL \ |
2526 | + libGLESv2 |
2527 | + |
2528 | +LOCAL_32_BIT_ONLY := true |
2529 | + |
2530 | +include $(BUILD_EXECUTABLE) |
2531 | + |
2532 | +include $(CLEAR_VARS) |
2533 | +include $(LOCAL_PATH)/../Android.common.mk |
2534 | + |
2535 | +LOCAL_CFLAGS += -Wno-multichar -D SIMPLE_PLAYER -std=gnu++0x |
2536 | + |
2537 | +LOCAL_SRC_FILES:= \ |
2538 | + media_codec_layer.cpp \ |
2539 | + media_codec_list.cpp \ |
2540 | + media_format_layer.cpp \ |
2541 | + codec.cpp \ |
2542 | + SimplePlayer.cpp |
2543 | + |
2544 | +LOCAL_SHARED_LIBRARIES := \ |
2545 | + libstagefright \ |
2546 | + libstagefright_foundation \ |
2547 | + liblog \ |
2548 | + libutils \ |
2549 | + libbinder \ |
2550 | + libmedia \ |
2551 | + libgui \ |
2552 | + libcutils \ |
2553 | + libui |
2554 | + |
2555 | +LOCAL_C_INCLUDES:= \ |
2556 | + $(HYBRIS_PATH)/include \ |
2557 | + frameworks/av/media/libstagefright \ |
2558 | + frameworks/native/include/media/openmax \ |
2559 | + frameworks/base/media/libstagefright/include \ |
2560 | + frameworks/base/include/media/stagefright \ |
2561 | + frameworks/base/include/media |
2562 | + |
2563 | +LOCAL_MODULE:= codec |
2564 | +LOCAL_MODULE_TAGS := optional |
2565 | + |
2566 | +LOCAL_32_BIT_ONLY := true |
2567 | + |
2568 | +include $(BUILD_EXECUTABLE) |
2569 | |
2570 | === added file 'android/compat/media/SimplePlayer.cpp' |
2571 | --- android/compat/media/SimplePlayer.cpp 1970-01-01 00:00:00 +0000 |
2572 | +++ android/compat/media/SimplePlayer.cpp 2016-01-11 14:31:46 +0000 |
2573 | @@ -0,0 +1,777 @@ |
2574 | +/* |
2575 | + * Copyright (C) 2012 The Android Open Source Project |
2576 | + * |
2577 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
2578 | + * you may not use this file except in compliance with the License. |
2579 | + * You may obtain a copy of the License at |
2580 | + * |
2581 | + * http://www.apache.org/licenses/LICENSE-2.0 |
2582 | + * |
2583 | + * Unless required by applicable law or agreed to in writing, software |
2584 | + * distributed under the License is distributed on an "AS IS" BASIS, |
2585 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2586 | + * See the License for the specific language governing permissions and |
2587 | + * limitations under the License. |
2588 | + */ |
2589 | + |
2590 | +//#define LOG_NDEBUG 0 |
2591 | +#define LOG_TAG "SimplePlayer" |
2592 | +#include <utils/Log.h> |
2593 | + |
2594 | +#include "SimplePlayer.h" |
2595 | + |
2596 | +#include <gui/Surface.h> |
2597 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
2598 | +#include <gui/SurfaceTextureClient.h> |
2599 | +#endif |
2600 | +#include <media/AudioTrack.h> |
2601 | +#include <media/ICrypto.h> |
2602 | +#include <media/stagefright/foundation/ABuffer.h> |
2603 | +#include <media/stagefright/foundation/ADebug.h> |
2604 | +#include <media/stagefright/foundation/AMessage.h> |
2605 | +#include <media/stagefright/MediaCodec.h> |
2606 | +#include <media/stagefright/MediaErrors.h> |
2607 | +#include <media/stagefright/NativeWindowWrapper.h> |
2608 | +#include <media/stagefright/NuMediaExtractor.h> |
2609 | + |
2610 | +#define USE_MEDIA_CODEC_LAYER |
2611 | + |
2612 | +namespace android { |
2613 | + |
2614 | +SimplePlayer::SimplePlayer() |
2615 | + : mState(UNINITIALIZED), |
2616 | + mDoMoreStuffGeneration(0), |
2617 | + mStartTimeRealUs(-1ll) { |
2618 | +} |
2619 | + |
2620 | +SimplePlayer::~SimplePlayer() { |
2621 | +} |
2622 | + |
2623 | +// static |
2624 | +status_t PostAndAwaitResponse( |
2625 | + const sp<AMessage> &msg, sp<AMessage> *response) { |
2626 | + status_t err = msg->postAndAwaitResponse(response); |
2627 | + printf("%s\n", __PRETTY_FUNCTION__); |
2628 | + |
2629 | + if (err != OK) { |
2630 | + return err; |
2631 | + } |
2632 | + |
2633 | + if (!(*response)->findInt32("err", &err)) { |
2634 | + err = OK; |
2635 | + } |
2636 | + |
2637 | + return err; |
2638 | +} |
2639 | +status_t SimplePlayer::setDataSource(const char *path) { |
2640 | + sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); |
2641 | + msg->setString("path", path); |
2642 | + sp<AMessage> response; |
2643 | + return PostAndAwaitResponse(msg, &response); |
2644 | +} |
2645 | + |
2646 | +status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) { |
2647 | + sp<AMessage> msg = new AMessage(kWhatSetSurface, id()); |
2648 | + |
2649 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
2650 | + sp<SurfaceTextureClient> surfaceTextureClient; |
2651 | + if (surfaceTexture != NULL) { |
2652 | + surfaceTextureClient = new SurfaceTextureClient(surfaceTexture); |
2653 | + } |
2654 | +#else |
2655 | + sp<Surface> surfaceTextureClient; |
2656 | + if (surfaceTexture != NULL) { |
2657 | + surfaceTextureClient = new Surface(surfaceTexture); |
2658 | + } |
2659 | +#endif |
2660 | + |
2661 | + msg->setObject( |
2662 | + "native-window", new NativeWindowWrapper(surfaceTextureClient)); |
2663 | + |
2664 | + sp<AMessage> response; |
2665 | + return PostAndAwaitResponse(msg, &response); |
2666 | +} |
2667 | + |
2668 | +status_t SimplePlayer::prepare() { |
2669 | + sp<AMessage> msg = new AMessage(kWhatPrepare, id()); |
2670 | + sp<AMessage> response; |
2671 | + return PostAndAwaitResponse(msg, &response); |
2672 | +} |
2673 | + |
2674 | +status_t SimplePlayer::start() { |
2675 | + printf("%s\n", __PRETTY_FUNCTION__); |
2676 | + sp<AMessage> msg = new AMessage(kWhatStart, id()); |
2677 | + sp<AMessage> response; |
2678 | + return PostAndAwaitResponse(msg, &response); |
2679 | +} |
2680 | + |
2681 | +status_t SimplePlayer::stop() { |
2682 | + sp<AMessage> msg = new AMessage(kWhatStop, id()); |
2683 | + sp<AMessage> response; |
2684 | + return PostAndAwaitResponse(msg, &response); |
2685 | +} |
2686 | + |
2687 | +status_t SimplePlayer::reset() { |
2688 | + sp<AMessage> msg = new AMessage(kWhatReset, id()); |
2689 | + sp<AMessage> response; |
2690 | + return PostAndAwaitResponse(msg, &response); |
2691 | +} |
2692 | + |
2693 | +void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) { |
2694 | + switch (msg->what()) { |
2695 | + case kWhatSetDataSource: |
2696 | + { |
2697 | + status_t err; |
2698 | + if (mState != UNINITIALIZED) { |
2699 | + err = INVALID_OPERATION; |
2700 | + } else { |
2701 | + CHECK(msg->findString("path", &mPath)); |
2702 | + mState = UNPREPARED; |
2703 | + } |
2704 | + |
2705 | + uint32_t replyID; |
2706 | + CHECK(msg->senderAwaitsResponse(&replyID)); |
2707 | + |
2708 | + sp<AMessage> response = new AMessage; |
2709 | + response->setInt32("err", err); |
2710 | + response->postReply(replyID); |
2711 | + break; |
2712 | + } |
2713 | + |
2714 | + case kWhatSetSurface: |
2715 | + { |
2716 | + status_t err; |
2717 | + if (mState != UNPREPARED) { |
2718 | + err = INVALID_OPERATION; |
2719 | + } else { |
2720 | + sp<RefBase> obj; |
2721 | + CHECK(msg->findObject("native-window", &obj)); |
2722 | + |
2723 | + mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); |
2724 | + |
2725 | + err = OK; |
2726 | + } |
2727 | + |
2728 | + uint32_t replyID; |
2729 | + CHECK(msg->senderAwaitsResponse(&replyID)); |
2730 | + |
2731 | + sp<AMessage> response = new AMessage; |
2732 | + response->setInt32("err", err); |
2733 | + response->postReply(replyID); |
2734 | + break; |
2735 | + } |
2736 | + |
2737 | + case kWhatPrepare: |
2738 | + { |
2739 | + status_t err; |
2740 | + if (mState != UNPREPARED) { |
2741 | + err = INVALID_OPERATION; |
2742 | + } else { |
2743 | + err = onPrepare(); |
2744 | + |
2745 | + if (err == OK) { |
2746 | + mState = STOPPED; |
2747 | + } |
2748 | + } |
2749 | + |
2750 | + uint32_t replyID; |
2751 | + CHECK(msg->senderAwaitsResponse(&replyID)); |
2752 | + |
2753 | + sp<AMessage> response = new AMessage; |
2754 | + response->setInt32("err", err); |
2755 | + response->postReply(replyID); |
2756 | + break; |
2757 | + } |
2758 | + |
2759 | + case kWhatStart: |
2760 | + { |
2761 | + status_t err = OK; |
2762 | + |
2763 | + if (mState == UNPREPARED) { |
2764 | + err = onPrepare(); |
2765 | + |
2766 | + if (err == OK) { |
2767 | + mState = STOPPED; |
2768 | + } |
2769 | + } |
2770 | + |
2771 | + if (err == OK) { |
2772 | + if (mState != STOPPED) { |
2773 | + err = INVALID_OPERATION; |
2774 | + } else { |
2775 | + err = onStart(); |
2776 | + |
2777 | + if (err == OK) { |
2778 | + mState = STARTED; |
2779 | + } |
2780 | + } |
2781 | + } |
2782 | + |
2783 | + uint32_t replyID; |
2784 | + CHECK(msg->senderAwaitsResponse(&replyID)); |
2785 | + |
2786 | + sp<AMessage> response = new AMessage; |
2787 | + response->setInt32("err", err); |
2788 | + response->postReply(replyID); |
2789 | + break; |
2790 | + } |
2791 | + |
2792 | + case kWhatStop: |
2793 | + { |
2794 | + status_t err; |
2795 | + |
2796 | + if (mState != STARTED) { |
2797 | + err = INVALID_OPERATION; |
2798 | + } else { |
2799 | + err = onStop(); |
2800 | + |
2801 | + if (err == OK) { |
2802 | + mState = STOPPED; |
2803 | + } |
2804 | + } |
2805 | + |
2806 | + uint32_t replyID; |
2807 | + CHECK(msg->senderAwaitsResponse(&replyID)); |
2808 | + |
2809 | + sp<AMessage> response = new AMessage; |
2810 | + response->setInt32("err", err); |
2811 | + response->postReply(replyID); |
2812 | + break; |
2813 | + } |
2814 | + |
2815 | + case kWhatReset: |
2816 | + { |
2817 | + status_t err = OK; |
2818 | + |
2819 | + if (mState == STARTED) { |
2820 | + CHECK_EQ(onStop(), (status_t)OK); |
2821 | + mState = STOPPED; |
2822 | + } |
2823 | + |
2824 | + if (mState == STOPPED) { |
2825 | + err = onReset(); |
2826 | + mState = UNINITIALIZED; |
2827 | + } |
2828 | + |
2829 | + uint32_t replyID; |
2830 | + CHECK(msg->senderAwaitsResponse(&replyID)); |
2831 | + |
2832 | + sp<AMessage> response = new AMessage; |
2833 | + response->setInt32("err", err); |
2834 | + response->postReply(replyID); |
2835 | + break; |
2836 | + } |
2837 | + |
2838 | + case kWhatDoMoreStuff: |
2839 | + { |
2840 | + int32_t generation; |
2841 | + CHECK(msg->findInt32("generation", &generation)); |
2842 | + |
2843 | + if (generation != mDoMoreStuffGeneration) { |
2844 | + break; |
2845 | + } |
2846 | + |
2847 | + status_t err = onDoMoreStuff(); |
2848 | + |
2849 | + if (err == OK) { |
2850 | + msg->post(10000ll); |
2851 | + } |
2852 | + break; |
2853 | + } |
2854 | + |
2855 | + default: |
2856 | + TRESPASS(); |
2857 | + } |
2858 | +} |
2859 | + |
2860 | +status_t SimplePlayer::onPrepare() { |
2861 | + CHECK_EQ(mState, UNPREPARED); |
2862 | + printf("%s\n", __PRETTY_FUNCTION__); |
2863 | + |
2864 | + mExtractor = new NuMediaExtractor; |
2865 | + |
2866 | + status_t err = mExtractor->setDataSource(mPath.c_str()); |
2867 | + |
2868 | + if (err != OK) { |
2869 | + mExtractor.clear(); |
2870 | + return err; |
2871 | + } |
2872 | + |
2873 | + if (mCodecLooper == NULL) { |
2874 | + mCodecLooper = new ALooper; |
2875 | + mCodecLooper->start(); |
2876 | + } |
2877 | + |
2878 | + bool haveAudio = false; |
2879 | + bool haveVideo = false; |
2880 | + for (size_t i = 0; i < mExtractor->countTracks(); ++i) { |
2881 | + sp<AMessage> format; |
2882 | + status_t err = mExtractor->getTrackFormat(i, &format); |
2883 | + CHECK_EQ(err, (status_t)OK); |
2884 | + |
2885 | + AString mime; |
2886 | + int32_t width = 0, height = 0, maxInputSize = 0; |
2887 | + int64_t durationUs = 0; |
2888 | + sp<ABuffer> csd0, csd1; |
2889 | +#ifdef USE_MEDIA_CODEC_LAYER |
2890 | + MediaFormat mformat; |
2891 | +#endif |
2892 | + CHECK(format->findString("mime", &mime)); |
2893 | + |
2894 | + if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) { |
2895 | + //haveAudio = true; |
2896 | + printf("*** Have audio but skipping it!\n"); |
2897 | + continue; |
2898 | + } else if (!haveVideo && !strncasecmp(mime.c_str(), "video/", 6)) { |
2899 | + haveVideo = true; |
2900 | + CHECK(format->findInt32("width", &width)); |
2901 | + CHECK(format->findInt32("height", &height)); |
2902 | + CHECK(format->findInt64("durationUs", &durationUs)); |
2903 | + CHECK(format->findInt32("max-input-size", &maxInputSize)); |
2904 | + CHECK(format->findBuffer("csd-0", &csd0)); |
2905 | + CHECK(format->findBuffer("csd-1", &csd1)); |
2906 | +#ifdef USE_MEDIA_CODEC_LAYER |
2907 | + mformat = media_format_create_video_format(mime.c_str(), width, height, durationUs, maxInputSize); |
2908 | + media_format_set_byte_buffer(mformat, "csd-0", csd0->data(), csd0->size()); |
2909 | + media_format_set_byte_buffer(mformat, "csd-1", csd1->data(), csd1->size()); |
2910 | +#endif |
2911 | + } else { |
2912 | + continue; |
2913 | + } |
2914 | + |
2915 | + err = mExtractor->selectTrack(i); |
2916 | + CHECK_EQ(err, (status_t)OK); |
2917 | + |
2918 | + CodecState *state = |
2919 | + &mStateByTrackIndex.editValueAt( |
2920 | + mStateByTrackIndex.add(i, CodecState())); |
2921 | + |
2922 | + state->mNumFramesWritten = 0; |
2923 | +#ifdef USE_MEDIA_CODEC_LAYER |
2924 | + state->mCodecDelegate = media_codec_create_by_codec_type(mime.c_str()); |
2925 | + state->mCodec = media_codec_get(state->mCodecDelegate); |
2926 | + CHECK(state->mCodecDelegate != NULL); |
2927 | +#else |
2928 | + state->mCodec = MediaCodec::CreateByType( |
2929 | + mCodecLooper, mime.c_str(), false /* encoder */); |
2930 | +#endif |
2931 | + |
2932 | + CHECK(state->mCodec != NULL); |
2933 | + |
2934 | +#ifdef USE_MEDIA_CODEC_LAYER |
2935 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
2936 | + err = media_codec_configure(state->mCodecDelegate, mformat, mNativeWindow->getSurfaceTextureClient().get(), 0); |
2937 | +#else |
2938 | + err = media_codec_configure(state->mCodecDelegate, mformat, mNativeWindow->getSurface().get(), 0); |
2939 | +#endif |
2940 | +#else |
2941 | + err = state->mCodec->configure( |
2942 | + format, |
2943 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
2944 | + mNativeWindow->getSurfaceTextureClient(), |
2945 | +#else |
2946 | + mNativeWindow->getSurface(), |
2947 | +#endif |
2948 | + NULL /* crypto */, |
2949 | + 0 /* flags */); |
2950 | +#endif |
2951 | + |
2952 | + CHECK_EQ(err, (status_t)OK); |
2953 | + |
2954 | + size_t j = 0; |
2955 | + sp<ABuffer> buffer; |
2956 | + // Place the CSD data into the source buffer |
2957 | + while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) { |
2958 | + state->mCSD.push_back(buffer); |
2959 | + |
2960 | + ++j; |
2961 | + } |
2962 | + } |
2963 | + |
2964 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { |
2965 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); |
2966 | + |
2967 | +#ifdef USE_MEDIA_CODEC_LAYER |
2968 | + status_t err = media_codec_start(state->mCodecDelegate); |
2969 | +#else |
2970 | + status_t err = state->mCodec->start(); |
2971 | +#endif |
2972 | + CHECK_EQ(err, (status_t)OK); |
2973 | + |
2974 | +#ifdef USE_MEDIA_CODEC_LAYER |
2975 | + size_t nInputBuffers = media_codec_get_input_buffers_size(state->mCodecDelegate); |
2976 | + ALOGD("nInputBuffers: %u", nInputBuffers); |
2977 | + for (size_t i=0; i<nInputBuffers; i++) |
2978 | + { |
2979 | + uint8_t *data = media_codec_get_nth_input_buffer(state->mCodecDelegate, i); |
2980 | + CHECK(data != NULL); |
2981 | + size_t size = media_codec_get_nth_input_buffer_capacity(state->mCodecDelegate, i); |
2982 | + ALOGD("input buffer[%d] size: %d", i, size); |
2983 | + sp<ABuffer> buf = new ABuffer(data, size); |
2984 | + state->mBuffers[0].insertAt(new ABuffer(data, size), i); |
2985 | + } |
2986 | +#else |
2987 | + err = state->mCodec->getInputBuffers(&state->mBuffers[0]); |
2988 | + CHECK_EQ(err, (status_t)OK); |
2989 | +#endif |
2990 | + |
2991 | + err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); |
2992 | + CHECK_EQ(err, (status_t)OK); |
2993 | + |
2994 | + for (size_t j = 0; j < state->mCSD.size(); ++j) { |
2995 | + const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j); |
2996 | + |
2997 | + size_t index; |
2998 | +#ifdef USE_MEDIA_CODEC_LAYER |
2999 | + err = media_codec_dequeue_input_buffer(state->mCodecDelegate, &index, -1ll); |
3000 | +#else |
3001 | + err = state->mCodec->dequeueInputBuffer(&index, -1ll); |
3002 | +#endif |
3003 | + CHECK_EQ(err, (status_t)OK); |
3004 | + |
3005 | + const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index); |
3006 | + |
3007 | + CHECK_LE(srcBuffer->size(), dstBuffer->capacity()); |
3008 | + dstBuffer->setRange(0, srcBuffer->size()); |
3009 | + memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size()); |
3010 | + |
3011 | +#ifdef USE_MEDIA_CODEC_LAYER |
3012 | + MediaCodecBufferInfo bufInfo; |
3013 | + bufInfo.index = index; |
3014 | + bufInfo.offset = 0; |
3015 | + bufInfo.size = dstBuffer->size(); |
3016 | + bufInfo.presentation_time_us = 0ll; |
3017 | + bufInfo.flags = MediaCodec::BUFFER_FLAG_CODECCONFIG; |
3018 | + |
3019 | + err = media_codec_queue_input_buffer( |
3020 | + state->mCodecDelegate, |
3021 | + &bufInfo); |
3022 | + |
3023 | +#else |
3024 | + err = state->mCodec->queueInputBuffer( |
3025 | + index, |
3026 | + 0, |
3027 | + dstBuffer->size(), |
3028 | + 0ll, |
3029 | + MediaCodec::BUFFER_FLAG_CODECCONFIG); |
3030 | +#endif |
3031 | + CHECK_EQ(err, (status_t)OK); |
3032 | + } |
3033 | + } |
3034 | + |
3035 | + return OK; |
3036 | +} |
3037 | + |
3038 | +status_t SimplePlayer::onStart() { |
3039 | + CHECK_EQ(mState, STOPPED); |
3040 | + |
3041 | + mStartTimeRealUs = -1ll; |
3042 | + |
3043 | + sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id()); |
3044 | + msg->setInt32("generation", ++mDoMoreStuffGeneration); |
3045 | + msg->post(); |
3046 | + |
3047 | + return OK; |
3048 | +} |
3049 | + |
3050 | +status_t SimplePlayer::onStop() { |
3051 | + CHECK_EQ(mState, STARTED); |
3052 | + |
3053 | + ++mDoMoreStuffGeneration; |
3054 | + |
3055 | + return OK; |
3056 | +} |
3057 | + |
3058 | +status_t SimplePlayer::onReset() { |
3059 | + CHECK_EQ(mState, STOPPED); |
3060 | + |
3061 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { |
3062 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); |
3063 | + |
3064 | + CHECK_EQ(state->mCodec->release(), (status_t)OK); |
3065 | + } |
3066 | + |
3067 | + mStartTimeRealUs = -1ll; |
3068 | + |
3069 | + mStateByTrackIndex.clear(); |
3070 | + mCodecLooper.clear(); |
3071 | + mExtractor.clear(); |
3072 | + mNativeWindow.clear(); |
3073 | + mPath.clear(); |
3074 | + |
3075 | + return OK; |
3076 | +} |
3077 | + |
3078 | +status_t SimplePlayer::onDoMoreStuff() { |
3079 | + ALOGV("onDoMoreStuff"); |
3080 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { |
3081 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); |
3082 | + |
3083 | + status_t err; |
3084 | + do { |
3085 | + size_t index; |
3086 | +#ifdef USE_MEDIA_CODEC_LAYER |
3087 | + err = media_codec_dequeue_input_buffer(state->mCodecDelegate, &index, 0ll); |
3088 | +#else |
3089 | + err = state->mCodec->dequeueInputBuffer(&index); |
3090 | +#endif |
3091 | + |
3092 | + if (err == OK) { |
3093 | + ALOGD("dequeued input buffer on track %d", |
3094 | + mStateByTrackIndex.keyAt(i)); |
3095 | + |
3096 | + state->mAvailInputBufferIndices.push_back(index); |
3097 | + } else { |
3098 | + ALOGD("dequeueInputBuffer on track %d returned %d", |
3099 | + mStateByTrackIndex.keyAt(i), err); |
3100 | + } |
3101 | + } while (err == OK); |
3102 | + |
3103 | + do { |
3104 | +#ifdef USE_MEDIA_CODEC_LAYER |
3105 | + BufferInfo info; |
3106 | + MediaCodecBufferInfo bufInfo; |
3107 | + err = media_codec_dequeue_output_buffer( |
3108 | + state->mCodecDelegate, |
3109 | + &bufInfo, |
3110 | + 0ll); |
3111 | + |
3112 | + info.mIndex = bufInfo.index; |
3113 | + info.mOffset = bufInfo.offset; |
3114 | + info.mSize = bufInfo.size; |
3115 | + info.mPresentationTimeUs = bufInfo.presentation_time_us; |
3116 | + info.mFlags = bufInfo.flags; |
3117 | + |
3118 | +#else |
3119 | + BufferInfo info; |
3120 | + err = state->mCodec->dequeueOutputBuffer( |
3121 | + &info.mIndex, |
3122 | + &info.mOffset, |
3123 | + &info.mSize, |
3124 | + &info.mPresentationTimeUs, |
3125 | + &info.mFlags); |
3126 | +#endif |
3127 | + |
3128 | + if (err == OK) { |
3129 | + ALOGV("dequeued output buffer on track %d", |
3130 | + mStateByTrackIndex.keyAt(i)); |
3131 | + |
3132 | + state->mAvailOutputBufferInfos.push_back(info); |
3133 | + } else if (err == INFO_FORMAT_CHANGED) { |
3134 | + err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state); |
3135 | + CHECK_EQ(err, (status_t)OK); |
3136 | + } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { |
3137 | + err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); |
3138 | + CHECK_EQ(err, (status_t)OK); |
3139 | + } else { |
3140 | + ALOGV("dequeueOutputBuffer on track %d returned %d", |
3141 | + mStateByTrackIndex.keyAt(i), err); |
3142 | + } |
3143 | + } while (err == OK |
3144 | + || err == INFO_FORMAT_CHANGED |
3145 | + || err == INFO_OUTPUT_BUFFERS_CHANGED); |
3146 | + } |
3147 | + |
3148 | + for (;;) { |
3149 | + size_t trackIndex; |
3150 | + status_t err = mExtractor->getSampleTrackIndex(&trackIndex); |
3151 | + |
3152 | + if (err != OK) { |
3153 | + ALOGI("encountered input EOS."); |
3154 | + break; |
3155 | + } else { |
3156 | + CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex); |
3157 | + |
3158 | + if (state->mAvailInputBufferIndices.empty()) { |
3159 | + break; |
3160 | + } |
3161 | + |
3162 | + size_t index = *state->mAvailInputBufferIndices.begin(); |
3163 | + state->mAvailInputBufferIndices.erase( |
3164 | + state->mAvailInputBufferIndices.begin()); |
3165 | + |
3166 | + const sp<ABuffer> &dstBuffer = |
3167 | + state->mBuffers[0].itemAt(index); |
3168 | + |
3169 | + err = mExtractor->readSampleData(dstBuffer); |
3170 | + CHECK_EQ(err, (status_t)OK); |
3171 | + |
3172 | + int64_t timeUs; |
3173 | + CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK); |
3174 | + |
3175 | +#ifdef USE_MEDIA_CODEC_LAYER |
3176 | + MediaCodecBufferInfo bufInfo; |
3177 | + bufInfo.index = index; |
3178 | + bufInfo.offset = dstBuffer->offset(); |
3179 | + bufInfo.size = dstBuffer->size(); |
3180 | + bufInfo.presentation_time_us = timeUs; |
3181 | + bufInfo.flags = 0; |
3182 | + |
3183 | + err = media_codec_queue_input_buffer( |
3184 | + state->mCodecDelegate, |
3185 | + &bufInfo); |
3186 | + |
3187 | +#else |
3188 | + err = state->mCodec->queueInputBuffer( |
3189 | + index, |
3190 | + dstBuffer->offset(), |
3191 | + dstBuffer->size(), |
3192 | + timeUs, |
3193 | + 0); |
3194 | +#endif |
3195 | + CHECK_EQ(err, (status_t)OK); |
3196 | + |
3197 | + ALOGV("enqueued input data on track %d", trackIndex); |
3198 | + |
3199 | + err = mExtractor->advance(); |
3200 | + CHECK_EQ(err, (status_t)OK); |
3201 | + } |
3202 | + } |
3203 | + |
3204 | + int64_t nowUs = ALooper::GetNowUs(); |
3205 | + |
3206 | + if (mStartTimeRealUs < 0ll) { |
3207 | + mStartTimeRealUs = nowUs + 1000000ll; |
3208 | + } |
3209 | + |
3210 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { |
3211 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); |
3212 | + |
3213 | + while (!state->mAvailOutputBufferInfos.empty()) { |
3214 | + BufferInfo *info = &*state->mAvailOutputBufferInfos.begin(); |
3215 | + |
3216 | + int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs; |
3217 | + int64_t lateByUs = nowUs - whenRealUs; |
3218 | + |
3219 | + if (lateByUs > -10000ll) { |
3220 | + bool release = true; |
3221 | + |
3222 | + if (lateByUs > 30000ll) { |
3223 | + ALOGI("track %d buffer late by %lld us, dropping.", |
3224 | + mStateByTrackIndex.keyAt(i), lateByUs); |
3225 | + state->mCodec->releaseOutputBuffer(info->mIndex); |
3226 | + } else { |
3227 | + if (state->mAudioTrack != NULL) { |
3228 | + const sp<ABuffer> &srcBuffer = |
3229 | + state->mBuffers[1].itemAt(info->mIndex); |
3230 | + |
3231 | + renderAudio(state, info, srcBuffer); |
3232 | + |
3233 | + if (info->mSize > 0) { |
3234 | + release = false; |
3235 | + } |
3236 | + } |
3237 | + |
3238 | + if (release) { |
3239 | +#ifdef USE_MEDIA_CODEC_LAYER |
3240 | + ALOGD("Rendering output buffer index %d and releasing", info->mIndex); |
3241 | + state->mCodec->renderOutputBufferAndRelease( |
3242 | + info->mIndex); |
3243 | +#else |
3244 | + ALOGD("Releasing output buffer index %d", info->mIndex); |
3245 | + state->mCodec->releaseOutputBuffer(info->mIndex); |
3246 | +#endif |
3247 | + } |
3248 | + } |
3249 | + |
3250 | + if (release) { |
3251 | + state->mAvailOutputBufferInfos.erase( |
3252 | + state->mAvailOutputBufferInfos.begin()); |
3253 | + |
3254 | + info = NULL; |
3255 | + } else { |
3256 | + break; |
3257 | + } |
3258 | + } else { |
3259 | + ALOGV("track %d buffer early by %lld us.", |
3260 | + mStateByTrackIndex.keyAt(i), -lateByUs); |
3261 | + break; |
3262 | + } |
3263 | + } |
3264 | + } |
3265 | + |
3266 | + return OK; |
3267 | +} |
3268 | + |
3269 | +status_t SimplePlayer::onOutputFormatChanged( |
3270 | + size_t trackIndex, CodecState *state) { |
3271 | + sp<AMessage> format; |
3272 | + status_t err = state->mCodec->getOutputFormat(&format); |
3273 | + |
3274 | + if (err != OK) { |
3275 | + return err; |
3276 | + } |
3277 | + |
3278 | + AString mime; |
3279 | + CHECK(format->findString("mime", &mime)); |
3280 | + |
3281 | + if (!strncasecmp(mime.c_str(), "audio/", 6)) { |
3282 | + int32_t channelCount; |
3283 | + int32_t sampleRate; |
3284 | + CHECK(format->findInt32("channel-count", &channelCount)); |
3285 | + CHECK(format->findInt32("sample-rate", &sampleRate)); |
3286 | + |
3287 | + state->mAudioTrack = new AudioTrack( |
3288 | + AUDIO_STREAM_MUSIC, |
3289 | + sampleRate, |
3290 | + AUDIO_FORMAT_PCM_16_BIT, |
3291 | + audio_channel_out_mask_from_count(channelCount), |
3292 | + 0); |
3293 | + |
3294 | + state->mNumFramesWritten = 0; |
3295 | + } |
3296 | + |
3297 | + return OK; |
3298 | +} |
3299 | + |
3300 | +void SimplePlayer::renderAudio( |
3301 | + CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) { |
3302 | + CHECK(state->mAudioTrack != NULL); |
3303 | + |
3304 | + if (state->mAudioTrack->stopped()) { |
3305 | + state->mAudioTrack->start(); |
3306 | + } |
3307 | + |
3308 | + uint32_t numFramesPlayed; |
3309 | + CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK); |
3310 | + |
3311 | + uint32_t numFramesAvailableToWrite = |
3312 | + state->mAudioTrack->frameCount() |
3313 | + - (state->mNumFramesWritten - numFramesPlayed); |
3314 | + |
3315 | + size_t numBytesAvailableToWrite = |
3316 | + numFramesAvailableToWrite * state->mAudioTrack->frameSize(); |
3317 | + |
3318 | + size_t copy = info->mSize; |
3319 | + if (copy > numBytesAvailableToWrite) { |
3320 | + copy = numBytesAvailableToWrite; |
3321 | + } |
3322 | + |
3323 | + if (copy == 0) { |
3324 | + return; |
3325 | + } |
3326 | + |
3327 | + int64_t startTimeUs = ALooper::GetNowUs(); |
3328 | + |
3329 | + ssize_t nbytes = state->mAudioTrack->write( |
3330 | + buffer->base() + info->mOffset, copy); |
3331 | + |
3332 | + CHECK_EQ(nbytes, (ssize_t)copy); |
3333 | + |
3334 | + int64_t delayUs = ALooper::GetNowUs() - startTimeUs; |
3335 | + |
3336 | + uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize(); |
3337 | + |
3338 | + if (delayUs > 2000ll) { |
3339 | + ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, " |
3340 | + "numFramesWritten=%u", |
3341 | + delayUs, numFramesAvailableToWrite, numFramesWritten); |
3342 | + } |
3343 | + |
3344 | + info->mOffset += nbytes; |
3345 | + info->mSize -= nbytes; |
3346 | + |
3347 | + state->mNumFramesWritten += numFramesWritten; |
3348 | +} |
3349 | + |
3350 | +} // namespace android |
3351 | |
3352 | === added file 'android/compat/media/SimplePlayer.h' |
3353 | --- android/compat/media/SimplePlayer.h 1970-01-01 00:00:00 +0000 |
3354 | +++ android/compat/media/SimplePlayer.h 2016-01-11 14:31:46 +0000 |
3355 | @@ -0,0 +1,120 @@ |
3356 | +/* |
3357 | + * Copyright (C) 2012 The Android Open Source Project |
3358 | + * |
3359 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
3360 | + * you may not use this file except in compliance with the License. |
3361 | + * You may obtain a copy of the License at |
3362 | + * |
3363 | + * http://www.apache.org/licenses/LICENSE-2.0 |
3364 | + * |
3365 | + * Unless required by applicable law or agreed to in writing, software |
3366 | + * distributed under the License is distributed on an "AS IS" BASIS, |
3367 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3368 | + * See the License for the specific language governing permissions and |
3369 | + * limitations under the License. |
3370 | + */ |
3371 | + |
3372 | +#include <media/stagefright/foundation/AHandler.h> |
3373 | +#include <media/stagefright/foundation/AString.h> |
3374 | +#include <utils/KeyedVector.h> |
3375 | + |
3376 | +#include <hybris/media/media_codec_layer.h> |
3377 | + |
3378 | +namespace android { |
3379 | + |
3380 | +struct ABuffer; |
3381 | +struct ALooper; |
3382 | +struct AudioTrack; |
3383 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
3384 | +struct ISurfaceTexture; |
3385 | +#else |
3386 | +struct IGraphicBufferProducer; |
3387 | +#endif |
3388 | +struct MediaCodec; |
3389 | +struct NativeWindowWrapper; |
3390 | +struct NuMediaExtractor; |
3391 | + |
3392 | +struct SimplePlayer : public AHandler { |
3393 | + SimplePlayer(); |
3394 | + |
3395 | + status_t setDataSource(const char *path); |
3396 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 |
3397 | + status_t setSurface(const sp<ISurfaceTexture> &surfaceTexture); |
3398 | +#else |
3399 | + status_t setSurface(const sp<IGraphicBufferProducer> &surfaceTexture); |
3400 | +#endif |
3401 | + status_t prepare(); |
3402 | + status_t start(); |
3403 | + status_t stop(); |
3404 | + status_t reset(); |
3405 | + |
3406 | +protected: |
3407 | + virtual ~SimplePlayer(); |
3408 | + |
3409 | + virtual void onMessageReceived(const sp<AMessage> &msg); |
3410 | + |
3411 | +private: |
3412 | + enum State { |
3413 | + UNINITIALIZED, |
3414 | + UNPREPARED, |
3415 | + STOPPED, |
3416 | + STARTED |
3417 | + }; |
3418 | + |
3419 | + enum { |
3420 | + kWhatSetDataSource, |
3421 | + kWhatSetSurface, |
3422 | + kWhatPrepare, |
3423 | + kWhatStart, |
3424 | + kWhatStop, |
3425 | + kWhatReset, |
3426 | + kWhatDoMoreStuff, |
3427 | + }; |
3428 | + |
3429 | + struct BufferInfo { |
3430 | + size_t mIndex; |
3431 | + size_t mOffset; |
3432 | + size_t mSize; |
3433 | + int64_t mPresentationTimeUs; |
3434 | + uint32_t mFlags; |
3435 | + }; |
3436 | + |
3437 | + struct CodecState |
3438 | + { |
3439 | + sp<MediaCodec> mCodec; |
3440 | + MediaCodecDelegate mCodecDelegate; |
3441 | + Vector<sp<ABuffer> > mCSD; |
3442 | + Vector<sp<ABuffer> > mBuffers[2]; |
3443 | + |
3444 | + List<size_t> mAvailInputBufferIndices; |
3445 | + List<BufferInfo> mAvailOutputBufferInfos; |
3446 | + |
3447 | + sp<AudioTrack> mAudioTrack; |
3448 | + uint32_t mNumFramesWritten; |
3449 | + }; |
3450 | + |
3451 | + State mState; |
3452 | + AString mPath; |
3453 | + sp<NativeWindowWrapper> mNativeWindow; |
3454 | + |
3455 | + sp<NuMediaExtractor> mExtractor; |
3456 | + sp<ALooper> mCodecLooper; |
3457 | + KeyedVector<size_t, CodecState> mStateByTrackIndex; |
3458 | + int32_t mDoMoreStuffGeneration; |
3459 | + |
3460 | + int64_t mStartTimeRealUs; |
3461 | + |
3462 | + status_t onPrepare(); |
3463 | + status_t onStart(); |
3464 | + status_t onStop(); |
3465 | + status_t onReset(); |
3466 | + status_t onDoMoreStuff(); |
3467 | + status_t onOutputFormatChanged(size_t trackIndex, CodecState *state); |
3468 | + |
3469 | + void renderAudio( |
3470 | + CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer); |
3471 | + |
3472 | + DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer); |
3473 | +}; |
3474 | + |
3475 | +} // namespace android |
3476 | |
3477 | === added file 'android/compat/media/camera_service.cpp' |
3478 | --- android/compat/media/camera_service.cpp 1970-01-01 00:00:00 +0000 |
3479 | +++ android/compat/media/camera_service.cpp 2016-01-11 14:31:46 +0000 |
3480 | @@ -0,0 +1,52 @@ |
3481 | +/* |
3482 | + * Copyright (C) 2014 Canonical Ltd |
3483 | + * |
3484 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
3485 | + * you may not use this file except in compliance with the License. |
3486 | + * You may obtain a copy of the License at |
3487 | + * |
3488 | + * http://www.apache.org/licenses/LICENSE-2.0 |
3489 | + * |
3490 | + * Unless required by applicable law or agreed to in writing, software |
3491 | + * distributed under the License is distributed on an "AS IS" BASIS, |
3492 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3493 | + * See the License for the specific language governing permissions and |
3494 | + * limitations under the License. |
3495 | + * |
3496 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> |
3497 | + */ |
3498 | + |
3499 | +#define LOG_NDEBUG 0 |
3500 | +#undef LOG_TAG |
3501 | +#define LOG_TAG "CameraServiceCompatLayer" |
3502 | + |
3503 | +#include "media_recorder_factory.h" |
3504 | +#include "media_recorder.h" |
3505 | + |
3506 | +#include <media/camera_record_service.h> |
3507 | +#include <CameraService.h> |
3508 | + |
3509 | +#include <signal.h> |
3510 | + |
3511 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) |
3512 | + |
3513 | +using namespace android; |
3514 | + |
3515 | +/*! |
3516 | + * \brief main() instantiates the MediaRecorderFactory Binder server and the CameraService |
3517 | + */ |
3518 | +int main(int argc, char** argv) |
3519 | +{ |
3520 | + signal(SIGPIPE, SIG_IGN); |
3521 | + |
3522 | + ALOGV("Starting camera services (MediaRecorderFactory, CameraRecordService & CameraService)"); |
3523 | + |
3524 | + // Instantiate the in-process MediaRecorderFactory which is responsible |
3525 | + // for creating a new IMediaRecorder (MediaRecorder) instance over Binder |
3526 | + MediaRecorderFactory::instantiate(); |
3527 | + // Enable audio recording for camera recording |
3528 | + CameraRecordService::instantiate(); |
3529 | + CameraService::instantiate(); |
3530 | + ProcessState::self()->startThreadPool(); |
3531 | + IPCThreadState::self()->joinThreadPool(); |
3532 | +} |
3533 | |
3534 | === added file 'android/compat/media/codec.cpp' |
3535 | --- android/compat/media/codec.cpp 1970-01-01 00:00:00 +0000 |
3536 | +++ android/compat/media/codec.cpp 2016-01-11 14:31:46 +0000 |
3537 | @@ -0,0 +1,433 @@ |
3538 | +/* |
3539 | + * Copyright (C) 2012 The Android Open Source Project |
3540 | + * |
3541 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
3542 | + * you may not use this file except in compliance with the License. |
3543 | + * You may obtain a copy of the License at |
3544 | + * |
3545 | + * http://www.apache.org/licenses/LICENSE-2.0 |
3546 | + * |
3547 | + * Unless required by applicable law or agreed to in writing, software |
3548 | + * distributed under the License is distributed on an "AS IS" BASIS, |
3549 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3550 | + * See the License for the specific language governing permissions and |
3551 | + * limitations under the License. |
3552 | + */ |
3553 | + |
3554 | +#define LOG_NDEBUG 0 |
3555 | +#define LOG_TAG "codec" |
3556 | +#include <utils/Log.h> |
3557 | + |
3558 | +#include "SimplePlayer.h" |
3559 | + |
3560 | +#include <binder/IServiceManager.h> |
3561 | +#include <binder/ProcessState.h> |
3562 | +#include <media/ICrypto.h> |
3563 | +#include <media/IMediaPlayerService.h> |
3564 | +#include <media/stagefright/foundation/ABuffer.h> |
3565 | +#include <media/stagefright/foundation/ADebug.h> |
3566 | +#include <media/stagefright/foundation/ALooper.h> |
3567 | +#include <media/stagefright/foundation/AMessage.h> |
3568 | +#include <media/stagefright/foundation/AString.h> |
3569 | +#include <media/stagefright/DataSource.h> |
3570 | +#include <media/stagefright/MediaCodec.h> |
3571 | +#include <media/stagefright/MediaCodecList.h> |
3572 | +#include <media/stagefright/MediaDefs.h> |
3573 | +#include <media/stagefright/NuMediaExtractor.h> |
3574 | +#include <gui/ISurfaceComposer.h> |
3575 | +#include <gui/SurfaceComposerClient.h> |
3576 | +#include <ui/DisplayInfo.h> |
3577 | + |
3578 | +static void usage(const char *me) { |
3579 | + fprintf(stderr, "usage: %s [-a] use audio\n" |
3580 | + "\t\t[-v] use video\n" |
3581 | + "\t\t[-p] playback\n" |
3582 | + "\t\t[-S] allocate buffers from a surface\n", |
3583 | + me); |
3584 | + |
3585 | + exit(1); |
3586 | +} |
3587 | + |
3588 | +namespace android { |
3589 | + |
3590 | +struct CodecState { |
3591 | + sp<MediaCodec> mCodec; |
3592 | + Vector<sp<ABuffer> > mInBuffers; |
3593 | + Vector<sp<ABuffer> > mOutBuffers; |
3594 | + bool mSignalledInputEOS; |
3595 | + bool mSawOutputEOS; |
3596 | + int64_t mNumBuffersDecoded; |
3597 | + int64_t mNumBytesDecoded; |
3598 | + bool mIsAudio; |
3599 | +}; |
3600 | + |
3601 | +} // namespace android |
3602 | + |
3603 | +static int decode( |
3604 | + const android::sp<android::ALooper> &looper, |
3605 | + const char *path, |
3606 | + bool useAudio, |
3607 | + bool useVideo, |
3608 | + const android::sp<android::Surface> &surface) { |
3609 | + using namespace android; |
3610 | + |
3611 | + static int64_t kTimeout = 500ll; |
3612 | + |
3613 | + sp<NuMediaExtractor> extractor = new NuMediaExtractor; |
3614 | + if (extractor->setDataSource(path) != OK) { |
3615 | + fprintf(stderr, "unable to instantiate extractor.\n"); |
3616 | + return 1; |
3617 | + } |
3618 | + |
3619 | + KeyedVector<size_t, CodecState> stateByTrack; |
3620 | + |
3621 | + bool haveAudio = false; |
3622 | + bool haveVideo = false; |
3623 | + for (size_t i = 0; i < extractor->countTracks(); ++i) { |
3624 | + sp<AMessage> format; |
3625 | + status_t err = extractor->getTrackFormat(i, &format); |
3626 | + CHECK_EQ(err, (status_t)OK); |
3627 | + |
3628 | + AString mime; |
3629 | + CHECK(format->findString("mime", &mime)); |
3630 | + |
3631 | + bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6); |
3632 | + bool isVideo = !strncasecmp(mime.c_str(), "video/", 6); |
3633 | + |
3634 | + if (useAudio && !haveAudio && isAudio) { |
3635 | + haveAudio = true; |
3636 | + } else if (useVideo && !haveVideo && isVideo) { |
3637 | + haveVideo = true; |
3638 | + } else { |
3639 | + continue; |
3640 | + } |
3641 | + |
3642 | + ALOGV("selecting track %d", i); |
3643 | + |
3644 | + err = extractor->selectTrack(i); |
3645 | + CHECK_EQ(err, (status_t)OK); |
3646 | + |
3647 | + CodecState *state = |
3648 | + &stateByTrack.editValueAt(stateByTrack.add(i, CodecState())); |
3649 | + |
3650 | + state->mNumBytesDecoded = 0; |
3651 | + state->mNumBuffersDecoded = 0; |
3652 | + state->mIsAudio = isAudio; |
3653 | + |
3654 | + state->mCodec = MediaCodec::CreateByType( |
3655 | + looper, mime.c_str(), false /* encoder */); |
3656 | + |
3657 | + CHECK(state->mCodec != NULL); |
3658 | + |
3659 | + err = state->mCodec->configure( |
3660 | + format, isVideo ? surface : NULL, |
3661 | + NULL /* crypto */, |
3662 | + 0 /* flags */); |
3663 | + |
3664 | + CHECK_EQ(err, (status_t)OK); |
3665 | + |
3666 | + state->mSignalledInputEOS = false; |
3667 | + state->mSawOutputEOS = false; |
3668 | + } |
3669 | + |
3670 | + CHECK(!stateByTrack.isEmpty()); |
3671 | + |
3672 | + int64_t startTimeUs = ALooper::GetNowUs(); |
3673 | + |
3674 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { |
3675 | + CodecState *state = &stateByTrack.editValueAt(i); |
3676 | + |
3677 | + sp<MediaCodec> codec = state->mCodec; |
3678 | + |
3679 | + CHECK_EQ((status_t)OK, codec->start()); |
3680 | + |
3681 | + CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers)); |
3682 | + CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers)); |
3683 | + |
3684 | + ALOGV("got %d input and %d output buffers", |
3685 | + state->mInBuffers.size(), state->mOutBuffers.size()); |
3686 | + } |
3687 | + |
3688 | + bool sawInputEOS = false; |
3689 | + |
3690 | + for (;;) { |
3691 | + if (!sawInputEOS) { |
3692 | + size_t trackIndex; |
3693 | + status_t err = extractor->getSampleTrackIndex(&trackIndex); |
3694 | + |
3695 | + if (err != OK) { |
3696 | + ALOGV("saw input eos"); |
3697 | + sawInputEOS = true; |
3698 | + } else { |
3699 | + CodecState *state = &stateByTrack.editValueFor(trackIndex); |
3700 | + |
3701 | + size_t index; |
3702 | + err = state->mCodec->dequeueInputBuffer(&index, kTimeout); |
3703 | + |
3704 | + if (err == OK) { |
3705 | + ALOGV("filling input buffer %d", index); |
3706 | + |
3707 | + const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index); |
3708 | + |
3709 | + err = extractor->readSampleData(buffer); |
3710 | + CHECK_EQ(err, (status_t)OK); |
3711 | + |
3712 | + int64_t timeUs; |
3713 | + err = extractor->getSampleTime(&timeUs); |
3714 | + CHECK_EQ(err, (status_t)OK); |
3715 | + |
3716 | + uint32_t bufferFlags = 0; |
3717 | + |
3718 | + err = state->mCodec->queueInputBuffer( |
3719 | + index, |
3720 | + 0 /* offset */, |
3721 | + buffer->size(), |
3722 | + timeUs, |
3723 | + bufferFlags); |
3724 | + |
3725 | + CHECK_EQ(err, (status_t)OK); |
3726 | + |
3727 | + extractor->advance(); |
3728 | + } else { |
3729 | + CHECK_EQ(err, -EAGAIN); |
3730 | + } |
3731 | + } |
3732 | + } else { |
3733 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { |
3734 | + CodecState *state = &stateByTrack.editValueAt(i); |
3735 | + |
3736 | + if (!state->mSignalledInputEOS) { |
3737 | + size_t index; |
3738 | + status_t err = |
3739 | + state->mCodec->dequeueInputBuffer(&index, kTimeout); |
3740 | + |
3741 | + if (err == OK) { |
3742 | + ALOGV("signalling input EOS on track %d", i); |
3743 | + |
3744 | + err = state->mCodec->queueInputBuffer( |
3745 | + index, |
3746 | + 0 /* offset */, |
3747 | + 0 /* size */, |
3748 | + 0ll /* timeUs */, |
3749 | + MediaCodec::BUFFER_FLAG_EOS); |
3750 | + |
3751 | + CHECK_EQ(err, (status_t)OK); |
3752 | + |
3753 | + state->mSignalledInputEOS = true; |
3754 | + } else { |
3755 | + CHECK_EQ(err, -EAGAIN); |
3756 | + } |
3757 | + } |
3758 | + } |
3759 | + } |
3760 | + |
3761 | + bool sawOutputEOSOnAllTracks = true; |
3762 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { |
3763 | + CodecState *state = &stateByTrack.editValueAt(i); |
3764 | + if (!state->mSawOutputEOS) { |
3765 | + sawOutputEOSOnAllTracks = false; |
3766 | + break; |
3767 | + } |
3768 | + } |
3769 | + |
3770 | + if (sawOutputEOSOnAllTracks) { |
3771 | + break; |
3772 | + } |
3773 | + |
3774 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { |
3775 | + CodecState *state = &stateByTrack.editValueAt(i); |
3776 | + |
3777 | + if (state->mSawOutputEOS) { |
3778 | + continue; |
3779 | + } |
3780 | + |
3781 | + size_t index; |
3782 | + size_t offset; |
3783 | + size_t size; |
3784 | + int64_t presentationTimeUs; |
3785 | + uint32_t flags; |
3786 | + status_t err = state->mCodec->dequeueOutputBuffer( |
3787 | + &index, &offset, &size, &presentationTimeUs, &flags, |
3788 | + kTimeout); |
3789 | + |
3790 | + if (err == OK) { |
3791 | + ALOGV("draining output buffer %d, time = %lld us", |
3792 | + index, presentationTimeUs); |
3793 | + |
3794 | + ++state->mNumBuffersDecoded; |
3795 | + state->mNumBytesDecoded += size; |
3796 | + |
3797 | + err = state->mCodec->releaseOutputBuffer(index); |
3798 | + CHECK_EQ(err, (status_t)OK); |
3799 | + |
3800 | + if (flags & MediaCodec::BUFFER_FLAG_EOS) { |
3801 | + ALOGV("reached EOS on output."); |
3802 | + |
3803 | + state->mSawOutputEOS = true; |
3804 | + } |
3805 | + } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { |
3806 | + ALOGV("INFO_OUTPUT_BUFFERS_CHANGED"); |
3807 | + CHECK_EQ((status_t)OK, |
3808 | + state->mCodec->getOutputBuffers(&state->mOutBuffers)); |
3809 | + |
3810 | + ALOGV("got %d output buffers", state->mOutBuffers.size()); |
3811 | + } else if (err == INFO_FORMAT_CHANGED) { |
3812 | + sp<AMessage> format; |
3813 | + CHECK_EQ((status_t)OK, state->mCodec->getOutputFormat(&format)); |
3814 | + |
3815 | + ALOGV("INFO_FORMAT_CHANGED: %s", format->debugString().c_str()); |
3816 | + } else { |
3817 | + CHECK_EQ(err, -EAGAIN); |
3818 | + } |
3819 | + } |
3820 | + } |
3821 | + |
3822 | + int64_t elapsedTimeUs = ALooper::GetNowUs() - startTimeUs; |
3823 | + |
3824 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { |
3825 | + CodecState *state = &stateByTrack.editValueAt(i); |
3826 | + |
3827 | + CHECK_EQ((status_t)OK, state->mCodec->release()); |
3828 | + |
3829 | + if (state->mIsAudio) { |
3830 | + ALOGD("track %d: %lld bytes received. %.2f KB/sec\n", |
3831 | + i, |
3832 | + state->mNumBytesDecoded, |
3833 | + state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs); |
3834 | + } else { |
3835 | + ALOGD("track %d: %lld frames decoded, %.2f fps. %lld bytes " |
3836 | + "received. %.2f KB/sec\n", |
3837 | + i, |
3838 | + state->mNumBuffersDecoded, |
3839 | + state->mNumBuffersDecoded * 1E6 / elapsedTimeUs, |
3840 | + state->mNumBytesDecoded, |
3841 | + state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs); |
3842 | + } |
3843 | + } |
3844 | + |
3845 | + return 0; |
3846 | +} |
3847 | + |
3848 | +int main(int argc, char **argv) { |
3849 | + using namespace android; |
3850 | + |
3851 | + const char *me = argv[0]; |
3852 | + |
3853 | + bool useAudio = false; |
3854 | + bool useVideo = false; |
3855 | + bool playback = false; |
3856 | + bool useSurface = false; |
3857 | + |
3858 | + int res; |
3859 | + while ((res = getopt(argc, argv, "havpSD")) >= 0) { |
3860 | + switch (res) { |
3861 | + case 'a': |
3862 | + { |
3863 | + useAudio = true; |
3864 | + break; |
3865 | + } |
3866 | + |
3867 | + case 'v': |
3868 | + { |
3869 | + useVideo = true; |
3870 | + break; |
3871 | + } |
3872 | + |
3873 | + case 'p': |
3874 | + { |
3875 | + playback = true; |
3876 | + break; |
3877 | + } |
3878 | + |
3879 | + case 'S': |
3880 | + { |
3881 | + useSurface = true; |
3882 | + break; |
3883 | + } |
3884 | + |
3885 | + case '?': |
3886 | + case 'h': |
3887 | + default: |
3888 | + { |
3889 | + usage(me); |
3890 | + } |
3891 | + } |
3892 | + } |
3893 | + |
3894 | + argc -= optind; |
3895 | + argv += optind; |
3896 | + |
3897 | + if (argc != 1) { |
3898 | + usage(me); |
3899 | + } |
3900 | + |
3901 | + if (!useAudio && !useVideo) { |
3902 | + useAudio = useVideo = true; |
3903 | + } |
3904 | + |
3905 | + ProcessState::self()->startThreadPool(); |
3906 | + |
3907 | + DataSource::RegisterDefaultSniffers(); |
3908 | + |
3909 | + sp<ALooper> looper = new ALooper; |
3910 | + looper->start(); |
3911 | + |
3912 | + sp<SurfaceComposerClient> composerClient; |
3913 | + sp<SurfaceControl> control; |
3914 | + sp<Surface> surface; |
3915 | + |
3916 | + if (playback || (useSurface && useVideo)) { |
3917 | + composerClient = new SurfaceComposerClient; |
3918 | + CHECK_EQ(composerClient->initCheck(), (status_t)OK); |
3919 | + |
3920 | + sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay( |
3921 | + ISurfaceComposer::eDisplayIdMain)); |
3922 | + DisplayInfo info; |
3923 | + SurfaceComposerClient::getDisplayInfo(display, &info); |
3924 | + ssize_t displayWidth = info.w; |
3925 | + ssize_t displayHeight = info.h; |
3926 | + |
3927 | + ALOGV("display is %ld x %ld\n", displayWidth, displayHeight); |
3928 | + |
3929 | + control = composerClient->createSurface( |
3930 | + String8("A Surface"), |
3931 | + displayWidth, |
3932 | + displayHeight, |
3933 | + PIXEL_FORMAT_RGB_565, |
3934 | + 0); |
3935 | + |
3936 | + CHECK(control != NULL); |
3937 | + CHECK(control->isValid()); |
3938 | + |
3939 | + SurfaceComposerClient::openGlobalTransaction(); |
3940 | + CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); |
3941 | + CHECK_EQ(control->show(), (status_t)OK); |
3942 | + SurfaceComposerClient::closeGlobalTransaction(); |
3943 | + |
3944 | + surface = control->getSurface(); |
3945 | + CHECK(surface != NULL); |
3946 | + } |
3947 | + |
3948 | + if (playback) { |
3949 | + sp<SimplePlayer> player = new SimplePlayer; |
3950 | + looper->registerHandler(player); |
3951 | + |
3952 | + player->setDataSource(argv[0]); |
3953 | + player->setSurface(surface->getSurfaceTexture()); |
3954 | + player->start(); |
3955 | + ALOGD("Playing for 60 seconds\n"); |
3956 | + sleep(60); |
3957 | + player->stop(); |
3958 | + player->reset(); |
3959 | + } else { |
3960 | + decode(looper, argv[0], useAudio, useVideo, surface); |
3961 | + } |
3962 | + |
3963 | + if (playback || (useSurface && useVideo)) { |
3964 | + composerClient->dispose(); |
3965 | + } |
3966 | + |
3967 | + looper->stop(); |
3968 | + |
3969 | + return 0; |
3970 | +} |
3971 | |
3972 | === added file 'android/compat/media/decoding_service.cpp' |
3973 | --- android/compat/media/decoding_service.cpp 1970-01-01 00:00:00 +0000 |
3974 | +++ android/compat/media/decoding_service.cpp 2016-01-11 14:31:46 +0000 |
3975 | @@ -0,0 +1,366 @@ |
3976 | +/* |
3977 | + * Copyright (C) 2014 Canonical Ltd |
3978 | + * |
3979 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
3980 | + * you may not use this file except in compliance with the License. |
3981 | + * You may obtain a copy of the License at |
3982 | + * |
3983 | + * http://www.apache.org/licenses/LICENSE-2.0 |
3984 | + * |
3985 | + * Unless required by applicable law or agreed to in writing, software |
3986 | + * distributed under the License is distributed on an "AS IS" BASIS, |
3987 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3988 | + * See the License for the specific language governing permissions and |
3989 | + * limitations under the License. |
3990 | + * |
3991 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> |
3992 | + */ |
3993 | + |
3994 | +// Uncomment to enable verbose debug output |
3995 | +#define LOG_NDEBUG 0 |
3996 | + |
3997 | +#undef LOG_TAG |
3998 | +#define LOG_TAG "DecodingService" |
3999 | + |
4000 | +#include "decoding_service_priv.h" |
4001 | + |
4002 | +#include <binder/IServiceManager.h> |
4003 | +#include <binder/Parcel.h> |
4004 | +#include <binder/IPCThreadState.h> |
4005 | +#include <binder/ProcessState.h> |
4006 | +#include <binder/BpBinder.h> |
4007 | + |
4008 | +typedef void* EGLDisplay; |
4009 | +typedef void* EGLSyncKHR; |
4010 | + |
4011 | +#include <ui/GraphicBuffer.h> |
4012 | +#include <gui/GraphicBufferAlloc.h> |
4013 | +#include <gui/IGraphicBufferProducer.h> |
4014 | +#include <gui/IGraphicBufferConsumer.h> |
4015 | +#include <gui/Surface.h> |
4016 | +#include <gui/NativeBufferAlloc.h> |
4017 | + |
4018 | +namespace android { |
4019 | + |
4020 | +IMPLEMENT_META_INTERFACE(DecodingService, "android.media.IDecodingService"); |
4021 | +IMPLEMENT_META_INTERFACE(DecodingServiceSession, "android.media.IDecodingServiceSession"); |
4022 | + |
4023 | +enum { |
4024 | + GET_IGRAPHICBUFFERCONSUMER = IBinder::FIRST_CALL_TRANSACTION, |
4025 | + GET_IGRAPHICBUFFERPRODUCER, |
4026 | + REGISTER_SESSION, |
4027 | + UNREGISTER_SESSION, |
4028 | +}; |
4029 | + |
4030 | +// ---------------------------------------------------------------------- |
4031 | + |
4032 | +status_t BnDecodingService::onTransact( |
4033 | + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) |
4034 | +{ |
4035 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4036 | + switch (code) { |
4037 | + case GET_IGRAPHICBUFFERCONSUMER: { |
4038 | + CHECK_INTERFACE(IDecodingService, data, reply); |
4039 | + sp<IGraphicBufferConsumer> gbc; |
4040 | + status_t res = getIGraphicBufferConsumer(&gbc); |
4041 | + |
4042 | + reply->writeStrongBinder(gbc->asBinder()); |
4043 | + reply->writeInt32(res); |
4044 | + |
4045 | + return NO_ERROR; |
4046 | + } break; |
4047 | + case GET_IGRAPHICBUFFERPRODUCER: { |
4048 | + CHECK_INTERFACE(IDecodingService, data, reply); |
4049 | + sp<IGraphicBufferProducer> gbp; |
4050 | + status_t res = getIGraphicBufferProducer(&gbp); |
4051 | + |
4052 | + reply->writeStrongBinder(gbp->asBinder()); |
4053 | + reply->writeInt32(res); |
4054 | + |
4055 | + return NO_ERROR; |
4056 | + } break; |
4057 | + case REGISTER_SESSION: { |
4058 | + CHECK_INTERFACE(IDecodingService, data, reply); |
4059 | + sp<IBinder> binder = data.readStrongBinder(); |
4060 | + uint32_t handle = data.readInt32(); |
4061 | + sp<IDecodingServiceSession> session(new BpDecodingServiceSession(binder)); |
4062 | + registerSession(session, handle); |
4063 | + |
4064 | + return NO_ERROR; |
4065 | + } break; |
4066 | + case UNREGISTER_SESSION: { |
4067 | + CHECK_INTERFACE(IDecodingService, data, reply); |
4068 | + unregisterSession(); |
4069 | + |
4070 | + return NO_ERROR; |
4071 | + } break; |
4072 | + default: |
4073 | + return BBinder::onTransact(code, data, reply, flags); |
4074 | + } |
4075 | +} |
4076 | + |
4077 | +status_t BpDecodingService::getIGraphicBufferConsumer(sp<IGraphicBufferConsumer>* gbc) |
4078 | +{ |
4079 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4080 | + Parcel data, reply; |
4081 | + data.writeInterfaceToken(IDecodingService::getInterfaceDescriptor()); |
4082 | + remote()->transact(GET_IGRAPHICBUFFERCONSUMER, data, &reply); |
4083 | + *gbc = interface_cast<IGraphicBufferConsumer>(reply.readStrongBinder()); |
4084 | + return reply.readInt32(); |
4085 | +} |
4086 | + |
4087 | +status_t BpDecodingService::getIGraphicBufferProducer(sp<IGraphicBufferProducer>* gbp) |
4088 | +{ |
4089 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4090 | + Parcel data, reply; |
4091 | + data.writeInterfaceToken(IDecodingService::getInterfaceDescriptor()); |
4092 | + remote()->transact(GET_IGRAPHICBUFFERPRODUCER, data, &reply); |
4093 | + *gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder()); |
4094 | + return NO_ERROR; |
4095 | +} |
4096 | + |
4097 | +status_t BpDecodingService::registerSession(const sp<IDecodingServiceSession>& session, uint32_t handle) |
4098 | +{ |
4099 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4100 | + Parcel data, reply; |
4101 | + data.writeInterfaceToken(IDecodingService::getInterfaceDescriptor()); |
4102 | + data.writeStrongBinder(session->asBinder()); |
4103 | + data.writeInt32(handle); |
4104 | + remote()->transact(REGISTER_SESSION, data, &reply); |
4105 | + return NO_ERROR; |
4106 | +} |
4107 | + |
4108 | +status_t BpDecodingService::unregisterSession() |
4109 | +{ |
4110 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4111 | + Parcel data, reply; |
4112 | + data.writeInterfaceToken(IDecodingService::getInterfaceDescriptor()); |
4113 | + remote()->transact(UNREGISTER_SESSION, data, &reply); |
4114 | + return NO_ERROR; |
4115 | +} |
4116 | + |
4117 | +sp<DecodingService> DecodingService::decoding_service = NULL; |
4118 | + |
4119 | +DecodingService::DecodingService() |
4120 | + : client_death_cb(NULL), |
4121 | + client_death_context(NULL) |
4122 | +{ |
4123 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4124 | +} |
4125 | + |
4126 | +DecodingService::~DecodingService() |
4127 | +{ |
4128 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4129 | +} |
4130 | + |
4131 | +void DecodingService::instantiate() |
4132 | +{ |
4133 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4134 | + defaultServiceManager()->addService( |
4135 | + String16(IDecodingService::exported_service_name()), service_instance()); |
4136 | + ALOGD("Added Binder service '%s' to ServiceManager", IDecodingService::exported_service_name()); |
4137 | + |
4138 | + service_instance()->createBufferQueue(); |
4139 | +} |
4140 | + |
4141 | +sp<DecodingService>& DecodingService::service_instance() |
4142 | +{ |
4143 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4144 | + |
4145 | + // TODO Add a mutex here |
4146 | + if (decoding_service == NULL) |
4147 | + { |
4148 | + ALOGD("Creating new static instance of DecodingService"); |
4149 | + decoding_service = new DecodingService(); |
4150 | + } |
4151 | + |
4152 | + return decoding_service; |
4153 | +} |
4154 | + |
4155 | +void DecodingService::setDecodingClientDeathCb(DecodingClientDeathCbHybris cb, uint32_t handle, void* context) |
4156 | +{ |
4157 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4158 | + |
4159 | + ClientCb *holder = (ClientCb*) malloc(sizeof(ClientCb)); |
4160 | + holder->cb = cb; |
4161 | + holder->context = context; |
4162 | + |
4163 | + clients.add(handle, holder); |
4164 | +} |
4165 | + |
4166 | +status_t DecodingService::getIGraphicBufferConsumer(sp<IGraphicBufferConsumer>* gbc) |
4167 | +{ |
4168 | + // TODO: Make sure instantiate() has been called first |
4169 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4170 | + pid_t pid = IPCThreadState::self()->getCallingPid(); |
4171 | + ALOGD("Calling Pid: %d", pid); |
4172 | + |
4173 | +#if ANDROID_VERSION_MAJOR==5 |
4174 | + *gbc = consumer; |
4175 | +#else |
4176 | + *gbc = buffer_queue; |
4177 | +#endif |
4178 | + |
4179 | + return OK; |
4180 | +} |
4181 | + |
4182 | +status_t DecodingService::getIGraphicBufferProducer(sp<IGraphicBufferProducer>* gbp) |
4183 | +{ |
4184 | + pid_t pid = IPCThreadState::self()->getCallingPid(); |
4185 | + ALOGD("Calling Pid: %d", pid); |
4186 | + |
4187 | +#if ANDROID_VERSION_MAJOR==5 |
4188 | + *gbp = producer; |
4189 | +#else |
4190 | + *gbp = buffer_queue; |
4191 | +#endif |
4192 | + ALOGD("producer(gbp): %p", (void*)gbp->get()); |
4193 | + return OK; |
4194 | +} |
4195 | + |
4196 | +status_t DecodingService::registerSession(const sp<IDecodingServiceSession>& session, uint32_t handle) |
4197 | +{ |
4198 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4199 | + |
4200 | + // Add session/handle to running clients map and connect death observer |
4201 | + status_t ret = session->asBinder()->linkToDeath(sp<IBinder::DeathRecipient>(this)); |
4202 | + clientCbs.add(session->asBinder(), clients.valueFor(handle)); |
4203 | + clients.removeItem(handle); |
4204 | + |
4205 | + // Create a new BufferQueue instance so that the next created client plays |
4206 | + // video correctly |
4207 | + createBufferQueue(); |
4208 | + |
4209 | + return ret; |
4210 | +} |
4211 | + |
4212 | +status_t DecodingService::unregisterSession() |
4213 | +{ |
4214 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4215 | + if (session != NULL) |
4216 | + { |
4217 | + session->asBinder()->unlinkToDeath(this); |
4218 | + session.clear(); |
4219 | + // Reset the BufferQueue instance so that the next created client plays |
4220 | + // video correctly |
4221 | +#if ANDROID_VERSION_MAJOR==5 |
4222 | + producer.clear(); |
4223 | + consumer.clear(); |
4224 | +#else |
4225 | + buffer_queue.clear(); |
4226 | +#endif |
4227 | + } |
4228 | + |
4229 | + return OK; |
4230 | +} |
4231 | + |
4232 | +void DecodingService::createBufferQueue() |
4233 | +{ |
4234 | + // Use a new native buffer allocator vs the default one, which means it'll use the proper one |
4235 | + // that will allow rendering to work with Mir |
4236 | + sp<IGraphicBufferAlloc> g_buffer_alloc(new GraphicBufferAlloc()); |
4237 | + |
4238 | + // This BuferQueue is shared between the client and the service |
4239 | +#if ANDROID_VERSION_MAJOR==5 |
4240 | + BufferQueue::createBufferQueue(&producer, &consumer); |
4241 | +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 |
4242 | + sp<NativeBufferAlloc> native_alloc(new NativeBufferAlloc()); |
4243 | + buffer_queue = new BufferQueue(false, NULL, native_alloc); |
4244 | +#else |
4245 | + buffer_queue = new BufferQueue(NULL); |
4246 | + ALOGD("buffer_queue: %p", (void*)buffer_queue.get()); |
4247 | +#endif |
4248 | +#if ANDROID_VERSION_MAJOR==5 |
4249 | + producer->setBufferCount(5); |
4250 | +#else |
4251 | + buffer_queue->setBufferCount(5); |
4252 | +#endif |
4253 | +} |
4254 | + |
4255 | +void DecodingService::binderDied(const wp<IBinder>& who) |
4256 | +{ |
4257 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4258 | + |
4259 | + sp<IBinder> sp = who.promote(); |
4260 | + ClientCb *cb = clientCbs.valueFor(sp); |
4261 | + |
4262 | + if (cb && cb->cb != NULL) { |
4263 | + cb->cb(cb->context); |
4264 | + free(cb); |
4265 | + clientCbs.removeItem(sp); |
4266 | + } |
4267 | + |
4268 | + unregisterSession(); |
4269 | +} |
4270 | + |
4271 | +sp<BpDecodingService> DecodingClient::decoding_service = NULL; |
4272 | + |
4273 | +DecodingClient::DecodingClient() |
4274 | +{ |
4275 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4276 | + |
4277 | + ProcessState::self()->startThreadPool(); |
4278 | +} |
4279 | + |
4280 | +DecodingClient::~DecodingClient() |
4281 | +{ |
4282 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4283 | +} |
4284 | + |
4285 | +sp<BpDecodingService>& DecodingClient::service_instance() |
4286 | +{ |
4287 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4288 | + // TODO: Add a mutex here |
4289 | + if (decoding_service == NULL) |
4290 | + { |
4291 | + ALOGD("Creating a new static BpDecodingService instance"); |
4292 | + sp<IServiceManager> service_manager = defaultServiceManager(); |
4293 | + sp<IBinder> service = service_manager->getService( |
4294 | + String16(IDecodingService::exported_service_name())); |
4295 | + decoding_service = new BpDecodingService(service); |
4296 | + } |
4297 | + |
4298 | + return decoding_service; |
4299 | +} |
4300 | + |
4301 | +status_t DecodingClient::getIGraphicBufferConsumer(sp<IGraphicBufferConsumer>* gbc) |
4302 | +{ |
4303 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4304 | + return service_instance()->getIGraphicBufferConsumer(gbc); |
4305 | +} |
4306 | + |
4307 | +// IDecodingServiceSession |
4308 | + |
4309 | +BpDecodingServiceSession::BpDecodingServiceSession(const sp<IBinder>& impl) |
4310 | + : BpInterface<IDecodingServiceSession>(impl) |
4311 | +{ |
4312 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4313 | +} |
4314 | + |
4315 | +BpDecodingServiceSession::~BpDecodingServiceSession() |
4316 | +{ |
4317 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4318 | +} |
4319 | + |
4320 | +BnDecodingServiceSession::BnDecodingServiceSession() |
4321 | +{ |
4322 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4323 | +} |
4324 | + |
4325 | +BnDecodingServiceSession::~BnDecodingServiceSession() |
4326 | +{ |
4327 | + ALOGD("%s", __PRETTY_FUNCTION__); |
4328 | +} |
4329 | + |
4330 | +status_t BnDecodingServiceSession::onTransact(uint32_t code, const Parcel& data, |
4331 | + Parcel* reply, uint32_t flags) |
4332 | +{ |
4333 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4334 | + |
4335 | + return NO_ERROR; |
4336 | +} |
4337 | + |
4338 | +// ----- C API ----- // |
4339 | + |
4340 | + |
4341 | +}; // namespace android |
4342 | |
4343 | === added file 'android/compat/media/decoding_service_priv.h' |
4344 | --- android/compat/media/decoding_service_priv.h 1970-01-01 00:00:00 +0000 |
4345 | +++ android/compat/media/decoding_service_priv.h 2016-01-11 14:31:46 +0000 |
4346 | @@ -0,0 +1,208 @@ |
4347 | +/* |
4348 | + * Copyright (C) 2014 Canonical Ltd |
4349 | + * |
4350 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
4351 | + * you may not use this file except in compliance with the License. |
4352 | + * You may obtain a copy of the License at |
4353 | + * |
4354 | + * http://www.apache.org/licenses/LICENSE-2.0 |
4355 | + * |
4356 | + * Unless required by applicable law or agreed to in writing, software |
4357 | + * distributed under the License is distributed on an "AS IS" BASIS, |
4358 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4359 | + * See the License for the specific language governing permissions and |
4360 | + * limitations under the License. |
4361 | + * |
4362 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> |
4363 | + */ |
4364 | + |
4365 | +#ifndef DECODING_SERVICE_PRIV_H_ |
4366 | +#define DECODING_SERVICE_PRIV_H_ |
4367 | + |
4368 | +#include "surface_texture_client_hybris_priv.h" |
4369 | + |
4370 | +#include <binder/IInterface.h> |
4371 | +#include <binder/Parcel.h> |
4372 | + |
4373 | +namespace android { |
4374 | + |
4375 | +typedef struct { |
4376 | + DecodingClientDeathCbHybris cb; |
4377 | + void *context; |
4378 | +} ClientCb; |
4379 | + |
4380 | +class IGraphicBufferConsumer; |
4381 | +class IGraphicBufferProducer; |
4382 | +class BufferQueue; |
4383 | +class GLConsumer; |
4384 | + |
4385 | +class IDecodingServiceSession : public IInterface |
4386 | +{ |
4387 | +public: |
4388 | + DECLARE_META_INTERFACE(DecodingServiceSession); |
4389 | + |
4390 | + static const char* exported_service_name() { return "android.media.IDecodingServiceSession"; } |
4391 | + |
4392 | +}; |
4393 | + |
4394 | +class BnDecodingServiceSession : public BnInterface<IDecodingServiceSession> |
4395 | +{ |
4396 | +public: |
4397 | + BnDecodingServiceSession(); |
4398 | + virtual ~BnDecodingServiceSession(); |
4399 | + |
4400 | + virtual status_t onTransact(uint32_t code, const Parcel& data, |
4401 | + Parcel* reply, uint32_t flags = 0); |
4402 | +}; |
4403 | + |
4404 | +enum { |
4405 | + SET_DECODING_CLIENT_DEATH_CB = IBinder::FIRST_CALL_TRANSACTION, |
4406 | +}; |
4407 | + |
4408 | +class BpDecodingServiceSession : public BpInterface<IDecodingServiceSession> |
4409 | +{ |
4410 | +public: |
4411 | + BpDecodingServiceSession(const sp<IBinder>& impl); |
4412 | + ~BpDecodingServiceSession(); |
4413 | +}; |
4414 | + |
4415 | +class IDecodingService: public IInterface |
4416 | +{ |
4417 | +public: |
4418 | + DECLARE_META_INTERFACE(DecodingService); |
4419 | + |
4420 | + static const char* exported_service_name() { return "android.media.IDecodingService"; } |
4421 | + |
4422 | + virtual status_t getIGraphicBufferConsumer(sp<IGraphicBufferConsumer>* gbc) = 0; |
4423 | + virtual status_t getIGraphicBufferProducer(sp<IGraphicBufferProducer>* gbp) = 0; |
4424 | + virtual status_t registerSession(const sp<IDecodingServiceSession>& session, uint32_t handle) = 0; |
4425 | + virtual status_t unregisterSession() = 0; |
4426 | +}; |
4427 | + |
4428 | +class BnDecodingService: public BnInterface<IDecodingService> |
4429 | +{ |
4430 | +public: |
4431 | + virtual status_t onTransact( uint32_t code, |
4432 | + const Parcel& data, |
4433 | + Parcel* reply, |
4434 | + uint32_t flags = 0); |
4435 | +}; |
4436 | + |
4437 | +class BpDecodingService: public BpInterface<IDecodingService> |
4438 | +{ |
4439 | +public: |
4440 | + BpDecodingService(const sp<IBinder>& impl) |
4441 | + : BpInterface<IDecodingService>(impl) |
4442 | + { |
4443 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4444 | + } |
4445 | + |
4446 | + virtual status_t getIGraphicBufferConsumer(sp<IGraphicBufferConsumer>* gbc); |
4447 | + virtual status_t getIGraphicBufferProducer(sp<IGraphicBufferProducer>* gbp); |
4448 | + virtual status_t registerSession(const sp<IDecodingServiceSession>& session, uint32_t handle); |
4449 | + virtual status_t unregisterSession(); |
4450 | +}; |
4451 | + |
4452 | +class DecodingService : public BnDecodingService, |
4453 | + public IBinder::DeathRecipient |
4454 | +{ |
4455 | +public: |
4456 | + DecodingService(); |
4457 | + virtual ~DecodingService(); |
4458 | + /** Adds the decoding service to the default service manager in Binder **/ |
4459 | + static void instantiate(); |
4460 | + static sp<DecodingService>& service_instance(); |
4461 | + |
4462 | + virtual void setDecodingClientDeathCb(DecodingClientDeathCbHybris cb, uint32_t handle, void* context); |
4463 | + |
4464 | + // IDecodingService interface: |
4465 | + virtual status_t getIGraphicBufferConsumer(sp<IGraphicBufferConsumer>* gbc); |
4466 | + virtual status_t getIGraphicBufferProducer(sp<IGraphicBufferProducer>* gbp); |
4467 | + |
4468 | + virtual status_t registerSession(const sp<IDecodingServiceSession>& session, uint32_t handle); |
4469 | + virtual status_t unregisterSession(); |
4470 | + |
4471 | + /** Get notified when the Binder connection to the client dies **/ |
4472 | + virtual void binderDied(const wp<IBinder>& who); |
4473 | + |
4474 | +protected: |
4475 | + virtual void createBufferQueue(); |
4476 | + |
4477 | +private: |
4478 | + static sp<DecodingService> decoding_service; |
4479 | +#if ANDROID_VERSION_MAJOR==5 |
4480 | + sp<IGraphicBufferProducer> producer; |
4481 | + sp<IGraphicBufferConsumer> consumer; |
4482 | +#else |
4483 | + sp<BufferQueue> buffer_queue; |
4484 | +#endif |
4485 | + sp<IDecodingServiceSession> session; |
4486 | + DecodingClientDeathCbHybris client_death_cb; |
4487 | + void *client_death_context; |
4488 | + KeyedVector< uint32_t, ClientCb* > clients; |
4489 | + KeyedVector< sp<IBinder>, ClientCb* > clientCbs; |
4490 | +}; |
4491 | + |
4492 | +class DecodingClient |
4493 | +{ |
4494 | +public: |
4495 | + DecodingClient(); |
4496 | + virtual ~DecodingClient(); |
4497 | + |
4498 | + static sp<BpDecodingService>& service_instance(); |
4499 | + |
4500 | + virtual status_t getIGraphicBufferConsumer(sp<IGraphicBufferConsumer>* gbc); |
4501 | + |
4502 | +private: |
4503 | + static sp<BpDecodingService> decoding_service; |
4504 | +}; |
4505 | + |
4506 | +struct IGBCWrapper |
4507 | +{ |
4508 | + IGBCWrapper(const sp<IGraphicBufferConsumer>& igbc) |
4509 | + { |
4510 | + consumer = igbc; |
4511 | + } |
4512 | + |
4513 | + sp<IGraphicBufferConsumer> consumer; |
4514 | +}; |
4515 | + |
4516 | +struct IGBPWrapper |
4517 | +{ |
4518 | + IGBPWrapper(const sp<IGraphicBufferProducer>& igbp) |
4519 | + { |
4520 | + producer = igbp; |
4521 | + } |
4522 | + |
4523 | + sp<IGraphicBufferProducer> producer; |
4524 | +}; |
4525 | + |
4526 | +struct GLConsumerWrapper |
4527 | +{ |
4528 | + GLConsumerWrapper(const sp<_GLConsumerHybris>& gl_consumer) |
4529 | + { |
4530 | + consumer = gl_consumer; |
4531 | + } |
4532 | + |
4533 | + sp<_GLConsumerHybris> consumer; |
4534 | +}; |
4535 | + |
4536 | +struct DSSessionWrapper |
4537 | +{ |
4538 | + DSSessionWrapper(const sp<IDecodingServiceSession>& session) |
4539 | + { |
4540 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4541 | + this->session = session; |
4542 | + } |
4543 | + |
4544 | + ~DSSessionWrapper() |
4545 | + { |
4546 | + ALOGD("Entering %s", __PRETTY_FUNCTION__); |
4547 | + } |
4548 | + |
4549 | + sp<IDecodingServiceSession> session; |
4550 | +}; |
4551 | + |
4552 | +}; // namespace android |
4553 | + |
4554 | +#endif |
4555 | |
4556 | === added file 'android/compat/media/direct_media_test.cpp' |
4557 | --- android/compat/media/direct_media_test.cpp 1970-01-01 00:00:00 +0000 |
4558 | +++ android/compat/media/direct_media_test.cpp 2016-01-11 14:31:46 +0000 |
4559 | @@ -0,0 +1,417 @@ |
4560 | +/* |
4561 | + * Copyright (C) 2013 Canonical Ltd |
4562 | + * |
4563 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
4564 | + * you may not use this file except in compliance with the License. |
4565 | + * You may obtain a copy of the License at |
4566 | + * |
4567 | + * http://www.apache.org/licenses/LICENSE-2.0 |
4568 | + * |
4569 | + * Unless required by applicable law or agreed to in writing, software |
4570 | + * distributed under the License is distributed on an "AS IS" BASIS, |
4571 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4572 | + * See the License for the specific language governing permissions and |
4573 | + * limitations under the License. |
4574 | + * |
4575 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> |
4576 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> |
4577 | + */ |
4578 | + |
4579 | +#include <hybris/media/media_compatibility_layer.h> |
4580 | +#include "direct_media_test.h" |
4581 | + |
4582 | +#include <utils/Errors.h> |
4583 | + |
4584 | +#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h> |
4585 | + |
4586 | +#include <GLES2/gl2.h> |
4587 | +#include <GLES2/gl2ext.h> |
4588 | + |
4589 | +#include <sys/stat.h> |
4590 | +#include <sys/types.h> |
4591 | +#include <fcntl.h> |
4592 | +#include <unistd.h> |
4593 | + |
4594 | +#include <cassert> |
4595 | +#include <cstdio> |
4596 | +#include <cstdlib> |
4597 | +#include <cstring> |
4598 | + |
4599 | +using namespace android; |
4600 | + |
4601 | +static float DestWidth = 0.0, DestHeight = 0.0; |
4602 | +// Actual video dimmensions |
4603 | +static int Width = 0, Height = 0; |
4604 | + |
4605 | +static GLfloat positionCoordinates[8]; |
4606 | + |
4607 | +MediaPlayerWrapper *player = NULL; |
4608 | + |
4609 | +void calculate_position_coordinates() |
4610 | +{ |
4611 | + // Assuming cropping output for now |
4612 | + float x = 1, y = 1; |
4613 | + |
4614 | + // Black borders |
4615 | + x = float(Width / DestWidth); |
4616 | + y = float(Height / DestHeight); |
4617 | + |
4618 | + // Make the larger side be 1 |
4619 | + if (x > y) { |
4620 | + y /= x; |
4621 | + x = 1; |
4622 | + } else { |
4623 | + x /= y; |
4624 | + y = 1; |
4625 | + } |
4626 | + |
4627 | + positionCoordinates[0] = -x; |
4628 | + positionCoordinates[1] = y; |
4629 | + positionCoordinates[2] = -x; |
4630 | + positionCoordinates[3] = -y; |
4631 | + positionCoordinates[4] = x; |
4632 | + positionCoordinates[5] = -y; |
4633 | + positionCoordinates[6] = x; |
4634 | + positionCoordinates[7] = y; |
4635 | +} |
4636 | + |
4637 | +WindowRenderer::WindowRenderer(int width, int height) |
4638 | + : mThreadCmd(CMD_IDLE) |
4639 | +{ |
4640 | + createThread(threadStart, this); |
4641 | +} |
4642 | + |
4643 | +WindowRenderer::~WindowRenderer() |
4644 | +{ |
4645 | +} |
4646 | + |
4647 | +int WindowRenderer::threadStart(void* self) |
4648 | +{ |
4649 | + ((WindowRenderer *)self)->glThread(); |
4650 | + return 0; |
4651 | +} |
4652 | + |
4653 | +void WindowRenderer::glThread() |
4654 | +{ |
4655 | + printf("%s\n", __PRETTY_FUNCTION__); |
4656 | + |
4657 | + Mutex::Autolock autoLock(mLock); |
4658 | +} |
4659 | + |
4660 | +struct ClientWithSurface |
4661 | +{ |
4662 | + SfClient* client; |
4663 | + SfSurface* surface; |
4664 | +}; |
4665 | + |
4666 | +ClientWithSurface client_with_surface(bool setup_surface_with_egl) |
4667 | +{ |
4668 | + ClientWithSurface cs = ClientWithSurface(); |
4669 | + |
4670 | + cs.client = sf_client_create(); |
4671 | + |
4672 | + if (!cs.client) { |
4673 | + printf("Problem creating client ... aborting now."); |
4674 | + return cs; |
4675 | + } |
4676 | + |
4677 | + static const size_t primary_display = 0; |
4678 | + |
4679 | + DestWidth = sf_get_display_width(primary_display); |
4680 | + DestHeight = sf_get_display_height(primary_display); |
4681 | + printf("Primary display width: %f, height: %f\n", DestWidth, DestHeight); |
4682 | + |
4683 | + SfSurfaceCreationParameters params = { |
4684 | + 0, |
4685 | + 0, |
4686 | + (int) DestWidth, |
4687 | + (int) DestHeight, |
4688 | + -1, //PIXEL_FORMAT_RGBA_8888, |
4689 | + 15000, |
4690 | + 0.5f, |
4691 | + setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL |
4692 | + "MediaCompatLayerTestSurface" |
4693 | + }; |
4694 | + |
4695 | + cs.surface = sf_surface_create(cs.client, ¶ms); |
4696 | + |
4697 | + if (!cs.surface) { |
4698 | + printf("Problem creating surface ... aborting now."); |
4699 | + return cs; |
4700 | + } |
4701 | + |
4702 | + sf_surface_make_current(cs.surface); |
4703 | + |
4704 | + return cs; |
4705 | +} |
4706 | + |
4707 | +struct RenderData |
4708 | +{ |
4709 | + static const char *vertex_shader() |
4710 | + { |
4711 | + return |
4712 | + "attribute vec4 a_position; \n" |
4713 | + "attribute vec2 a_texCoord; \n" |
4714 | + "uniform mat4 m_texMatrix; \n" |
4715 | + "varying vec2 v_texCoord; \n" |
4716 | + "varying float topDown; \n" |
4717 | + "void main() \n" |
4718 | + "{ \n" |
4719 | + " gl_Position = a_position; \n" |
4720 | + " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n" |
4721 | + "} \n"; |
4722 | + } |
4723 | + |
4724 | + static const char *fragment_shader() |
4725 | + { |
4726 | + return |
4727 | + "#extension GL_OES_EGL_image_external : require \n" |
4728 | + "precision mediump float; \n" |
4729 | + "varying vec2 v_texCoord; \n" |
4730 | + "uniform samplerExternalOES s_texture; \n" |
4731 | + "void main() \n" |
4732 | + "{ \n" |
4733 | + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" |
4734 | + "} \n"; |
4735 | + } |
4736 | + |
4737 | + static GLuint loadShader(GLenum shaderType, const char* pSource) |
4738 | + { |
4739 | + GLuint shader = glCreateShader(shaderType); |
4740 | + |
4741 | + if (shader) { |
4742 | + glShaderSource(shader, 1, &pSource, NULL); |
4743 | + glCompileShader(shader); |
4744 | + GLint compiled = 0; |
4745 | + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); |
4746 | + |
4747 | + if (!compiled) { |
4748 | + GLint infoLen = 0; |
4749 | + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); |
4750 | + if (infoLen) { |
4751 | + char* buf = (char*) malloc(infoLen); |
4752 | + if (buf) { |
4753 | + glGetShaderInfoLog(shader, infoLen, NULL, buf); |
4754 | + fprintf(stderr, "Could not compile shader %d:\n%s\n", |
4755 | + shaderType, buf); |
4756 | + free(buf); |
4757 | + } |
4758 | + glDeleteShader(shader); |
4759 | + shader = 0; |
4760 | + } |
4761 | + } |
4762 | + } else { |
4763 | + printf("Error, during shader creation: %i\n", glGetError()); |
4764 | + } |
4765 | + |
4766 | + return shader; |
4767 | + } |
4768 | + |
4769 | + static GLuint create_program(const char* pVertexSource, const char* pFragmentSource) |
4770 | + { |
4771 | + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); |
4772 | + if (!vertexShader) { |
4773 | + printf("vertex shader not compiled\n"); |
4774 | + return 0; |
4775 | + } |
4776 | + |
4777 | + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); |
4778 | + if (!pixelShader) { |
4779 | + printf("frag shader not compiled\n"); |
4780 | + return 0; |
4781 | + } |
4782 | + |
4783 | + GLuint program = glCreateProgram(); |
4784 | + if (program) { |
4785 | + glAttachShader(program, vertexShader); |
4786 | + glAttachShader(program, pixelShader); |
4787 | + glLinkProgram(program); |
4788 | + GLint linkStatus = GL_FALSE; |
4789 | + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); |
4790 | + |
4791 | + if (linkStatus != GL_TRUE) { |
4792 | + GLint bufLength = 0; |
4793 | + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); |
4794 | + if (bufLength) { |
4795 | + char* buf = (char*) malloc(bufLength); |
4796 | + if (buf) { |
4797 | + glGetProgramInfoLog(program, bufLength, NULL, buf); |
4798 | + fprintf(stderr, "Could not link program:\n%s\n", buf); |
4799 | + free(buf); |
4800 | + } |
4801 | + } |
4802 | + glDeleteProgram(program); |
4803 | + program = 0; |
4804 | + } |
4805 | + } |
4806 | + |
4807 | + return program; |
4808 | + } |
4809 | + |
4810 | + RenderData() : program_object(create_program(vertex_shader(), fragment_shader())) |
4811 | + { |
4812 | + position_loc = glGetAttribLocation(program_object, "a_position"); |
4813 | + tex_coord_loc = glGetAttribLocation(program_object, "a_texCoord"); |
4814 | + sampler_loc = glGetUniformLocation(program_object, "s_texture"); |
4815 | + matrix_loc = glGetUniformLocation(program_object, "m_texMatrix"); |
4816 | + } |
4817 | + |
4818 | + // Handle to a program object |
4819 | + GLuint program_object; |
4820 | + // Attribute locations |
4821 | + GLint position_loc; |
4822 | + GLint tex_coord_loc; |
4823 | + // Sampler location |
4824 | + GLint sampler_loc; |
4825 | + // Matrix location |
4826 | + GLint matrix_loc; |
4827 | +}; |
4828 | + |
4829 | +static int setup_video_texture(ClientWithSurface *cs, GLuint *preview_texture_id) |
4830 | +{ |
4831 | + assert(cs != NULL); |
4832 | + assert(preview_texture_id != NULL); |
4833 | + |
4834 | + sf_surface_make_current(cs->surface); |
4835 | + |
4836 | + glGenTextures(1, preview_texture_id); |
4837 | + glClearColor(0, 0, 0, 0); |
4838 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
4839 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
4840 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
4841 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
4842 | + |
4843 | + android_media_set_preview_texture(player, *preview_texture_id); |
4844 | + |
4845 | + return 0; |
4846 | +} |
4847 | + |
4848 | +static void print_gl_error(unsigned int line) |
4849 | +{ |
4850 | + GLint error = glGetError(); |
4851 | + printf("GL error: %#04x (line: %d)\n", error, line); |
4852 | +} |
4853 | + |
4854 | +static int update_gl_buffer(RenderData *render_data, EGLDisplay *disp, EGLSurface *surface) |
4855 | +{ |
4856 | + assert(disp != NULL); |
4857 | + assert(surface != NULL); |
4858 | + |
4859 | + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; |
4860 | + |
4861 | + const GLfloat textureCoordinates[] = { |
4862 | + 1.0f, 1.0f, |
4863 | + 0.0f, 1.0f, |
4864 | + 0.0f, 0.0f, |
4865 | + 1.0f, 0.0f |
4866 | + }; |
4867 | + |
4868 | + calculate_position_coordinates(); |
4869 | + |
4870 | + glClear(GL_COLOR_BUFFER_BIT); |
4871 | + // Use the program object |
4872 | + glUseProgram(render_data->program_object); |
4873 | + // Enable attributes |
4874 | + glEnableVertexAttribArray(render_data->position_loc); |
4875 | + glEnableVertexAttribArray(render_data->tex_coord_loc); |
4876 | + // Load the vertex position |
4877 | + glVertexAttribPointer(render_data->position_loc, |
4878 | + 2, |
4879 | + GL_FLOAT, |
4880 | + GL_FALSE, |
4881 | + 0, |
4882 | + positionCoordinates); |
4883 | + // Load the texture coordinate |
4884 | + glVertexAttribPointer(render_data->tex_coord_loc, |
4885 | + 2, |
4886 | + GL_FLOAT, |
4887 | + GL_FALSE, |
4888 | + 0, |
4889 | + textureCoordinates); |
4890 | + |
4891 | + GLfloat matrix[16]; |
4892 | + android_media_surface_texture_get_transformation_matrix(player, matrix); |
4893 | + |
4894 | + glUniformMatrix4fv(render_data->matrix_loc, 1, GL_FALSE, matrix); |
4895 | + |
4896 | + glActiveTexture(GL_TEXTURE0); |
4897 | + // Set the sampler texture unit to 0 |
4898 | + glUniform1i(render_data->sampler_loc, 0); |
4899 | + glUniform1i(render_data->matrix_loc, 0); |
4900 | + android_media_update_surface_texture(player); |
4901 | + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
4902 | + //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); |
4903 | + glDisableVertexAttribArray(render_data->position_loc); |
4904 | + glDisableVertexAttribArray(render_data->tex_coord_loc); |
4905 | + |
4906 | + eglSwapBuffers(*disp, *surface); |
4907 | + |
4908 | + return 0; |
4909 | +} |
4910 | + |
4911 | +void set_video_size_cb(int height, int width, void *context) |
4912 | +{ |
4913 | + printf("Video height: %d, width: %d\n", height, width); |
4914 | + printf("Video dest height: %f, width: %f\n", DestHeight, DestWidth); |
4915 | + |
4916 | + Height = height; |
4917 | + Width = width; |
4918 | +} |
4919 | + |
4920 | +int main(int argc, char **argv) |
4921 | +{ |
4922 | + if (argc < 2) { |
4923 | + printf("Usage: direct_media_test <video_to_play>\n"); |
4924 | + return EXIT_FAILURE; |
4925 | + } |
4926 | + |
4927 | + player = android_media_new_player(); |
4928 | + if (player == NULL) { |
4929 | + printf("Problem creating new media player.\n"); |
4930 | + return EXIT_FAILURE; |
4931 | + } |
4932 | + |
4933 | + // Set player event cb for when the video size is known: |
4934 | + android_media_set_video_size_cb(player, set_video_size_cb, NULL); |
4935 | + |
4936 | + printf("Setting data source to: %s.\n", argv[1]); |
4937 | + |
4938 | + if (android_media_set_data_source(player, argv[1]) != OK) { |
4939 | + printf("Failed to set data source: %s\n", argv[1]); |
4940 | + return EXIT_FAILURE; |
4941 | + } |
4942 | + |
4943 | + WindowRenderer renderer(DestWidth, DestHeight); |
4944 | + |
4945 | + printf("Creating EGL surface.\n"); |
4946 | + ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */); |
4947 | + if (!cs.surface) { |
4948 | + printf("Problem acquiring surface for preview"); |
4949 | + return EXIT_FAILURE; |
4950 | + } |
4951 | + |
4952 | + printf("Creating GL texture.\n"); |
4953 | + GLuint preview_texture_id; |
4954 | + EGLDisplay disp = sf_client_get_egl_display(cs.client); |
4955 | + EGLSurface surface = sf_surface_get_egl_surface(cs.surface); |
4956 | + |
4957 | + sf_surface_make_current(cs.surface); |
4958 | + if (setup_video_texture(&cs, &preview_texture_id) != OK) { |
4959 | + printf("Problem setting up GL texture for video surface.\n"); |
4960 | + return EXIT_FAILURE; |
4961 | + } |
4962 | + |
4963 | + RenderData render_data; |
4964 | + |
4965 | + printf("Starting video playback.\n"); |
4966 | + android_media_play(player); |
4967 | + |
4968 | + printf("Updating gl buffer continuously...\n"); |
4969 | + while (android_media_is_playing(player)) { |
4970 | + update_gl_buffer(&render_data, &disp, &surface); |
4971 | + } |
4972 | + |
4973 | + android_media_stop(player); |
4974 | + |
4975 | + return EXIT_SUCCESS; |
4976 | +} |
4977 | |
4978 | === added file 'android/compat/media/direct_media_test.h' |
4979 | --- android/compat/media/direct_media_test.h 1970-01-01 00:00:00 +0000 |
4980 | +++ android/compat/media/direct_media_test.h 2016-01-11 14:31:46 +0000 |
4981 | @@ -0,0 +1,58 @@ |
4982 | +/* |
4983 | + * Copyright (C) 2013 Canonical Ltd |
4984 | + * |
4985 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
4986 | + * you may not use this file except in compliance with the License. |
4987 | + * You may obtain a copy of the License at |
4988 | + * |
4989 | + * http://www.apache.org/licenses/LICENSE-2.0 |
4990 | + * |
4991 | + * Unless required by applicable law or agreed to in writing, software |
4992 | + * distributed under the License is distributed on an "AS IS" BASIS, |
4993 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4994 | + * See the License for the specific language governing permissions and |
4995 | + * limitations under the License. |
4996 | + * |
4997 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> |
4998 | + */ |
4999 | + |
5000 | +#ifndef DIRECT_MEDIA_TEST_H_ |
FAILED: Continuous integration, rev:317 /code.launchpad .net/~morphis/ platform- api/add- hybris- compat- layer/+ merge/281987/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// jenkins. qa.ubuntu. com/job/ platform- api-ci/ 455/ jenkins. qa.ubuntu. com/job/ platform- api-vivid- amd64-ci/ 68/console jenkins. qa.ubuntu. com/job/ platform- api-vivid- armhf-ci/ 68/console jenkins. qa.ubuntu. com/job/ platform- api-vivid- i386-ci/ 68/console
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/platform- api-ci/ 455/rebuild
http://