Commit | Line | Data |
---|---|---|
4395b8c4 RSA |
1 | Subject: Collected Debian patches for libhybris |
2 | Author: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
3 | ||
4 | The libhybris package is maintained in Git rather than maintaining | |
5 | patches as separate files, and separating the patches doesn't seem to | |
6 | be worth the effort. They are therefore all included in this single | |
7 | Debian patch. | |
8 | ||
9 | For full commit history and separated commits, see the packaging Git | |
10 | repository. | |
11 | --- /dev/null | |
12 | +++ libhybris-0.1.0+git20131207+e452e83/compat/Android.common.mk | |
13 | @@ -0,0 +1,10 @@ | |
14 | +# define ANDROID_VERSION MAJOR, MINOR and PATCH | |
15 | + | |
16 | +ANDROID_VERSION_MAJOR := $(word 1, $(subst ., , $(PLATFORM_VERSION))) | |
17 | +ANDROID_VERSION_MINOR := $(word 2, $(subst ., , $(PLATFORM_VERSION))) | |
18 | +ANDROID_VERSION_PATCH := $(word 3, $(subst ., , $(PLATFORM_VERSION))) | |
19 | + | |
20 | +LOCAL_CFLAGS += \ | |
21 | + -DANDROID_VERSION_MAJOR=$(ANDROID_VERSION_MAJOR) \ | |
22 | + -DANDROID_VERSION_MINOR=$(ANDROID_VERSION_MINOR) \ | |
23 | + -DANDROID_VERSION_PATCH=$(ANDROID_VERSION_PATCH) | |
24 | --- libhybris-0.1.0+git20131207+e452e83.orig/compat/camera/Android.mk | |
25 | +++ libhybris-0.1.0+git20131207+e452e83/compat/camera/Android.mk | |
26 | @@ -1,5 +1,6 @@ | |
27 | LOCAL_PATH:= $(call my-dir) | |
28 | include $(CLEAR_VARS) | |
29 | +include $(LOCAL_PATH)/../Android.common.mk | |
30 | ||
31 | HYBRIS_PATH := $(LOCAL_PATH)/../../hybris | |
32 | ||
33 | --- libhybris-0.1.0+git20131207+e452e83.orig/compat/camera/camera_compatibility_layer.cpp | |
34 | +++ libhybris-0.1.0+git20131207+e452e83/compat/camera/camera_compatibility_layer.cpp | |
35 | @@ -27,17 +27,25 @@ | |
36 | #include <binder/ProcessState.h> | |
37 | #include <camera/Camera.h> | |
38 | #include <camera/CameraParameters.h> | |
39 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
40 | #include <gui/SurfaceTexture.h> | |
41 | +#else | |
42 | +#include <gui/GLConsumer.h> | |
43 | +#endif | |
44 | #include <ui/GraphicBuffer.h> | |
45 | ||
46 | +#include <GLES2/gl2.h> | |
47 | +#include <GLES2/gl2ext.h> | |
48 | + | |
49 | #undef LOG_TAG | |
50 | #define LOG_TAG "CameraCompatibilityLayer" | |
51 | #include <utils/KeyedVector.h> | |
52 | #include <utils/Log.h> | |
53 | +#include <utils/String16.h> | |
54 | ||
55 | #define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) | |
56 | ||
57 | -// From android::SurfaceTexture::FrameAvailableListener | |
58 | +// From android::GLConsumer::FrameAvailableListener | |
59 | void CameraControl::onFrameAvailable() | |
60 | { | |
61 | REPORT_FUNCTION(); | |
62 | @@ -170,7 +178,11 @@ CameraControl* android_camera_connect_to | |
63 | ||
64 | CameraControl* cc = new CameraControl(); | |
65 | cc->listener = listener; | |
66 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=3 | |
67 | + cc->camera = android::Camera::connect(camera_id, android::String16("hybris"), android::Camera::USE_CALLING_UID); | |
68 | +#else | |
69 | cc->camera = android::Camera::connect(camera_id); | |
70 | +#endif | |
71 | ||
72 | if (cc->camera == NULL) | |
73 | return NULL; | |
74 | @@ -511,30 +523,57 @@ void android_camera_set_preview_texture( | |
75 | assert(control); | |
76 | ||
77 | static const bool allow_synchronous_mode = false; | |
78 | + static const bool is_controlled_by_app = true; | |
79 | ||
80 | android::sp<android::NativeBufferAlloc> native_alloc( | |
81 | new android::NativeBufferAlloc() | |
82 | ); | |
83 | ||
84 | android::sp<android::BufferQueue> buffer_queue( | |
85 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
86 | new android::BufferQueue(false, NULL, native_alloc) | |
87 | +#else | |
88 | + new android::BufferQueue(NULL, native_alloc) | |
89 | +#endif | |
90 | ); | |
91 | ||
92 | if (control->preview_texture == NULL) { | |
93 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
94 | control->preview_texture = android::sp<android::SurfaceTexture>( | |
95 | new android::SurfaceTexture( | |
96 | +#else | |
97 | + control->preview_texture = android::sp<android::GLConsumer>( | |
98 | + new android::GLConsumer( | |
99 | +#endif | |
100 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
101 | texture_id, | |
102 | allow_synchronous_mode, | |
103 | GL_TEXTURE_EXTERNAL_OES, | |
104 | true, | |
105 | buffer_queue)); | |
106 | +#else | |
107 | + buffer_queue, | |
108 | + texture_id, | |
109 | + GL_TEXTURE_EXTERNAL_OES, | |
110 | + true, | |
111 | + is_controlled_by_app)); | |
112 | +#endif | |
113 | } | |
114 | ||
115 | control->preview_texture->setFrameAvailableListener( | |
116 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
117 | android::sp<android::SurfaceTexture::FrameAvailableListener>(control)); | |
118 | +#else | |
119 | + android::sp<android::GLConsumer::FrameAvailableListener>(control)); | |
120 | +#endif | |
121 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
122 | control->camera->setPreviewTexture(control->preview_texture->getBufferQueue()); | |
123 | +#else | |
124 | + control->camera->setPreviewTarget(buffer_queue); | |
125 | +#endif | |
126 | } | |
127 | ||
128 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
129 | void android_camera_set_preview_surface(CameraControl* control, SfSurface* surface) | |
130 | { | |
131 | REPORT_FUNCTION(); | |
132 | @@ -544,6 +583,7 @@ void android_camera_set_preview_surface( | |
133 | android::Mutex::Autolock al(control->guard); | |
134 | control->camera->setPreviewDisplay(surface->surface); | |
135 | } | |
136 | +#endif | |
137 | ||
138 | void android_camera_start_preview(CameraControl* control) | |
139 | { | |
140 | --- libhybris-0.1.0+git20131207+e452e83.orig/compat/input/Android.mk | |
141 | +++ libhybris-0.1.0+git20131207+e452e83/compat/input/Android.mk | |
142 | @@ -18,6 +18,11 @@ LOCAL_SHARED_LIBRARIES := \ | |
143 | libgui \ | |
144 | libandroidfw | |
145 | ||
146 | +HAS_LIBINPUTSERVICE := $(shell test $(ANDROID_VERSION_MAJOR) -eq 4 -a $(ANDROID_VERSION_MINOR) -gt 2 && echo true) | |
147 | +ifeq ($(HAS_LIBINPUTSERVICE),true) | |
148 | +LOCAL_SHARED_LIBRARIES += libinputservice | |
149 | +endif | |
150 | + | |
151 | LOCAL_C_INCLUDES := \ | |
152 | $(HYBRIS_PATH)/include \ | |
153 | external/skia/include/core \ | |
154 | --- /dev/null | |
155 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/Android.mk | |
156 | @@ -0,0 +1,109 @@ | |
157 | +LOCAL_PATH:= $(call my-dir) | |
158 | +include $(CLEAR_VARS) | |
159 | +include $(LOCAL_PATH)/../Android.common.mk | |
160 | + | |
161 | +HYBRIS_PATH := $(LOCAL_PATH)/../../hybris | |
162 | + | |
163 | +LOCAL_CFLAGS += -std=gnu++0x | |
164 | + | |
165 | +LOCAL_SRC_FILES:= \ | |
166 | + media_compatibility_layer.cpp \ | |
167 | + media_codec_layer.cpp \ | |
168 | + media_codec_list.cpp \ | |
169 | + media_format_layer.cpp \ | |
170 | + surface_texture_client_hybris.cpp \ | |
171 | + recorder_compatibility_layer.cpp | |
172 | + | |
173 | +LOCAL_MODULE:= libmedia_compat_layer | |
174 | +LOCAL_MODULE_TAGS := optional | |
175 | + | |
176 | +LOCAL_SHARED_LIBRARIES := \ | |
177 | + libcutils \ | |
178 | + libcamera_client \ | |
179 | + libutils \ | |
180 | + libbinder \ | |
181 | + libhardware \ | |
182 | + libui \ | |
183 | + libgui \ | |
184 | + libstagefright \ | |
185 | + libstagefright_foundation \ | |
186 | + libEGL \ | |
187 | + libGLESv2 \ | |
188 | + libmedia | |
189 | + | |
190 | +LOCAL_C_INCLUDES := \ | |
191 | + $(HYBRIS_PATH)/include \ | |
192 | + frameworks/base/media/libstagefright/include \ | |
193 | + frameworks/base/include/media/stagefright \ | |
194 | + frameworks/base/include/media | |
195 | + | |
196 | +include $(BUILD_SHARED_LIBRARY) | |
197 | + | |
198 | +include $(CLEAR_VARS) | |
199 | +include $(LOCAL_PATH)/../Android.common.mk | |
200 | + | |
201 | +LOCAL_SRC_FILES:= \ | |
202 | + direct_media_test.cpp | |
203 | + | |
204 | +LOCAL_MODULE:= direct_media_test | |
205 | +LOCAL_MODULE_TAGS := optional | |
206 | + | |
207 | +LOCAL_C_INCLUDES := \ | |
208 | + $(HYBRIS_PATH)/include \ | |
209 | + bionic \ | |
210 | + bionic/libstdc++/include \ | |
211 | + external/gtest/include \ | |
212 | + external/stlport/stlport \ | |
213 | + external/skia/include/core \ | |
214 | + frameworks/base/include | |
215 | + | |
216 | +LOCAL_SHARED_LIBRARIES := \ | |
217 | + libis_compat_layer \ | |
218 | + libsf_compat_layer \ | |
219 | + libmedia_compat_layer \ | |
220 | + libcutils \ | |
221 | + libutils \ | |
222 | + libbinder \ | |
223 | + libhardware \ | |
224 | + libui \ | |
225 | + libgui \ | |
226 | + libEGL \ | |
227 | + libGLESv2 | |
228 | + | |
229 | +include $(BUILD_EXECUTABLE) | |
230 | + | |
231 | +include $(CLEAR_VARS) | |
232 | +include $(LOCAL_PATH)/../Android.common.mk | |
233 | + | |
234 | +LOCAL_CFLAGS += -Wno-multichar -D SIMPLE_PLAYER -std=gnu++0x | |
235 | + | |
236 | +LOCAL_SRC_FILES:= \ | |
237 | + media_codec_layer.cpp \ | |
238 | + media_codec_list.cpp \ | |
239 | + media_format_layer.cpp \ | |
240 | + codec.cpp \ | |
241 | + SimplePlayer.cpp | |
242 | + | |
243 | +LOCAL_SHARED_LIBRARIES := \ | |
244 | + libstagefright \ | |
245 | + libstagefright_foundation \ | |
246 | + liblog \ | |
247 | + libutils \ | |
248 | + libbinder \ | |
249 | + libmedia \ | |
250 | + libgui \ | |
251 | + libcutils \ | |
252 | + libui | |
253 | + | |
254 | +LOCAL_C_INCLUDES:= \ | |
255 | + $(HYBRIS_PATH)/include \ | |
256 | + frameworks/av/media/libstagefright \ | |
257 | + frameworks/native/include/media/openmax \ | |
258 | + frameworks/base/media/libstagefright/include \ | |
259 | + frameworks/base/include/media/stagefright \ | |
260 | + frameworks/base/include/media | |
261 | + | |
262 | +LOCAL_MODULE:= codec | |
263 | +LOCAL_MODULE_TAGS := optional | |
264 | + | |
265 | +include $(BUILD_EXECUTABLE) | |
266 | --- /dev/null | |
267 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/SimplePlayer.cpp | |
268 | @@ -0,0 +1,777 @@ | |
269 | +/* | |
270 | + * Copyright (C) 2012 The Android Open Source Project | |
271 | + * | |
272 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
273 | + * you may not use this file except in compliance with the License. | |
274 | + * You may obtain a copy of the License at | |
275 | + * | |
276 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
277 | + * | |
278 | + * Unless required by applicable law or agreed to in writing, software | |
279 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
280 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
281 | + * See the License for the specific language governing permissions and | |
282 | + * limitations under the License. | |
283 | + */ | |
284 | + | |
285 | +//#define LOG_NDEBUG 0 | |
286 | +#define LOG_TAG "SimplePlayer" | |
287 | +#include <utils/Log.h> | |
288 | + | |
289 | +#include "SimplePlayer.h" | |
290 | + | |
291 | +#include <gui/Surface.h> | |
292 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
293 | +#include <gui/SurfaceTextureClient.h> | |
294 | +#endif | |
295 | +#include <media/AudioTrack.h> | |
296 | +#include <media/ICrypto.h> | |
297 | +#include <media/stagefright/foundation/ABuffer.h> | |
298 | +#include <media/stagefright/foundation/ADebug.h> | |
299 | +#include <media/stagefright/foundation/AMessage.h> | |
300 | +#include <media/stagefright/MediaCodec.h> | |
301 | +#include <media/stagefright/MediaErrors.h> | |
302 | +#include <media/stagefright/NativeWindowWrapper.h> | |
303 | +#include <media/stagefright/NuMediaExtractor.h> | |
304 | + | |
305 | +#define USE_MEDIA_CODEC_LAYER | |
306 | + | |
307 | +namespace android { | |
308 | + | |
309 | +SimplePlayer::SimplePlayer() | |
310 | + : mState(UNINITIALIZED), | |
311 | + mDoMoreStuffGeneration(0), | |
312 | + mStartTimeRealUs(-1ll) { | |
313 | +} | |
314 | + | |
315 | +SimplePlayer::~SimplePlayer() { | |
316 | +} | |
317 | + | |
318 | +// static | |
319 | +status_t PostAndAwaitResponse( | |
320 | + const sp<AMessage> &msg, sp<AMessage> *response) { | |
321 | + status_t err = msg->postAndAwaitResponse(response); | |
322 | + printf("%s\n", __PRETTY_FUNCTION__); | |
323 | + | |
324 | + if (err != OK) { | |
325 | + return err; | |
326 | + } | |
327 | + | |
328 | + if (!(*response)->findInt32("err", &err)) { | |
329 | + err = OK; | |
330 | + } | |
331 | + | |
332 | + return err; | |
333 | +} | |
334 | +status_t SimplePlayer::setDataSource(const char *path) { | |
335 | + sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); | |
336 | + msg->setString("path", path); | |
337 | + sp<AMessage> response; | |
338 | + return PostAndAwaitResponse(msg, &response); | |
339 | +} | |
340 | + | |
341 | +status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) { | |
342 | + sp<AMessage> msg = new AMessage(kWhatSetSurface, id()); | |
343 | + | |
344 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
345 | + sp<SurfaceTextureClient> surfaceTextureClient; | |
346 | + if (surfaceTexture != NULL) { | |
347 | + surfaceTextureClient = new SurfaceTextureClient(surfaceTexture); | |
348 | + } | |
349 | +#else | |
350 | + sp<Surface> surfaceTextureClient; | |
351 | + if (surfaceTexture != NULL) { | |
352 | + surfaceTextureClient = new Surface(surfaceTexture); | |
353 | + } | |
354 | +#endif | |
355 | + | |
356 | + msg->setObject( | |
357 | + "native-window", new NativeWindowWrapper(surfaceTextureClient)); | |
358 | + | |
359 | + sp<AMessage> response; | |
360 | + return PostAndAwaitResponse(msg, &response); | |
361 | +} | |
362 | + | |
363 | +status_t SimplePlayer::prepare() { | |
364 | + sp<AMessage> msg = new AMessage(kWhatPrepare, id()); | |
365 | + sp<AMessage> response; | |
366 | + return PostAndAwaitResponse(msg, &response); | |
367 | +} | |
368 | + | |
369 | +status_t SimplePlayer::start() { | |
370 | + printf("%s\n", __PRETTY_FUNCTION__); | |
371 | + sp<AMessage> msg = new AMessage(kWhatStart, id()); | |
372 | + sp<AMessage> response; | |
373 | + return PostAndAwaitResponse(msg, &response); | |
374 | +} | |
375 | + | |
376 | +status_t SimplePlayer::stop() { | |
377 | + sp<AMessage> msg = new AMessage(kWhatStop, id()); | |
378 | + sp<AMessage> response; | |
379 | + return PostAndAwaitResponse(msg, &response); | |
380 | +} | |
381 | + | |
382 | +status_t SimplePlayer::reset() { | |
383 | + sp<AMessage> msg = new AMessage(kWhatReset, id()); | |
384 | + sp<AMessage> response; | |
385 | + return PostAndAwaitResponse(msg, &response); | |
386 | +} | |
387 | + | |
388 | +void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) { | |
389 | + switch (msg->what()) { | |
390 | + case kWhatSetDataSource: | |
391 | + { | |
392 | + status_t err; | |
393 | + if (mState != UNINITIALIZED) { | |
394 | + err = INVALID_OPERATION; | |
395 | + } else { | |
396 | + CHECK(msg->findString("path", &mPath)); | |
397 | + mState = UNPREPARED; | |
398 | + } | |
399 | + | |
400 | + uint32_t replyID; | |
401 | + CHECK(msg->senderAwaitsResponse(&replyID)); | |
402 | + | |
403 | + sp<AMessage> response = new AMessage; | |
404 | + response->setInt32("err", err); | |
405 | + response->postReply(replyID); | |
406 | + break; | |
407 | + } | |
408 | + | |
409 | + case kWhatSetSurface: | |
410 | + { | |
411 | + status_t err; | |
412 | + if (mState != UNPREPARED) { | |
413 | + err = INVALID_OPERATION; | |
414 | + } else { | |
415 | + sp<RefBase> obj; | |
416 | + CHECK(msg->findObject("native-window", &obj)); | |
417 | + | |
418 | + mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); | |
419 | + | |
420 | + err = OK; | |
421 | + } | |
422 | + | |
423 | + uint32_t replyID; | |
424 | + CHECK(msg->senderAwaitsResponse(&replyID)); | |
425 | + | |
426 | + sp<AMessage> response = new AMessage; | |
427 | + response->setInt32("err", err); | |
428 | + response->postReply(replyID); | |
429 | + break; | |
430 | + } | |
431 | + | |
432 | + case kWhatPrepare: | |
433 | + { | |
434 | + status_t err; | |
435 | + if (mState != UNPREPARED) { | |
436 | + err = INVALID_OPERATION; | |
437 | + } else { | |
438 | + err = onPrepare(); | |
439 | + | |
440 | + if (err == OK) { | |
441 | + mState = STOPPED; | |
442 | + } | |
443 | + } | |
444 | + | |
445 | + uint32_t replyID; | |
446 | + CHECK(msg->senderAwaitsResponse(&replyID)); | |
447 | + | |
448 | + sp<AMessage> response = new AMessage; | |
449 | + response->setInt32("err", err); | |
450 | + response->postReply(replyID); | |
451 | + break; | |
452 | + } | |
453 | + | |
454 | + case kWhatStart: | |
455 | + { | |
456 | + status_t err = OK; | |
457 | + | |
458 | + if (mState == UNPREPARED) { | |
459 | + err = onPrepare(); | |
460 | + | |
461 | + if (err == OK) { | |
462 | + mState = STOPPED; | |
463 | + } | |
464 | + } | |
465 | + | |
466 | + if (err == OK) { | |
467 | + if (mState != STOPPED) { | |
468 | + err = INVALID_OPERATION; | |
469 | + } else { | |
470 | + err = onStart(); | |
471 | + | |
472 | + if (err == OK) { | |
473 | + mState = STARTED; | |
474 | + } | |
475 | + } | |
476 | + } | |
477 | + | |
478 | + uint32_t replyID; | |
479 | + CHECK(msg->senderAwaitsResponse(&replyID)); | |
480 | + | |
481 | + sp<AMessage> response = new AMessage; | |
482 | + response->setInt32("err", err); | |
483 | + response->postReply(replyID); | |
484 | + break; | |
485 | + } | |
486 | + | |
487 | + case kWhatStop: | |
488 | + { | |
489 | + status_t err; | |
490 | + | |
491 | + if (mState != STARTED) { | |
492 | + err = INVALID_OPERATION; | |
493 | + } else { | |
494 | + err = onStop(); | |
495 | + | |
496 | + if (err == OK) { | |
497 | + mState = STOPPED; | |
498 | + } | |
499 | + } | |
500 | + | |
501 | + uint32_t replyID; | |
502 | + CHECK(msg->senderAwaitsResponse(&replyID)); | |
503 | + | |
504 | + sp<AMessage> response = new AMessage; | |
505 | + response->setInt32("err", err); | |
506 | + response->postReply(replyID); | |
507 | + break; | |
508 | + } | |
509 | + | |
510 | + case kWhatReset: | |
511 | + { | |
512 | + status_t err = OK; | |
513 | + | |
514 | + if (mState == STARTED) { | |
515 | + CHECK_EQ(onStop(), (status_t)OK); | |
516 | + mState = STOPPED; | |
517 | + } | |
518 | + | |
519 | + if (mState == STOPPED) { | |
520 | + err = onReset(); | |
521 | + mState = UNINITIALIZED; | |
522 | + } | |
523 | + | |
524 | + uint32_t replyID; | |
525 | + CHECK(msg->senderAwaitsResponse(&replyID)); | |
526 | + | |
527 | + sp<AMessage> response = new AMessage; | |
528 | + response->setInt32("err", err); | |
529 | + response->postReply(replyID); | |
530 | + break; | |
531 | + } | |
532 | + | |
533 | + case kWhatDoMoreStuff: | |
534 | + { | |
535 | + int32_t generation; | |
536 | + CHECK(msg->findInt32("generation", &generation)); | |
537 | + | |
538 | + if (generation != mDoMoreStuffGeneration) { | |
539 | + break; | |
540 | + } | |
541 | + | |
542 | + status_t err = onDoMoreStuff(); | |
543 | + | |
544 | + if (err == OK) { | |
545 | + msg->post(10000ll); | |
546 | + } | |
547 | + break; | |
548 | + } | |
549 | + | |
550 | + default: | |
551 | + TRESPASS(); | |
552 | + } | |
553 | +} | |
554 | + | |
555 | +status_t SimplePlayer::onPrepare() { | |
556 | + CHECK_EQ(mState, UNPREPARED); | |
557 | + printf("%s\n", __PRETTY_FUNCTION__); | |
558 | + | |
559 | + mExtractor = new NuMediaExtractor; | |
560 | + | |
561 | + status_t err = mExtractor->setDataSource(mPath.c_str()); | |
562 | + | |
563 | + if (err != OK) { | |
564 | + mExtractor.clear(); | |
565 | + return err; | |
566 | + } | |
567 | + | |
568 | + if (mCodecLooper == NULL) { | |
569 | + mCodecLooper = new ALooper; | |
570 | + mCodecLooper->start(); | |
571 | + } | |
572 | + | |
573 | + bool haveAudio = false; | |
574 | + bool haveVideo = false; | |
575 | + for (size_t i = 0; i < mExtractor->countTracks(); ++i) { | |
576 | + sp<AMessage> format; | |
577 | + status_t err = mExtractor->getTrackFormat(i, &format); | |
578 | + CHECK_EQ(err, (status_t)OK); | |
579 | + | |
580 | + AString mime; | |
581 | + int32_t width = 0, height = 0, maxInputSize = 0; | |
582 | + int64_t durationUs = 0; | |
583 | + sp<ABuffer> csd0, csd1; | |
584 | +#ifdef USE_MEDIA_CODEC_LAYER | |
585 | + MediaFormat mformat; | |
586 | +#endif | |
587 | + CHECK(format->findString("mime", &mime)); | |
588 | + | |
589 | + if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) { | |
590 | + //haveAudio = true; | |
591 | + printf("*** Have audio but skipping it!\n"); | |
592 | + continue; | |
593 | + } else if (!haveVideo && !strncasecmp(mime.c_str(), "video/", 6)) { | |
594 | + haveVideo = true; | |
595 | + CHECK(format->findInt32("width", &width)); | |
596 | + CHECK(format->findInt32("height", &height)); | |
597 | + CHECK(format->findInt64("durationUs", &durationUs)); | |
598 | + CHECK(format->findInt32("max-input-size", &maxInputSize)); | |
599 | + CHECK(format->findBuffer("csd-0", &csd0)); | |
600 | + CHECK(format->findBuffer("csd-1", &csd1)); | |
601 | +#ifdef USE_MEDIA_CODEC_LAYER | |
602 | + mformat = media_format_create_video_format(mime.c_str(), width, height, durationUs, maxInputSize); | |
603 | + media_format_set_byte_buffer(mformat, "csd-0", csd0->data(), csd0->size()); | |
604 | + media_format_set_byte_buffer(mformat, "csd-1", csd1->data(), csd1->size()); | |
605 | +#endif | |
606 | + } else { | |
607 | + continue; | |
608 | + } | |
609 | + | |
610 | + err = mExtractor->selectTrack(i); | |
611 | + CHECK_EQ(err, (status_t)OK); | |
612 | + | |
613 | + CodecState *state = | |
614 | + &mStateByTrackIndex.editValueAt( | |
615 | + mStateByTrackIndex.add(i, CodecState())); | |
616 | + | |
617 | + state->mNumFramesWritten = 0; | |
618 | +#ifdef USE_MEDIA_CODEC_LAYER | |
619 | + state->mCodecDelegate = media_codec_create_by_codec_type(mime.c_str()); | |
620 | + state->mCodec = media_codec_get(state->mCodecDelegate); | |
621 | + CHECK(state->mCodecDelegate != NULL); | |
622 | +#else | |
623 | + state->mCodec = MediaCodec::CreateByType( | |
624 | + mCodecLooper, mime.c_str(), false /* encoder */); | |
625 | +#endif | |
626 | + | |
627 | + CHECK(state->mCodec != NULL); | |
628 | + | |
629 | +#ifdef USE_MEDIA_CODEC_LAYER | |
630 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
631 | + err = media_codec_configure(state->mCodecDelegate, mformat, mNativeWindow->getSurfaceTextureClient().get(), 0); | |
632 | +#else | |
633 | + err = media_codec_configure(state->mCodecDelegate, mformat, mNativeWindow->getSurface().get(), 0); | |
634 | +#endif | |
635 | +#else | |
636 | + err = state->mCodec->configure( | |
637 | + format, | |
638 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
639 | + mNativeWindow->getSurfaceTextureClient(), | |
640 | +#else | |
641 | + mNativeWindow->getSurface(), | |
642 | +#endif | |
643 | + NULL /* crypto */, | |
644 | + 0 /* flags */); | |
645 | +#endif | |
646 | + | |
647 | + CHECK_EQ(err, (status_t)OK); | |
648 | + | |
649 | + size_t j = 0; | |
650 | + sp<ABuffer> buffer; | |
651 | + // Place the CSD data into the source buffer | |
652 | + while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) { | |
653 | + state->mCSD.push_back(buffer); | |
654 | + | |
655 | + ++j; | |
656 | + } | |
657 | + } | |
658 | + | |
659 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { | |
660 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); | |
661 | + | |
662 | +#ifdef USE_MEDIA_CODEC_LAYER | |
663 | + status_t err = media_codec_start(state->mCodecDelegate); | |
664 | +#else | |
665 | + status_t err = state->mCodec->start(); | |
666 | +#endif | |
667 | + CHECK_EQ(err, (status_t)OK); | |
668 | + | |
669 | +#ifdef USE_MEDIA_CODEC_LAYER | |
670 | + size_t nInputBuffers = media_codec_get_input_buffers_size(state->mCodecDelegate); | |
671 | + ALOGD("nInputBuffers: %u", nInputBuffers); | |
672 | + for (size_t i=0; i<nInputBuffers; i++) | |
673 | + { | |
674 | + uint8_t *data = media_codec_get_nth_input_buffer(state->mCodecDelegate, i); | |
675 | + CHECK(data != NULL); | |
676 | + size_t size = media_codec_get_nth_input_buffer_capacity(state->mCodecDelegate, i); | |
677 | + ALOGD("input buffer[%d] size: %d", i, size); | |
678 | + sp<ABuffer> buf = new ABuffer(data, size); | |
679 | + state->mBuffers[0].insertAt(new ABuffer(data, size), i); | |
680 | + } | |
681 | +#else | |
682 | + err = state->mCodec->getInputBuffers(&state->mBuffers[0]); | |
683 | + CHECK_EQ(err, (status_t)OK); | |
684 | +#endif | |
685 | + | |
686 | + err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); | |
687 | + CHECK_EQ(err, (status_t)OK); | |
688 | + | |
689 | + for (size_t j = 0; j < state->mCSD.size(); ++j) { | |
690 | + const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j); | |
691 | + | |
692 | + size_t index; | |
693 | +#ifdef USE_MEDIA_CODEC_LAYER | |
694 | + err = media_codec_dequeue_input_buffer(state->mCodecDelegate, &index, -1ll); | |
695 | +#else | |
696 | + err = state->mCodec->dequeueInputBuffer(&index, -1ll); | |
697 | +#endif | |
698 | + CHECK_EQ(err, (status_t)OK); | |
699 | + | |
700 | + const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index); | |
701 | + | |
702 | + CHECK_LE(srcBuffer->size(), dstBuffer->capacity()); | |
703 | + dstBuffer->setRange(0, srcBuffer->size()); | |
704 | + memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size()); | |
705 | + | |
706 | +#ifdef USE_MEDIA_CODEC_LAYER | |
707 | + MediaCodecBufferInfo bufInfo; | |
708 | + bufInfo.index = index; | |
709 | + bufInfo.offset = 0; | |
710 | + bufInfo.size = dstBuffer->size(); | |
711 | + bufInfo.presentation_time_us = 0ll; | |
712 | + bufInfo.flags = MediaCodec::BUFFER_FLAG_CODECCONFIG; | |
713 | + | |
714 | + err = media_codec_queue_input_buffer( | |
715 | + state->mCodecDelegate, | |
716 | + &bufInfo); | |
717 | + | |
718 | +#else | |
719 | + err = state->mCodec->queueInputBuffer( | |
720 | + index, | |
721 | + 0, | |
722 | + dstBuffer->size(), | |
723 | + 0ll, | |
724 | + MediaCodec::BUFFER_FLAG_CODECCONFIG); | |
725 | +#endif | |
726 | + CHECK_EQ(err, (status_t)OK); | |
727 | + } | |
728 | + } | |
729 | + | |
730 | + return OK; | |
731 | +} | |
732 | + | |
733 | +status_t SimplePlayer::onStart() { | |
734 | + CHECK_EQ(mState, STOPPED); | |
735 | + | |
736 | + mStartTimeRealUs = -1ll; | |
737 | + | |
738 | + sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id()); | |
739 | + msg->setInt32("generation", ++mDoMoreStuffGeneration); | |
740 | + msg->post(); | |
741 | + | |
742 | + return OK; | |
743 | +} | |
744 | + | |
745 | +status_t SimplePlayer::onStop() { | |
746 | + CHECK_EQ(mState, STARTED); | |
747 | + | |
748 | + ++mDoMoreStuffGeneration; | |
749 | + | |
750 | + return OK; | |
751 | +} | |
752 | + | |
753 | +status_t SimplePlayer::onReset() { | |
754 | + CHECK_EQ(mState, STOPPED); | |
755 | + | |
756 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { | |
757 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); | |
758 | + | |
759 | + CHECK_EQ(state->mCodec->release(), (status_t)OK); | |
760 | + } | |
761 | + | |
762 | + mStartTimeRealUs = -1ll; | |
763 | + | |
764 | + mStateByTrackIndex.clear(); | |
765 | + mCodecLooper.clear(); | |
766 | + mExtractor.clear(); | |
767 | + mNativeWindow.clear(); | |
768 | + mPath.clear(); | |
769 | + | |
770 | + return OK; | |
771 | +} | |
772 | + | |
773 | +status_t SimplePlayer::onDoMoreStuff() { | |
774 | + ALOGV("onDoMoreStuff"); | |
775 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { | |
776 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); | |
777 | + | |
778 | + status_t err; | |
779 | + do { | |
780 | + size_t index; | |
781 | +#ifdef USE_MEDIA_CODEC_LAYER | |
782 | + err = media_codec_dequeue_input_buffer(state->mCodecDelegate, &index, 0ll); | |
783 | +#else | |
784 | + err = state->mCodec->dequeueInputBuffer(&index); | |
785 | +#endif | |
786 | + | |
787 | + if (err == OK) { | |
788 | + ALOGD("dequeued input buffer on track %d", | |
789 | + mStateByTrackIndex.keyAt(i)); | |
790 | + | |
791 | + state->mAvailInputBufferIndices.push_back(index); | |
792 | + } else { | |
793 | + ALOGD("dequeueInputBuffer on track %d returned %d", | |
794 | + mStateByTrackIndex.keyAt(i), err); | |
795 | + } | |
796 | + } while (err == OK); | |
797 | + | |
798 | + do { | |
799 | +#ifdef USE_MEDIA_CODEC_LAYER | |
800 | + BufferInfo info; | |
801 | + MediaCodecBufferInfo bufInfo; | |
802 | + err = media_codec_dequeue_output_buffer( | |
803 | + state->mCodecDelegate, | |
804 | + &bufInfo, | |
805 | + 0ll); | |
806 | + | |
807 | + info.mIndex = bufInfo.index; | |
808 | + info.mOffset = bufInfo.offset; | |
809 | + info.mSize = bufInfo.size; | |
810 | + info.mPresentationTimeUs = bufInfo.presentation_time_us; | |
811 | + info.mFlags = bufInfo.flags; | |
812 | + | |
813 | +#else | |
814 | + BufferInfo info; | |
815 | + err = state->mCodec->dequeueOutputBuffer( | |
816 | + &info.mIndex, | |
817 | + &info.mOffset, | |
818 | + &info.mSize, | |
819 | + &info.mPresentationTimeUs, | |
820 | + &info.mFlags); | |
821 | +#endif | |
822 | + | |
823 | + if (err == OK) { | |
824 | + ALOGV("dequeued output buffer on track %d", | |
825 | + mStateByTrackIndex.keyAt(i)); | |
826 | + | |
827 | + state->mAvailOutputBufferInfos.push_back(info); | |
828 | + } else if (err == INFO_FORMAT_CHANGED) { | |
829 | + err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state); | |
830 | + CHECK_EQ(err, (status_t)OK); | |
831 | + } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { | |
832 | + err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); | |
833 | + CHECK_EQ(err, (status_t)OK); | |
834 | + } else { | |
835 | + ALOGV("dequeueOutputBuffer on track %d returned %d", | |
836 | + mStateByTrackIndex.keyAt(i), err); | |
837 | + } | |
838 | + } while (err == OK | |
839 | + || err == INFO_FORMAT_CHANGED | |
840 | + || err == INFO_OUTPUT_BUFFERS_CHANGED); | |
841 | + } | |
842 | + | |
843 | + for (;;) { | |
844 | + size_t trackIndex; | |
845 | + status_t err = mExtractor->getSampleTrackIndex(&trackIndex); | |
846 | + | |
847 | + if (err != OK) { | |
848 | + ALOGI("encountered input EOS."); | |
849 | + break; | |
850 | + } else { | |
851 | + CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex); | |
852 | + | |
853 | + if (state->mAvailInputBufferIndices.empty()) { | |
854 | + break; | |
855 | + } | |
856 | + | |
857 | + size_t index = *state->mAvailInputBufferIndices.begin(); | |
858 | + state->mAvailInputBufferIndices.erase( | |
859 | + state->mAvailInputBufferIndices.begin()); | |
860 | + | |
861 | + const sp<ABuffer> &dstBuffer = | |
862 | + state->mBuffers[0].itemAt(index); | |
863 | + | |
864 | + err = mExtractor->readSampleData(dstBuffer); | |
865 | + CHECK_EQ(err, (status_t)OK); | |
866 | + | |
867 | + int64_t timeUs; | |
868 | + CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK); | |
869 | + | |
870 | +#ifdef USE_MEDIA_CODEC_LAYER | |
871 | + MediaCodecBufferInfo bufInfo; | |
872 | + bufInfo.index = index; | |
873 | + bufInfo.offset = dstBuffer->offset(); | |
874 | + bufInfo.size = dstBuffer->size(); | |
875 | + bufInfo.presentation_time_us = timeUs; | |
876 | + bufInfo.flags = 0; | |
877 | + | |
878 | + err = media_codec_queue_input_buffer( | |
879 | + state->mCodecDelegate, | |
880 | + &bufInfo); | |
881 | + | |
882 | +#else | |
883 | + err = state->mCodec->queueInputBuffer( | |
884 | + index, | |
885 | + dstBuffer->offset(), | |
886 | + dstBuffer->size(), | |
887 | + timeUs, | |
888 | + 0); | |
889 | +#endif | |
890 | + CHECK_EQ(err, (status_t)OK); | |
891 | + | |
892 | + ALOGV("enqueued input data on track %d", trackIndex); | |
893 | + | |
894 | + err = mExtractor->advance(); | |
895 | + CHECK_EQ(err, (status_t)OK); | |
896 | + } | |
897 | + } | |
898 | + | |
899 | + int64_t nowUs = ALooper::GetNowUs(); | |
900 | + | |
901 | + if (mStartTimeRealUs < 0ll) { | |
902 | + mStartTimeRealUs = nowUs + 1000000ll; | |
903 | + } | |
904 | + | |
905 | + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { | |
906 | + CodecState *state = &mStateByTrackIndex.editValueAt(i); | |
907 | + | |
908 | + while (!state->mAvailOutputBufferInfos.empty()) { | |
909 | + BufferInfo *info = &*state->mAvailOutputBufferInfos.begin(); | |
910 | + | |
911 | + int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs; | |
912 | + int64_t lateByUs = nowUs - whenRealUs; | |
913 | + | |
914 | + if (lateByUs > -10000ll) { | |
915 | + bool release = true; | |
916 | + | |
917 | + if (lateByUs > 30000ll) { | |
918 | + ALOGI("track %d buffer late by %lld us, dropping.", | |
919 | + mStateByTrackIndex.keyAt(i), lateByUs); | |
920 | + state->mCodec->releaseOutputBuffer(info->mIndex); | |
921 | + } else { | |
922 | + if (state->mAudioTrack != NULL) { | |
923 | + const sp<ABuffer> &srcBuffer = | |
924 | + state->mBuffers[1].itemAt(info->mIndex); | |
925 | + | |
926 | + renderAudio(state, info, srcBuffer); | |
927 | + | |
928 | + if (info->mSize > 0) { | |
929 | + release = false; | |
930 | + } | |
931 | + } | |
932 | + | |
933 | + if (release) { | |
934 | +#ifdef USE_MEDIA_CODEC_LAYER | |
935 | + ALOGD("Rendering output buffer index %d and releasing", info->mIndex); | |
936 | + state->mCodec->renderOutputBufferAndRelease( | |
937 | + info->mIndex); | |
938 | +#else | |
939 | + ALOGD("Releasing output buffer index %d", info->mIndex); | |
940 | + state->mCodec->releaseOutputBuffer(info->mIndex); | |
941 | +#endif | |
942 | + } | |
943 | + } | |
944 | + | |
945 | + if (release) { | |
946 | + state->mAvailOutputBufferInfos.erase( | |
947 | + state->mAvailOutputBufferInfos.begin()); | |
948 | + | |
949 | + info = NULL; | |
950 | + } else { | |
951 | + break; | |
952 | + } | |
953 | + } else { | |
954 | + ALOGV("track %d buffer early by %lld us.", | |
955 | + mStateByTrackIndex.keyAt(i), -lateByUs); | |
956 | + break; | |
957 | + } | |
958 | + } | |
959 | + } | |
960 | + | |
961 | + return OK; | |
962 | +} | |
963 | + | |
964 | +status_t SimplePlayer::onOutputFormatChanged( | |
965 | + size_t trackIndex, CodecState *state) { | |
966 | + sp<AMessage> format; | |
967 | + status_t err = state->mCodec->getOutputFormat(&format); | |
968 | + | |
969 | + if (err != OK) { | |
970 | + return err; | |
971 | + } | |
972 | + | |
973 | + AString mime; | |
974 | + CHECK(format->findString("mime", &mime)); | |
975 | + | |
976 | + if (!strncasecmp(mime.c_str(), "audio/", 6)) { | |
977 | + int32_t channelCount; | |
978 | + int32_t sampleRate; | |
979 | + CHECK(format->findInt32("channel-count", &channelCount)); | |
980 | + CHECK(format->findInt32("sample-rate", &sampleRate)); | |
981 | + | |
982 | + state->mAudioTrack = new AudioTrack( | |
983 | + AUDIO_STREAM_MUSIC, | |
984 | + sampleRate, | |
985 | + AUDIO_FORMAT_PCM_16_BIT, | |
986 | + audio_channel_out_mask_from_count(channelCount), | |
987 | + 0); | |
988 | + | |
989 | + state->mNumFramesWritten = 0; | |
990 | + } | |
991 | + | |
992 | + return OK; | |
993 | +} | |
994 | + | |
995 | +void SimplePlayer::renderAudio( | |
996 | + CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) { | |
997 | + CHECK(state->mAudioTrack != NULL); | |
998 | + | |
999 | + if (state->mAudioTrack->stopped()) { | |
1000 | + state->mAudioTrack->start(); | |
1001 | + } | |
1002 | + | |
1003 | + uint32_t numFramesPlayed; | |
1004 | + CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK); | |
1005 | + | |
1006 | + uint32_t numFramesAvailableToWrite = | |
1007 | + state->mAudioTrack->frameCount() | |
1008 | + - (state->mNumFramesWritten - numFramesPlayed); | |
1009 | + | |
1010 | + size_t numBytesAvailableToWrite = | |
1011 | + numFramesAvailableToWrite * state->mAudioTrack->frameSize(); | |
1012 | + | |
1013 | + size_t copy = info->mSize; | |
1014 | + if (copy > numBytesAvailableToWrite) { | |
1015 | + copy = numBytesAvailableToWrite; | |
1016 | + } | |
1017 | + | |
1018 | + if (copy == 0) { | |
1019 | + return; | |
1020 | + } | |
1021 | + | |
1022 | + int64_t startTimeUs = ALooper::GetNowUs(); | |
1023 | + | |
1024 | + ssize_t nbytes = state->mAudioTrack->write( | |
1025 | + buffer->base() + info->mOffset, copy); | |
1026 | + | |
1027 | + CHECK_EQ(nbytes, (ssize_t)copy); | |
1028 | + | |
1029 | + int64_t delayUs = ALooper::GetNowUs() - startTimeUs; | |
1030 | + | |
1031 | + uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize(); | |
1032 | + | |
1033 | + if (delayUs > 2000ll) { | |
1034 | + ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, " | |
1035 | + "numFramesWritten=%u", | |
1036 | + delayUs, numFramesAvailableToWrite, numFramesWritten); | |
1037 | + } | |
1038 | + | |
1039 | + info->mOffset += nbytes; | |
1040 | + info->mSize -= nbytes; | |
1041 | + | |
1042 | + state->mNumFramesWritten += numFramesWritten; | |
1043 | +} | |
1044 | + | |
1045 | +} // namespace android | |
1046 | --- /dev/null | |
1047 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/SimplePlayer.h | |
1048 | @@ -0,0 +1,120 @@ | |
1049 | +/* | |
1050 | + * Copyright (C) 2012 The Android Open Source Project | |
1051 | + * | |
1052 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
1053 | + * you may not use this file except in compliance with the License. | |
1054 | + * You may obtain a copy of the License at | |
1055 | + * | |
1056 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
1057 | + * | |
1058 | + * Unless required by applicable law or agreed to in writing, software | |
1059 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
1060 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
1061 | + * See the License for the specific language governing permissions and | |
1062 | + * limitations under the License. | |
1063 | + */ | |
1064 | + | |
1065 | +#include <media/stagefright/foundation/AHandler.h> | |
1066 | +#include <media/stagefright/foundation/AString.h> | |
1067 | +#include <utils/KeyedVector.h> | |
1068 | + | |
1069 | +#include <hybris/media/media_codec_layer.h> | |
1070 | + | |
1071 | +namespace android { | |
1072 | + | |
1073 | +struct ABuffer; | |
1074 | +struct ALooper; | |
1075 | +struct AudioTrack; | |
1076 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
1077 | +struct ISurfaceTexture; | |
1078 | +#else | |
1079 | +struct IGraphicBufferProducer; | |
1080 | +#endif | |
1081 | +struct MediaCodec; | |
1082 | +struct NativeWindowWrapper; | |
1083 | +struct NuMediaExtractor; | |
1084 | + | |
1085 | +struct SimplePlayer : public AHandler { | |
1086 | + SimplePlayer(); | |
1087 | + | |
1088 | + status_t setDataSource(const char *path); | |
1089 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
1090 | + status_t setSurface(const sp<ISurfaceTexture> &surfaceTexture); | |
1091 | +#else | |
1092 | + status_t setSurface(const sp<IGraphicBufferProducer> &surfaceTexture); | |
1093 | +#endif | |
1094 | + status_t prepare(); | |
1095 | + status_t start(); | |
1096 | + status_t stop(); | |
1097 | + status_t reset(); | |
1098 | + | |
1099 | +protected: | |
1100 | + virtual ~SimplePlayer(); | |
1101 | + | |
1102 | + virtual void onMessageReceived(const sp<AMessage> &msg); | |
1103 | + | |
1104 | +private: | |
1105 | + enum State { | |
1106 | + UNINITIALIZED, | |
1107 | + UNPREPARED, | |
1108 | + STOPPED, | |
1109 | + STARTED | |
1110 | + }; | |
1111 | + | |
1112 | + enum { | |
1113 | + kWhatSetDataSource, | |
1114 | + kWhatSetSurface, | |
1115 | + kWhatPrepare, | |
1116 | + kWhatStart, | |
1117 | + kWhatStop, | |
1118 | + kWhatReset, | |
1119 | + kWhatDoMoreStuff, | |
1120 | + }; | |
1121 | + | |
1122 | + struct BufferInfo { | |
1123 | + size_t mIndex; | |
1124 | + size_t mOffset; | |
1125 | + size_t mSize; | |
1126 | + int64_t mPresentationTimeUs; | |
1127 | + uint32_t mFlags; | |
1128 | + }; | |
1129 | + | |
1130 | + struct CodecState | |
1131 | + { | |
1132 | + sp<MediaCodec> mCodec; | |
1133 | + MediaCodecDelegate mCodecDelegate; | |
1134 | + Vector<sp<ABuffer> > mCSD; | |
1135 | + Vector<sp<ABuffer> > mBuffers[2]; | |
1136 | + | |
1137 | + List<size_t> mAvailInputBufferIndices; | |
1138 | + List<BufferInfo> mAvailOutputBufferInfos; | |
1139 | + | |
1140 | + sp<AudioTrack> mAudioTrack; | |
1141 | + uint32_t mNumFramesWritten; | |
1142 | + }; | |
1143 | + | |
1144 | + State mState; | |
1145 | + AString mPath; | |
1146 | + sp<NativeWindowWrapper> mNativeWindow; | |
1147 | + | |
1148 | + sp<NuMediaExtractor> mExtractor; | |
1149 | + sp<ALooper> mCodecLooper; | |
1150 | + KeyedVector<size_t, CodecState> mStateByTrackIndex; | |
1151 | + int32_t mDoMoreStuffGeneration; | |
1152 | + | |
1153 | + int64_t mStartTimeRealUs; | |
1154 | + | |
1155 | + status_t onPrepare(); | |
1156 | + status_t onStart(); | |
1157 | + status_t onStop(); | |
1158 | + status_t onReset(); | |
1159 | + status_t onDoMoreStuff(); | |
1160 | + status_t onOutputFormatChanged(size_t trackIndex, CodecState *state); | |
1161 | + | |
1162 | + void renderAudio( | |
1163 | + CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer); | |
1164 | + | |
1165 | + DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer); | |
1166 | +}; | |
1167 | + | |
1168 | +} // namespace android | |
1169 | --- /dev/null | |
1170 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/codec.cpp | |
1171 | @@ -0,0 +1,433 @@ | |
1172 | +/* | |
1173 | + * Copyright (C) 2012 The Android Open Source Project | |
1174 | + * | |
1175 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
1176 | + * you may not use this file except in compliance with the License. | |
1177 | + * You may obtain a copy of the License at | |
1178 | + * | |
1179 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
1180 | + * | |
1181 | + * Unless required by applicable law or agreed to in writing, software | |
1182 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
1183 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
1184 | + * See the License for the specific language governing permissions and | |
1185 | + * limitations under the License. | |
1186 | + */ | |
1187 | + | |
1188 | +#define LOG_NDEBUG 0 | |
1189 | +#define LOG_TAG "codec" | |
1190 | +#include <utils/Log.h> | |
1191 | + | |
1192 | +#include "SimplePlayer.h" | |
1193 | + | |
1194 | +#include <binder/IServiceManager.h> | |
1195 | +#include <binder/ProcessState.h> | |
1196 | +#include <media/ICrypto.h> | |
1197 | +#include <media/IMediaPlayerService.h> | |
1198 | +#include <media/stagefright/foundation/ABuffer.h> | |
1199 | +#include <media/stagefright/foundation/ADebug.h> | |
1200 | +#include <media/stagefright/foundation/ALooper.h> | |
1201 | +#include <media/stagefright/foundation/AMessage.h> | |
1202 | +#include <media/stagefright/foundation/AString.h> | |
1203 | +#include <media/stagefright/DataSource.h> | |
1204 | +#include <media/stagefright/MediaCodec.h> | |
1205 | +#include <media/stagefright/MediaCodecList.h> | |
1206 | +#include <media/stagefright/MediaDefs.h> | |
1207 | +#include <media/stagefright/NuMediaExtractor.h> | |
1208 | +#include <gui/ISurfaceComposer.h> | |
1209 | +#include <gui/SurfaceComposerClient.h> | |
1210 | +#include <ui/DisplayInfo.h> | |
1211 | + | |
1212 | +static void usage(const char *me) { | |
1213 | + fprintf(stderr, "usage: %s [-a] use audio\n" | |
1214 | + "\t\t[-v] use video\n" | |
1215 | + "\t\t[-p] playback\n" | |
1216 | + "\t\t[-S] allocate buffers from a surface\n", | |
1217 | + me); | |
1218 | + | |
1219 | + exit(1); | |
1220 | +} | |
1221 | + | |
1222 | +namespace android { | |
1223 | + | |
1224 | +struct CodecState { | |
1225 | + sp<MediaCodec> mCodec; | |
1226 | + Vector<sp<ABuffer> > mInBuffers; | |
1227 | + Vector<sp<ABuffer> > mOutBuffers; | |
1228 | + bool mSignalledInputEOS; | |
1229 | + bool mSawOutputEOS; | |
1230 | + int64_t mNumBuffersDecoded; | |
1231 | + int64_t mNumBytesDecoded; | |
1232 | + bool mIsAudio; | |
1233 | +}; | |
1234 | + | |
1235 | +} // namespace android | |
1236 | + | |
1237 | +static int decode( | |
1238 | + const android::sp<android::ALooper> &looper, | |
1239 | + const char *path, | |
1240 | + bool useAudio, | |
1241 | + bool useVideo, | |
1242 | + const android::sp<android::Surface> &surface) { | |
1243 | + using namespace android; | |
1244 | + | |
1245 | + static int64_t kTimeout = 500ll; | |
1246 | + | |
1247 | + sp<NuMediaExtractor> extractor = new NuMediaExtractor; | |
1248 | + if (extractor->setDataSource(path) != OK) { | |
1249 | + fprintf(stderr, "unable to instantiate extractor.\n"); | |
1250 | + return 1; | |
1251 | + } | |
1252 | + | |
1253 | + KeyedVector<size_t, CodecState> stateByTrack; | |
1254 | + | |
1255 | + bool haveAudio = false; | |
1256 | + bool haveVideo = false; | |
1257 | + for (size_t i = 0; i < extractor->countTracks(); ++i) { | |
1258 | + sp<AMessage> format; | |
1259 | + status_t err = extractor->getTrackFormat(i, &format); | |
1260 | + CHECK_EQ(err, (status_t)OK); | |
1261 | + | |
1262 | + AString mime; | |
1263 | + CHECK(format->findString("mime", &mime)); | |
1264 | + | |
1265 | + bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6); | |
1266 | + bool isVideo = !strncasecmp(mime.c_str(), "video/", 6); | |
1267 | + | |
1268 | + if (useAudio && !haveAudio && isAudio) { | |
1269 | + haveAudio = true; | |
1270 | + } else if (useVideo && !haveVideo && isVideo) { | |
1271 | + haveVideo = true; | |
1272 | + } else { | |
1273 | + continue; | |
1274 | + } | |
1275 | + | |
1276 | + ALOGV("selecting track %d", i); | |
1277 | + | |
1278 | + err = extractor->selectTrack(i); | |
1279 | + CHECK_EQ(err, (status_t)OK); | |
1280 | + | |
1281 | + CodecState *state = | |
1282 | + &stateByTrack.editValueAt(stateByTrack.add(i, CodecState())); | |
1283 | + | |
1284 | + state->mNumBytesDecoded = 0; | |
1285 | + state->mNumBuffersDecoded = 0; | |
1286 | + state->mIsAudio = isAudio; | |
1287 | + | |
1288 | + state->mCodec = MediaCodec::CreateByType( | |
1289 | + looper, mime.c_str(), false /* encoder */); | |
1290 | + | |
1291 | + CHECK(state->mCodec != NULL); | |
1292 | + | |
1293 | + err = state->mCodec->configure( | |
1294 | + format, isVideo ? surface : NULL, | |
1295 | + NULL /* crypto */, | |
1296 | + 0 /* flags */); | |
1297 | + | |
1298 | + CHECK_EQ(err, (status_t)OK); | |
1299 | + | |
1300 | + state->mSignalledInputEOS = false; | |
1301 | + state->mSawOutputEOS = false; | |
1302 | + } | |
1303 | + | |
1304 | + CHECK(!stateByTrack.isEmpty()); | |
1305 | + | |
1306 | + int64_t startTimeUs = ALooper::GetNowUs(); | |
1307 | + | |
1308 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { | |
1309 | + CodecState *state = &stateByTrack.editValueAt(i); | |
1310 | + | |
1311 | + sp<MediaCodec> codec = state->mCodec; | |
1312 | + | |
1313 | + CHECK_EQ((status_t)OK, codec->start()); | |
1314 | + | |
1315 | + CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers)); | |
1316 | + CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers)); | |
1317 | + | |
1318 | + ALOGV("got %d input and %d output buffers", | |
1319 | + state->mInBuffers.size(), state->mOutBuffers.size()); | |
1320 | + } | |
1321 | + | |
1322 | + bool sawInputEOS = false; | |
1323 | + | |
1324 | + for (;;) { | |
1325 | + if (!sawInputEOS) { | |
1326 | + size_t trackIndex; | |
1327 | + status_t err = extractor->getSampleTrackIndex(&trackIndex); | |
1328 | + | |
1329 | + if (err != OK) { | |
1330 | + ALOGV("saw input eos"); | |
1331 | + sawInputEOS = true; | |
1332 | + } else { | |
1333 | + CodecState *state = &stateByTrack.editValueFor(trackIndex); | |
1334 | + | |
1335 | + size_t index; | |
1336 | + err = state->mCodec->dequeueInputBuffer(&index, kTimeout); | |
1337 | + | |
1338 | + if (err == OK) { | |
1339 | + ALOGV("filling input buffer %d", index); | |
1340 | + | |
1341 | + const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index); | |
1342 | + | |
1343 | + err = extractor->readSampleData(buffer); | |
1344 | + CHECK_EQ(err, (status_t)OK); | |
1345 | + | |
1346 | + int64_t timeUs; | |
1347 | + err = extractor->getSampleTime(&timeUs); | |
1348 | + CHECK_EQ(err, (status_t)OK); | |
1349 | + | |
1350 | + uint32_t bufferFlags = 0; | |
1351 | + | |
1352 | + err = state->mCodec->queueInputBuffer( | |
1353 | + index, | |
1354 | + 0 /* offset */, | |
1355 | + buffer->size(), | |
1356 | + timeUs, | |
1357 | + bufferFlags); | |
1358 | + | |
1359 | + CHECK_EQ(err, (status_t)OK); | |
1360 | + | |
1361 | + extractor->advance(); | |
1362 | + } else { | |
1363 | + CHECK_EQ(err, -EAGAIN); | |
1364 | + } | |
1365 | + } | |
1366 | + } else { | |
1367 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { | |
1368 | + CodecState *state = &stateByTrack.editValueAt(i); | |
1369 | + | |
1370 | + if (!state->mSignalledInputEOS) { | |
1371 | + size_t index; | |
1372 | + status_t err = | |
1373 | + state->mCodec->dequeueInputBuffer(&index, kTimeout); | |
1374 | + | |
1375 | + if (err == OK) { | |
1376 | + ALOGV("signalling input EOS on track %d", i); | |
1377 | + | |
1378 | + err = state->mCodec->queueInputBuffer( | |
1379 | + index, | |
1380 | + 0 /* offset */, | |
1381 | + 0 /* size */, | |
1382 | + 0ll /* timeUs */, | |
1383 | + MediaCodec::BUFFER_FLAG_EOS); | |
1384 | + | |
1385 | + CHECK_EQ(err, (status_t)OK); | |
1386 | + | |
1387 | + state->mSignalledInputEOS = true; | |
1388 | + } else { | |
1389 | + CHECK_EQ(err, -EAGAIN); | |
1390 | + } | |
1391 | + } | |
1392 | + } | |
1393 | + } | |
1394 | + | |
1395 | + bool sawOutputEOSOnAllTracks = true; | |
1396 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { | |
1397 | + CodecState *state = &stateByTrack.editValueAt(i); | |
1398 | + if (!state->mSawOutputEOS) { | |
1399 | + sawOutputEOSOnAllTracks = false; | |
1400 | + break; | |
1401 | + } | |
1402 | + } | |
1403 | + | |
1404 | + if (sawOutputEOSOnAllTracks) { | |
1405 | + break; | |
1406 | + } | |
1407 | + | |
1408 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { | |
1409 | + CodecState *state = &stateByTrack.editValueAt(i); | |
1410 | + | |
1411 | + if (state->mSawOutputEOS) { | |
1412 | + continue; | |
1413 | + } | |
1414 | + | |
1415 | + size_t index; | |
1416 | + size_t offset; | |
1417 | + size_t size; | |
1418 | + int64_t presentationTimeUs; | |
1419 | + uint32_t flags; | |
1420 | + status_t err = state->mCodec->dequeueOutputBuffer( | |
1421 | + &index, &offset, &size, &presentationTimeUs, &flags, | |
1422 | + kTimeout); | |
1423 | + | |
1424 | + if (err == OK) { | |
1425 | + ALOGV("draining output buffer %d, time = %lld us", | |
1426 | + index, presentationTimeUs); | |
1427 | + | |
1428 | + ++state->mNumBuffersDecoded; | |
1429 | + state->mNumBytesDecoded += size; | |
1430 | + | |
1431 | + err = state->mCodec->releaseOutputBuffer(index); | |
1432 | + CHECK_EQ(err, (status_t)OK); | |
1433 | + | |
1434 | + if (flags & MediaCodec::BUFFER_FLAG_EOS) { | |
1435 | + ALOGV("reached EOS on output."); | |
1436 | + | |
1437 | + state->mSawOutputEOS = true; | |
1438 | + } | |
1439 | + } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { | |
1440 | + ALOGV("INFO_OUTPUT_BUFFERS_CHANGED"); | |
1441 | + CHECK_EQ((status_t)OK, | |
1442 | + state->mCodec->getOutputBuffers(&state->mOutBuffers)); | |
1443 | + | |
1444 | + ALOGV("got %d output buffers", state->mOutBuffers.size()); | |
1445 | + } else if (err == INFO_FORMAT_CHANGED) { | |
1446 | + sp<AMessage> format; | |
1447 | + CHECK_EQ((status_t)OK, state->mCodec->getOutputFormat(&format)); | |
1448 | + | |
1449 | + ALOGV("INFO_FORMAT_CHANGED: %s", format->debugString().c_str()); | |
1450 | + } else { | |
1451 | + CHECK_EQ(err, -EAGAIN); | |
1452 | + } | |
1453 | + } | |
1454 | + } | |
1455 | + | |
1456 | + int64_t elapsedTimeUs = ALooper::GetNowUs() - startTimeUs; | |
1457 | + | |
1458 | + for (size_t i = 0; i < stateByTrack.size(); ++i) { | |
1459 | + CodecState *state = &stateByTrack.editValueAt(i); | |
1460 | + | |
1461 | + CHECK_EQ((status_t)OK, state->mCodec->release()); | |
1462 | + | |
1463 | + if (state->mIsAudio) { | |
1464 | + ALOGD("track %d: %lld bytes received. %.2f KB/sec\n", | |
1465 | + i, | |
1466 | + state->mNumBytesDecoded, | |
1467 | + state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs); | |
1468 | + } else { | |
1469 | + ALOGD("track %d: %lld frames decoded, %.2f fps. %lld bytes " | |
1470 | + "received. %.2f KB/sec\n", | |
1471 | + i, | |
1472 | + state->mNumBuffersDecoded, | |
1473 | + state->mNumBuffersDecoded * 1E6 / elapsedTimeUs, | |
1474 | + state->mNumBytesDecoded, | |
1475 | + state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs); | |
1476 | + } | |
1477 | + } | |
1478 | + | |
1479 | + return 0; | |
1480 | +} | |
1481 | + | |
1482 | +int main(int argc, char **argv) { | |
1483 | + using namespace android; | |
1484 | + | |
1485 | + const char *me = argv[0]; | |
1486 | + | |
1487 | + bool useAudio = false; | |
1488 | + bool useVideo = false; | |
1489 | + bool playback = false; | |
1490 | + bool useSurface = false; | |
1491 | + | |
1492 | + int res; | |
1493 | + while ((res = getopt(argc, argv, "havpSD")) >= 0) { | |
1494 | + switch (res) { | |
1495 | + case 'a': | |
1496 | + { | |
1497 | + useAudio = true; | |
1498 | + break; | |
1499 | + } | |
1500 | + | |
1501 | + case 'v': | |
1502 | + { | |
1503 | + useVideo = true; | |
1504 | + break; | |
1505 | + } | |
1506 | + | |
1507 | + case 'p': | |
1508 | + { | |
1509 | + playback = true; | |
1510 | + break; | |
1511 | + } | |
1512 | + | |
1513 | + case 'S': | |
1514 | + { | |
1515 | + useSurface = true; | |
1516 | + break; | |
1517 | + } | |
1518 | + | |
1519 | + case '?': | |
1520 | + case 'h': | |
1521 | + default: | |
1522 | + { | |
1523 | + usage(me); | |
1524 | + } | |
1525 | + } | |
1526 | + } | |
1527 | + | |
1528 | + argc -= optind; | |
1529 | + argv += optind; | |
1530 | + | |
1531 | + if (argc != 1) { | |
1532 | + usage(me); | |
1533 | + } | |
1534 | + | |
1535 | + if (!useAudio && !useVideo) { | |
1536 | + useAudio = useVideo = true; | |
1537 | + } | |
1538 | + | |
1539 | + ProcessState::self()->startThreadPool(); | |
1540 | + | |
1541 | + DataSource::RegisterDefaultSniffers(); | |
1542 | + | |
1543 | + sp<ALooper> looper = new ALooper; | |
1544 | + looper->start(); | |
1545 | + | |
1546 | + sp<SurfaceComposerClient> composerClient; | |
1547 | + sp<SurfaceControl> control; | |
1548 | + sp<Surface> surface; | |
1549 | + | |
1550 | + if (playback || (useSurface && useVideo)) { | |
1551 | + composerClient = new SurfaceComposerClient; | |
1552 | + CHECK_EQ(composerClient->initCheck(), (status_t)OK); | |
1553 | + | |
1554 | + sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay( | |
1555 | + ISurfaceComposer::eDisplayIdMain)); | |
1556 | + DisplayInfo info; | |
1557 | + SurfaceComposerClient::getDisplayInfo(display, &info); | |
1558 | + ssize_t displayWidth = info.w; | |
1559 | + ssize_t displayHeight = info.h; | |
1560 | + | |
1561 | + ALOGV("display is %ld x %ld\n", displayWidth, displayHeight); | |
1562 | + | |
1563 | + control = composerClient->createSurface( | |
1564 | + String8("A Surface"), | |
1565 | + displayWidth, | |
1566 | + displayHeight, | |
1567 | + PIXEL_FORMAT_RGB_565, | |
1568 | + 0); | |
1569 | + | |
1570 | + CHECK(control != NULL); | |
1571 | + CHECK(control->isValid()); | |
1572 | + | |
1573 | + SurfaceComposerClient::openGlobalTransaction(); | |
1574 | + CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); | |
1575 | + CHECK_EQ(control->show(), (status_t)OK); | |
1576 | + SurfaceComposerClient::closeGlobalTransaction(); | |
1577 | + | |
1578 | + surface = control->getSurface(); | |
1579 | + CHECK(surface != NULL); | |
1580 | + } | |
1581 | + | |
1582 | + if (playback) { | |
1583 | + sp<SimplePlayer> player = new SimplePlayer; | |
1584 | + looper->registerHandler(player); | |
1585 | + | |
1586 | + player->setDataSource(argv[0]); | |
1587 | + player->setSurface(surface->getSurfaceTexture()); | |
1588 | + player->start(); | |
1589 | + ALOGD("Playing for 60 seconds\n"); | |
1590 | + sleep(60); | |
1591 | + player->stop(); | |
1592 | + player->reset(); | |
1593 | + } else { | |
1594 | + decode(looper, argv[0], useAudio, useVideo, surface); | |
1595 | + } | |
1596 | + | |
1597 | + if (playback || (useSurface && useVideo)) { | |
1598 | + composerClient->dispose(); | |
1599 | + } | |
1600 | + | |
1601 | + looper->stop(); | |
1602 | + | |
1603 | + return 0; | |
1604 | +} | |
1605 | --- /dev/null | |
1606 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/direct_media_test.cpp | |
1607 | @@ -0,0 +1,417 @@ | |
1608 | +/* | |
1609 | + * Copyright (C) 2013 Canonical Ltd | |
1610 | + * | |
1611 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
1612 | + * you may not use this file except in compliance with the License. | |
1613 | + * You may obtain a copy of the License at | |
1614 | + * | |
1615 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
1616 | + * | |
1617 | + * Unless required by applicable law or agreed to in writing, software | |
1618 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
1619 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
1620 | + * See the License for the specific language governing permissions and | |
1621 | + * limitations under the License. | |
1622 | + * | |
1623 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
1624 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
1625 | + */ | |
1626 | + | |
1627 | +#include <hybris/media/media_compatibility_layer.h> | |
1628 | +#include "direct_media_test.h" | |
1629 | + | |
1630 | +#include <utils/Errors.h> | |
1631 | + | |
1632 | +#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h> | |
1633 | + | |
1634 | +#include <GLES2/gl2.h> | |
1635 | +#include <GLES2/gl2ext.h> | |
1636 | + | |
1637 | +#include <sys/stat.h> | |
1638 | +#include <sys/types.h> | |
1639 | +#include <fcntl.h> | |
1640 | +#include <unistd.h> | |
1641 | + | |
1642 | +#include <cassert> | |
1643 | +#include <cstdio> | |
1644 | +#include <cstdlib> | |
1645 | +#include <cstring> | |
1646 | + | |
1647 | +using namespace android; | |
1648 | + | |
1649 | +static float DestWidth = 0.0, DestHeight = 0.0; | |
1650 | +// Actual video dimmensions | |
1651 | +static int Width = 0, Height = 0; | |
1652 | + | |
1653 | +static GLfloat positionCoordinates[8]; | |
1654 | + | |
1655 | +MediaPlayerWrapper *player = NULL; | |
1656 | + | |
1657 | +void calculate_position_coordinates() | |
1658 | +{ | |
1659 | + // Assuming cropping output for now | |
1660 | + float x = 1, y = 1; | |
1661 | + | |
1662 | + // Black borders | |
1663 | + x = float(Width / DestWidth); | |
1664 | + y = float(Height / DestHeight); | |
1665 | + | |
1666 | + // Make the larger side be 1 | |
1667 | + if (x > y) { | |
1668 | + y /= x; | |
1669 | + x = 1; | |
1670 | + } else { | |
1671 | + x /= y; | |
1672 | + y = 1; | |
1673 | + } | |
1674 | + | |
1675 | + positionCoordinates[0] = -x; | |
1676 | + positionCoordinates[1] = y; | |
1677 | + positionCoordinates[2] = -x; | |
1678 | + positionCoordinates[3] = -y; | |
1679 | + positionCoordinates[4] = x; | |
1680 | + positionCoordinates[5] = -y; | |
1681 | + positionCoordinates[6] = x; | |
1682 | + positionCoordinates[7] = y; | |
1683 | +} | |
1684 | + | |
1685 | +WindowRenderer::WindowRenderer(int width, int height) | |
1686 | + : mThreadCmd(CMD_IDLE) | |
1687 | +{ | |
1688 | + createThread(threadStart, this); | |
1689 | +} | |
1690 | + | |
1691 | +WindowRenderer::~WindowRenderer() | |
1692 | +{ | |
1693 | +} | |
1694 | + | |
1695 | +int WindowRenderer::threadStart(void* self) | |
1696 | +{ | |
1697 | + ((WindowRenderer *)self)->glThread(); | |
1698 | + return 0; | |
1699 | +} | |
1700 | + | |
1701 | +void WindowRenderer::glThread() | |
1702 | +{ | |
1703 | + printf("%s\n", __PRETTY_FUNCTION__); | |
1704 | + | |
1705 | + Mutex::Autolock autoLock(mLock); | |
1706 | +} | |
1707 | + | |
1708 | +struct ClientWithSurface | |
1709 | +{ | |
1710 | + SfClient* client; | |
1711 | + SfSurface* surface; | |
1712 | +}; | |
1713 | + | |
1714 | +ClientWithSurface client_with_surface(bool setup_surface_with_egl) | |
1715 | +{ | |
1716 | + ClientWithSurface cs = ClientWithSurface(); | |
1717 | + | |
1718 | + cs.client = sf_client_create(); | |
1719 | + | |
1720 | + if (!cs.client) { | |
1721 | + printf("Problem creating client ... aborting now."); | |
1722 | + return cs; | |
1723 | + } | |
1724 | + | |
1725 | + static const size_t primary_display = 0; | |
1726 | + | |
1727 | + DestWidth = sf_get_display_width(primary_display); | |
1728 | + DestHeight = sf_get_display_height(primary_display); | |
1729 | + printf("Primary display width: %f, height: %f\n", DestWidth, DestHeight); | |
1730 | + | |
1731 | + SfSurfaceCreationParameters params = { | |
1732 | + 0, | |
1733 | + 0, | |
1734 | + (int) DestWidth, | |
1735 | + (int) DestHeight, | |
1736 | + -1, //PIXEL_FORMAT_RGBA_8888, | |
1737 | + 15000, | |
1738 | + 0.5f, | |
1739 | + setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL | |
1740 | + "MediaCompatLayerTestSurface" | |
1741 | + }; | |
1742 | + | |
1743 | + cs.surface = sf_surface_create(cs.client, ¶ms); | |
1744 | + | |
1745 | + if (!cs.surface) { | |
1746 | + printf("Problem creating surface ... aborting now."); | |
1747 | + return cs; | |
1748 | + } | |
1749 | + | |
1750 | + sf_surface_make_current(cs.surface); | |
1751 | + | |
1752 | + return cs; | |
1753 | +} | |
1754 | + | |
1755 | +struct RenderData | |
1756 | +{ | |
1757 | + static const char *vertex_shader() | |
1758 | + { | |
1759 | + return | |
1760 | + "attribute vec4 a_position; \n" | |
1761 | + "attribute vec2 a_texCoord; \n" | |
1762 | + "uniform mat4 m_texMatrix; \n" | |
1763 | + "varying vec2 v_texCoord; \n" | |
1764 | + "varying float topDown; \n" | |
1765 | + "void main() \n" | |
1766 | + "{ \n" | |
1767 | + " gl_Position = a_position; \n" | |
1768 | + " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n" | |
1769 | + "} \n"; | |
1770 | + } | |
1771 | + | |
1772 | + static const char *fragment_shader() | |
1773 | + { | |
1774 | + return | |
1775 | + "#extension GL_OES_EGL_image_external : require \n" | |
1776 | + "precision mediump float; \n" | |
1777 | + "varying vec2 v_texCoord; \n" | |
1778 | + "uniform samplerExternalOES s_texture; \n" | |
1779 | + "void main() \n" | |
1780 | + "{ \n" | |
1781 | + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" | |
1782 | + "} \n"; | |
1783 | + } | |
1784 | + | |
1785 | + static GLuint loadShader(GLenum shaderType, const char* pSource) | |
1786 | + { | |
1787 | + GLuint shader = glCreateShader(shaderType); | |
1788 | + | |
1789 | + if (shader) { | |
1790 | + glShaderSource(shader, 1, &pSource, NULL); | |
1791 | + glCompileShader(shader); | |
1792 | + GLint compiled = 0; | |
1793 | + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); | |
1794 | + | |
1795 | + if (!compiled) { | |
1796 | + GLint infoLen = 0; | |
1797 | + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); | |
1798 | + if (infoLen) { | |
1799 | + char* buf = (char*) malloc(infoLen); | |
1800 | + if (buf) { | |
1801 | + glGetShaderInfoLog(shader, infoLen, NULL, buf); | |
1802 | + fprintf(stderr, "Could not compile shader %d:\n%s\n", | |
1803 | + shaderType, buf); | |
1804 | + free(buf); | |
1805 | + } | |
1806 | + glDeleteShader(shader); | |
1807 | + shader = 0; | |
1808 | + } | |
1809 | + } | |
1810 | + } else { | |
1811 | + printf("Error, during shader creation: %i\n", glGetError()); | |
1812 | + } | |
1813 | + | |
1814 | + return shader; | |
1815 | + } | |
1816 | + | |
1817 | + static GLuint create_program(const char* pVertexSource, const char* pFragmentSource) | |
1818 | + { | |
1819 | + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); | |
1820 | + if (!vertexShader) { | |
1821 | + printf("vertex shader not compiled\n"); | |
1822 | + return 0; | |
1823 | + } | |
1824 | + | |
1825 | + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); | |
1826 | + if (!pixelShader) { | |
1827 | + printf("frag shader not compiled\n"); | |
1828 | + return 0; | |
1829 | + } | |
1830 | + | |
1831 | + GLuint program = glCreateProgram(); | |
1832 | + if (program) { | |
1833 | + glAttachShader(program, vertexShader); | |
1834 | + glAttachShader(program, pixelShader); | |
1835 | + glLinkProgram(program); | |
1836 | + GLint linkStatus = GL_FALSE; | |
1837 | + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); | |
1838 | + | |
1839 | + if (linkStatus != GL_TRUE) { | |
1840 | + GLint bufLength = 0; | |
1841 | + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); | |
1842 | + if (bufLength) { | |
1843 | + char* buf = (char*) malloc(bufLength); | |
1844 | + if (buf) { | |
1845 | + glGetProgramInfoLog(program, bufLength, NULL, buf); | |
1846 | + fprintf(stderr, "Could not link program:\n%s\n", buf); | |
1847 | + free(buf); | |
1848 | + } | |
1849 | + } | |
1850 | + glDeleteProgram(program); | |
1851 | + program = 0; | |
1852 | + } | |
1853 | + } | |
1854 | + | |
1855 | + return program; | |
1856 | + } | |
1857 | + | |
1858 | + RenderData() : program_object(create_program(vertex_shader(), fragment_shader())) | |
1859 | + { | |
1860 | + position_loc = glGetAttribLocation(program_object, "a_position"); | |
1861 | + tex_coord_loc = glGetAttribLocation(program_object, "a_texCoord"); | |
1862 | + sampler_loc = glGetUniformLocation(program_object, "s_texture"); | |
1863 | + matrix_loc = glGetUniformLocation(program_object, "m_texMatrix"); | |
1864 | + } | |
1865 | + | |
1866 | + // Handle to a program object | |
1867 | + GLuint program_object; | |
1868 | + // Attribute locations | |
1869 | + GLint position_loc; | |
1870 | + GLint tex_coord_loc; | |
1871 | + // Sampler location | |
1872 | + GLint sampler_loc; | |
1873 | + // Matrix location | |
1874 | + GLint matrix_loc; | |
1875 | +}; | |
1876 | + | |
1877 | +static int setup_video_texture(ClientWithSurface *cs, GLuint *preview_texture_id) | |
1878 | +{ | |
1879 | + assert(cs != NULL); | |
1880 | + assert(preview_texture_id != NULL); | |
1881 | + | |
1882 | + sf_surface_make_current(cs->surface); | |
1883 | + | |
1884 | + glGenTextures(1, preview_texture_id); | |
1885 | + glClearColor(0, 0, 0, 0); | |
1886 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
1887 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
1888 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
1889 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
1890 | + | |
1891 | + android_media_set_preview_texture(player, *preview_texture_id); | |
1892 | + | |
1893 | + return 0; | |
1894 | +} | |
1895 | + | |
1896 | +static void print_gl_error(unsigned int line) | |
1897 | +{ | |
1898 | + GLint error = glGetError(); | |
1899 | + printf("GL error: %#04x (line: %d)\n", error, line); | |
1900 | +} | |
1901 | + | |
1902 | +static int update_gl_buffer(RenderData *render_data, EGLDisplay *disp, EGLSurface *surface) | |
1903 | +{ | |
1904 | + assert(disp != NULL); | |
1905 | + assert(surface != NULL); | |
1906 | + | |
1907 | + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; | |
1908 | + | |
1909 | + const GLfloat textureCoordinates[] = { | |
1910 | + 1.0f, 1.0f, | |
1911 | + 0.0f, 1.0f, | |
1912 | + 0.0f, 0.0f, | |
1913 | + 1.0f, 0.0f | |
1914 | + }; | |
1915 | + | |
1916 | + calculate_position_coordinates(); | |
1917 | + | |
1918 | + glClear(GL_COLOR_BUFFER_BIT); | |
1919 | + // Use the program object | |
1920 | + glUseProgram(render_data->program_object); | |
1921 | + // Enable attributes | |
1922 | + glEnableVertexAttribArray(render_data->position_loc); | |
1923 | + glEnableVertexAttribArray(render_data->tex_coord_loc); | |
1924 | + // Load the vertex position | |
1925 | + glVertexAttribPointer(render_data->position_loc, | |
1926 | + 2, | |
1927 | + GL_FLOAT, | |
1928 | + GL_FALSE, | |
1929 | + 0, | |
1930 | + positionCoordinates); | |
1931 | + // Load the texture coordinate | |
1932 | + glVertexAttribPointer(render_data->tex_coord_loc, | |
1933 | + 2, | |
1934 | + GL_FLOAT, | |
1935 | + GL_FALSE, | |
1936 | + 0, | |
1937 | + textureCoordinates); | |
1938 | + | |
1939 | + GLfloat matrix[16]; | |
1940 | + android_media_surface_texture_get_transformation_matrix(player, matrix); | |
1941 | + | |
1942 | + glUniformMatrix4fv(render_data->matrix_loc, 1, GL_FALSE, matrix); | |
1943 | + | |
1944 | + glActiveTexture(GL_TEXTURE0); | |
1945 | + // Set the sampler texture unit to 0 | |
1946 | + glUniform1i(render_data->sampler_loc, 0); | |
1947 | + glUniform1i(render_data->matrix_loc, 0); | |
1948 | + android_media_update_surface_texture(player); | |
1949 | + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | |
1950 | + //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); | |
1951 | + glDisableVertexAttribArray(render_data->position_loc); | |
1952 | + glDisableVertexAttribArray(render_data->tex_coord_loc); | |
1953 | + | |
1954 | + eglSwapBuffers(*disp, *surface); | |
1955 | + | |
1956 | + return 0; | |
1957 | +} | |
1958 | + | |
1959 | +void set_video_size_cb(int height, int width, void *context) | |
1960 | +{ | |
1961 | + printf("Video height: %d, width: %d\n", height, width); | |
1962 | + printf("Video dest height: %f, width: %f\n", DestHeight, DestWidth); | |
1963 | + | |
1964 | + Height = height; | |
1965 | + Width = width; | |
1966 | +} | |
1967 | + | |
1968 | +int main(int argc, char **argv) | |
1969 | +{ | |
1970 | + if (argc < 2) { | |
1971 | + printf("Usage: direct_media_test <video_to_play>\n"); | |
1972 | + return EXIT_FAILURE; | |
1973 | + } | |
1974 | + | |
1975 | + player = android_media_new_player(); | |
1976 | + if (player == NULL) { | |
1977 | + printf("Problem creating new media player.\n"); | |
1978 | + return EXIT_FAILURE; | |
1979 | + } | |
1980 | + | |
1981 | + // Set player event cb for when the video size is known: | |
1982 | + android_media_set_video_size_cb(player, set_video_size_cb, NULL); | |
1983 | + | |
1984 | + printf("Setting data source to: %s.\n", argv[1]); | |
1985 | + | |
1986 | + if (android_media_set_data_source(player, argv[1]) != OK) { | |
1987 | + printf("Failed to set data source: %s\n", argv[1]); | |
1988 | + return EXIT_FAILURE; | |
1989 | + } | |
1990 | + | |
1991 | + WindowRenderer renderer(DestWidth, DestHeight); | |
1992 | + | |
1993 | + printf("Creating EGL surface.\n"); | |
1994 | + ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */); | |
1995 | + if (!cs.surface) { | |
1996 | + printf("Problem acquiring surface for preview"); | |
1997 | + return EXIT_FAILURE; | |
1998 | + } | |
1999 | + | |
2000 | + printf("Creating GL texture.\n"); | |
2001 | + GLuint preview_texture_id; | |
2002 | + EGLDisplay disp = sf_client_get_egl_display(cs.client); | |
2003 | + EGLSurface surface = sf_surface_get_egl_surface(cs.surface); | |
2004 | + | |
2005 | + sf_surface_make_current(cs.surface); | |
2006 | + if (setup_video_texture(&cs, &preview_texture_id) != OK) { | |
2007 | + printf("Problem setting up GL texture for video surface.\n"); | |
2008 | + return EXIT_FAILURE; | |
2009 | + } | |
2010 | + | |
2011 | + RenderData render_data; | |
2012 | + | |
2013 | + printf("Starting video playback.\n"); | |
2014 | + android_media_play(player); | |
2015 | + | |
2016 | + printf("Updating gl buffer continuously...\n"); | |
2017 | + while (android_media_is_playing(player)) { | |
2018 | + update_gl_buffer(&render_data, &disp, &surface); | |
2019 | + } | |
2020 | + | |
2021 | + android_media_stop(player); | |
2022 | + | |
2023 | + return EXIT_SUCCESS; | |
2024 | +} | |
2025 | --- /dev/null | |
2026 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/direct_media_test.h | |
2027 | @@ -0,0 +1,58 @@ | |
2028 | +/* | |
2029 | + * Copyright (C) 2013 Canonical Ltd | |
2030 | + * | |
2031 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
2032 | + * you may not use this file except in compliance with the License. | |
2033 | + * You may obtain a copy of the License at | |
2034 | + * | |
2035 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
2036 | + * | |
2037 | + * Unless required by applicable law or agreed to in writing, software | |
2038 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
2039 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
2040 | + * See the License for the specific language governing permissions and | |
2041 | + * limitations under the License. | |
2042 | + * | |
2043 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
2044 | + */ | |
2045 | + | |
2046 | +#ifndef DIRECT_MEDIA_TEST_H_ | |
2047 | +#define DIRECT_MEDIA_TEST_H_ | |
2048 | + | |
2049 | +#include <EGL/egl.h> | |
2050 | +#include <GLES2/gl2.h> | |
2051 | +#include <utils/threads.h> | |
2052 | + | |
2053 | +namespace android { | |
2054 | + | |
2055 | +class RenderInput; | |
2056 | + | |
2057 | +class WindowRenderer | |
2058 | +{ | |
2059 | +public: | |
2060 | + WindowRenderer(int width, int height); | |
2061 | + ~WindowRenderer(); | |
2062 | + | |
2063 | +private: | |
2064 | + // The GL thread functions | |
2065 | + static int threadStart(void* self); | |
2066 | + void glThread(); | |
2067 | + | |
2068 | + // These variables are used to communicate between the GL thread and | |
2069 | + // other threads. | |
2070 | + Mutex mLock; | |
2071 | + Condition mCond; | |
2072 | + enum { | |
2073 | + CMD_IDLE, | |
2074 | + CMD_RENDER_INPUT, | |
2075 | + CMD_RESERVE_TEXTURE, | |
2076 | + CMD_DELETE_TEXTURE, | |
2077 | + CMD_QUIT, | |
2078 | + }; | |
2079 | + int mThreadCmd; | |
2080 | + RenderInput* mThreadRenderInput; | |
2081 | + GLuint mThreadTextureId; | |
2082 | +}; | |
2083 | +} // android | |
2084 | + | |
2085 | +#endif | |
2086 | --- /dev/null | |
2087 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_codec_layer.cpp | |
2088 | @@ -0,0 +1,763 @@ | |
2089 | +/* | |
2090 | + * Copyright (C) 2013 Canonical Ltd | |
2091 | + * | |
2092 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
2093 | + * you may not use this file except in compliance with the License. | |
2094 | + * You may obtain a copy of the License at | |
2095 | + * | |
2096 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
2097 | + * | |
2098 | + * Unless required by applicable law or agreed to in writing, software | |
2099 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
2100 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
2101 | + * See the License for the specific language governing permissions and | |
2102 | + * limitations under the License. | |
2103 | + * | |
2104 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
2105 | + */ | |
2106 | + | |
2107 | +// Uncomment to enable verbose debug output | |
2108 | +#define LOG_NDEBUG 0 | |
2109 | + | |
2110 | +#undef LOG_TAG | |
2111 | +#define LOG_TAG "MediaCodecLayer" | |
2112 | + | |
2113 | +#include <hybris/media/media_codec_layer.h> | |
2114 | +#include <hybris/media/media_compatibility_layer.h> | |
2115 | +#include <hybris/media/media_format_layer.h> | |
2116 | + | |
2117 | +#include "media_format_layer_priv.h" | |
2118 | +#include "surface_texture_client_hybris_priv.h" | |
2119 | + | |
2120 | +#include <fcntl.h> | |
2121 | +#include <sys/stat.h> | |
2122 | + | |
2123 | +#include <binder/ProcessState.h> | |
2124 | + | |
2125 | +#include <media/stagefright/foundation/AHandler.h> | |
2126 | +#include <media/stagefright/foundation/AString.h> | |
2127 | +#include <media/ICrypto.h> | |
2128 | +#include <media/stagefright/foundation/ABuffer.h> | |
2129 | +#include <media/stagefright/foundation/ADebug.h> | |
2130 | +#include <media/stagefright/foundation/AMessage.h> | |
2131 | +#include <media/stagefright/MediaCodec.h> | |
2132 | +#include <media/stagefright/MediaErrors.h> | |
2133 | +#include <media/stagefright/NativeWindowWrapper.h> | |
2134 | + | |
2135 | +#include <utils/Vector.h> | |
2136 | +#include <utils/Log.h> | |
2137 | +#include <utils/RefBase.h> | |
2138 | + | |
2139 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); | |
2140 | + | |
2141 | +using namespace android; | |
2142 | + | |
2143 | +struct _MediaCodecDelegate : public AHandler | |
2144 | +{ | |
2145 | +public: | |
2146 | + typedef sp<_MediaCodecDelegate> Ptr; | |
2147 | + | |
2148 | + explicit _MediaCodecDelegate(void *context); | |
2149 | + virtual ~_MediaCodecDelegate(); | |
2150 | + | |
2151 | +protected: | |
2152 | + virtual void onMessageReceived(const sp<AMessage> &msg) { } | |
2153 | + | |
2154 | +public: | |
2155 | + sp<MediaCodec> media_codec; | |
2156 | + sp<ALooper> looper; | |
2157 | + | |
2158 | + Vector<sp<ABuffer> > input_buffers; | |
2159 | + Vector<sp<ABuffer> > output_buffers; | |
2160 | + List<MediaCodecBufferInfo> available_output_buffer_infos; | |
2161 | + List<size_t> available_input_buffer_indices; | |
2162 | + bool output_format_changed; | |
2163 | + bool hardware_rendering; | |
2164 | + | |
2165 | + void *context; | |
2166 | + unsigned int refcount; | |
2167 | +}; | |
2168 | + | |
2169 | +_MediaCodecDelegate::_MediaCodecDelegate(void *context) | |
2170 | + : output_format_changed(false), | |
2171 | + hardware_rendering(false), | |
2172 | + context(context), | |
2173 | + refcount(1) | |
2174 | +{ | |
2175 | + REPORT_FUNCTION() | |
2176 | +} | |
2177 | + | |
2178 | +_MediaCodecDelegate::~_MediaCodecDelegate() | |
2179 | +{ | |
2180 | + REPORT_FUNCTION() | |
2181 | +} | |
2182 | + | |
2183 | +static inline _MediaCodecDelegate *get_internal_delegate(MediaCodecDelegate delegate) | |
2184 | +{ | |
2185 | + if (delegate == NULL) | |
2186 | + { | |
2187 | + ALOGE("delegate must not be NULL"); | |
2188 | + return NULL; | |
2189 | + } | |
2190 | + | |
2191 | + _MediaCodecDelegate *d = static_cast<_MediaCodecDelegate*>(delegate); | |
2192 | + // Some simple sanity checks that must be true for a valid MediaCodecDelegate instance | |
2193 | + if (d->media_codec == NULL || d->refcount < 1) | |
2194 | + return NULL; | |
2195 | + | |
2196 | + return d; | |
2197 | +} | |
2198 | + | |
2199 | +MediaCodecDelegate media_codec_create_by_codec_name(const char *name) | |
2200 | +{ | |
2201 | + REPORT_FUNCTION() | |
2202 | + | |
2203 | + if (name == NULL) | |
2204 | + { | |
2205 | + ALOGE("name must not be NULL"); | |
2206 | + return NULL; | |
2207 | + } | |
2208 | + | |
2209 | + ALOGD("Creating codec '%s'", name); | |
2210 | + | |
2211 | + ProcessState::self()->startThreadPool(); | |
2212 | + | |
2213 | + _MediaCodecDelegate *d(new _MediaCodecDelegate(NULL)); | |
2214 | + d->looper = new ALooper; | |
2215 | + d->looper->start(); | |
2216 | + | |
2217 | + d->media_codec = android::MediaCodec::CreateByComponentName(d->looper, name); | |
2218 | + | |
2219 | + return d; | |
2220 | +} | |
2221 | + | |
2222 | +#ifdef SIMPLE_PLAYER | |
2223 | +MediaCodec* media_codec_get(MediaCodecDelegate delegate) | |
2224 | +{ | |
2225 | + REPORT_FUNCTION() | |
2226 | + | |
2227 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2228 | + if (d == NULL) | |
2229 | + return NULL; | |
2230 | + | |
2231 | + return d->media_codec.get(); | |
2232 | +} | |
2233 | +#endif | |
2234 | + | |
2235 | +MediaCodecDelegate media_codec_create_by_codec_type(const char *type) | |
2236 | +{ | |
2237 | + REPORT_FUNCTION() | |
2238 | + | |
2239 | + if (type == NULL) | |
2240 | + { | |
2241 | + ALOGE("type must not be NULL"); | |
2242 | + return NULL; | |
2243 | + } | |
2244 | + | |
2245 | + ALOGD("Creating codec by type '%s'", type); | |
2246 | + | |
2247 | + ProcessState::self()->startThreadPool(); | |
2248 | + | |
2249 | + _MediaCodecDelegate *d(new _MediaCodecDelegate(NULL)); | |
2250 | + d->looper = new ALooper; | |
2251 | + d->looper->start(); | |
2252 | + | |
2253 | + d->media_codec = android::MediaCodec::CreateByType(d->looper, type, false); | |
2254 | + | |
2255 | + return d; | |
2256 | +} | |
2257 | + | |
2258 | +void media_codec_delegate_destroy(MediaCodecDelegate delegate) | |
2259 | +{ | |
2260 | + REPORT_FUNCTION() | |
2261 | + | |
2262 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2263 | + if (d == NULL) | |
2264 | + { | |
2265 | + ALOGE("d == NULL, cannot destroy MediaCodecDelegate instance"); | |
2266 | + return; | |
2267 | + } | |
2268 | + | |
2269 | + ALOGI("Releasing media_codec"); | |
2270 | + d->media_codec->release(); | |
2271 | + ALOGI("Stopping looper"); | |
2272 | + d->looper->stop(); | |
2273 | + | |
2274 | + ALOGI("Setting refcount = 0"); | |
2275 | + d->refcount = 0; | |
2276 | + | |
2277 | + ALOGI("Deleting the MediaCodecDelegate instance"); | |
2278 | + delete d; | |
2279 | +} | |
2280 | + | |
2281 | +void media_codec_delegate_ref(MediaCodecDelegate delegate) | |
2282 | +{ | |
2283 | + REPORT_FUNCTION() | |
2284 | + | |
2285 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2286 | + if (d == NULL) | |
2287 | + return; | |
2288 | + | |
2289 | + d->refcount++; | |
2290 | +} | |
2291 | + | |
2292 | +void media_codec_delegate_unref(MediaCodecDelegate delegate) | |
2293 | +{ | |
2294 | + REPORT_FUNCTION() | |
2295 | + | |
2296 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2297 | + if (d == NULL) | |
2298 | + { | |
2299 | + ALOGE("d == NULL, cannot unref MediaCodecDelegate instance"); | |
2300 | + return; | |
2301 | + } | |
2302 | + | |
2303 | + if (d->refcount > 1) | |
2304 | + d->refcount--; | |
2305 | + else | |
2306 | + media_codec_delegate_destroy (delegate); | |
2307 | +} | |
2308 | + | |
2309 | +#ifdef SIMPLE_PLAYER | |
2310 | +int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, void *nativeWindow, uint32_t flags) | |
2311 | +#else | |
2312 | +int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, SurfaceTextureClientHybris stc, uint32_t flags) | |
2313 | +#endif | |
2314 | +{ | |
2315 | + REPORT_FUNCTION() | |
2316 | + | |
2317 | + if (format == NULL) | |
2318 | + { | |
2319 | + ALOGE("format must not be NULL"); | |
2320 | + return BAD_VALUE; | |
2321 | + } | |
2322 | + | |
2323 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2324 | + if (d == NULL) | |
2325 | + return BAD_VALUE; | |
2326 | + | |
2327 | + _MediaFormat *format_priv = static_cast<_MediaFormat*>(format); | |
2328 | +#ifndef SIMPLE_PLAYER | |
2329 | + _SurfaceTextureClientHybris *stch = static_cast<_SurfaceTextureClientHybris*>(stc); | |
2330 | +#endif | |
2331 | + | |
2332 | + sp<AMessage> aformat = new AMessage; | |
2333 | + aformat->setString("mime", format_priv->mime.c_str()); | |
2334 | + if (format_priv->duration_us > 0) | |
2335 | + aformat->setInt64("durationUs", format_priv->duration_us); | |
2336 | + aformat->setInt32("width", format_priv->width); | |
2337 | + aformat->setInt32("height", format_priv->height); | |
2338 | + if (format_priv->max_input_size > 0) | |
2339 | + aformat->setInt32("max-input-size", format_priv->max_input_size); | |
2340 | + | |
2341 | + ALOGD("Format: %s", aformat->debugString().c_str()); | |
2342 | + | |
2343 | +#ifdef SIMPLE_PLAYER | |
2344 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
2345 | + sp<SurfaceTextureClient> surfaceTextureClient = static_cast<SurfaceTextureClient*>(nativeWindow); | |
2346 | +#else | |
2347 | + sp<Surface> surfaceTextureClient = static_cast<Surface*>(nativeWindow); | |
2348 | +#endif | |
2349 | + // TODO: Don't just pass NULL for the security when DRM is needed | |
2350 | + d->media_codec->configure(aformat, surfaceTextureClient, NULL, flags); | |
2351 | +#else | |
2352 | + ALOGD("SurfaceTextureClientHybris: %p", stch); | |
2353 | + | |
2354 | + // Make sure we're ready to configure the codec and the Surface/SurfaceTextureClient together | |
2355 | + if (stch != NULL && stch->hardwareRendering() && stch->isReady()) | |
2356 | + { | |
2357 | + ALOGD("Doing hardware decoding with hardware rendering"); | |
2358 | + // TODO: Don't just pass NULL for the security when DRM is needed | |
2359 | + d->media_codec->configure(aformat, stch, NULL, flags); | |
2360 | + } | |
2361 | + else | |
2362 | + { | |
2363 | + ALOGD("Doing hardware decoding path with software rendering"); | |
2364 | + // This scenario is for hardware video decoding, but software rendering, therefore there's | |
2365 | + // no need to pass a valid Surface/SurfaceTextureClient instance to configure() | |
2366 | + d->media_codec->configure(aformat, NULL, NULL, flags); | |
2367 | + } | |
2368 | + | |
2369 | +#endif | |
2370 | + | |
2371 | + return OK; | |
2372 | +} | |
2373 | + | |
2374 | +int media_codec_set_surface_texture_client(MediaCodecDelegate delegate, SurfaceTextureClientHybris stc) | |
2375 | +{ | |
2376 | + REPORT_FUNCTION() | |
2377 | + | |
2378 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2379 | + if (d == NULL) | |
2380 | + return BAD_VALUE; | |
2381 | + if (stc == NULL) | |
2382 | + { | |
2383 | + ALOGE("stc must not be NULL"); | |
2384 | + return BAD_VALUE; | |
2385 | + } | |
2386 | + | |
2387 | + _SurfaceTextureClientHybris *stcu = static_cast<_SurfaceTextureClientHybris*>(stc); | |
2388 | + status_t err = native_window_api_connect(stcu, NATIVE_WINDOW_API_MEDIA); | |
2389 | + if (err != OK) | |
2390 | + { | |
2391 | + ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err); | |
2392 | + return err; | |
2393 | + } | |
2394 | + | |
2395 | + return OK; | |
2396 | +} | |
2397 | + | |
2398 | +int media_codec_queue_csd(MediaCodecDelegate delegate, MediaFormat format) | |
2399 | +{ | |
2400 | + REPORT_FUNCTION() | |
2401 | + | |
2402 | + if (format == NULL) | |
2403 | + { | |
2404 | + ALOGE("format must not be NULL"); | |
2405 | + return BAD_VALUE; | |
2406 | + } | |
2407 | + | |
2408 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2409 | + _MediaFormat *format_priv = static_cast<_MediaFormat*>(format); | |
2410 | + assert(format_priv->csd != NULL); | |
2411 | + | |
2412 | + status_t err = OK; | |
2413 | + | |
2414 | + Vector<sp<ABuffer> > input_bufs[1]; | |
2415 | + err = d->media_codec->getInputBuffers(&input_bufs[0]); | |
2416 | + CHECK_EQ(err, static_cast<status_t>(OK)); | |
2417 | + | |
2418 | + for (size_t i=0; i<2; ++i) | |
2419 | + { | |
2420 | + const sp<ABuffer> &srcBuffer = format_priv->csd; | |
2421 | + | |
2422 | + size_t index = 0; | |
2423 | + err = d->media_codec->dequeueInputBuffer(&index, -1ll); | |
2424 | + CHECK_EQ(err, static_cast<status_t>(OK)); | |
2425 | + | |
2426 | + const sp<ABuffer> &dstBuffer = input_bufs[0].itemAt(index); | |
2427 | + | |
2428 | + CHECK_LE(srcBuffer->size(), dstBuffer->capacity()); | |
2429 | + dstBuffer->setRange(0, srcBuffer->size()); | |
2430 | + memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size()); | |
2431 | + | |
2432 | + AString err_msg; | |
2433 | + err = d->media_codec->queueInputBuffer( | |
2434 | + index, | |
2435 | + 0, | |
2436 | + dstBuffer->size(), | |
2437 | + 0ll, | |
2438 | + MediaCodec::BUFFER_FLAG_CODECCONFIG); | |
2439 | + CHECK_EQ(err, static_cast<status_t>(OK)); | |
2440 | + } | |
2441 | + | |
2442 | + return err; | |
2443 | +} | |
2444 | + | |
2445 | +int media_codec_start(MediaCodecDelegate delegate) | |
2446 | +{ | |
2447 | + REPORT_FUNCTION() | |
2448 | + | |
2449 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2450 | + if (d == NULL) | |
2451 | + return BAD_VALUE; | |
2452 | + | |
2453 | + return d->media_codec->start(); | |
2454 | +} | |
2455 | + | |
2456 | +int media_codec_stop(MediaCodecDelegate delegate) | |
2457 | +{ | |
2458 | + REPORT_FUNCTION() | |
2459 | + | |
2460 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2461 | + if (d == NULL) | |
2462 | + return BAD_VALUE; | |
2463 | + | |
2464 | + return d->media_codec->stop(); | |
2465 | +} | |
2466 | + | |
2467 | +int media_codec_release(MediaCodecDelegate delegate) | |
2468 | +{ | |
2469 | + REPORT_FUNCTION() | |
2470 | + | |
2471 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2472 | + if (d == NULL) | |
2473 | + return BAD_VALUE; | |
2474 | + | |
2475 | + return d->media_codec->release(); | |
2476 | +} | |
2477 | + | |
2478 | +int media_codec_flush(MediaCodecDelegate delegate) | |
2479 | +{ | |
2480 | + REPORT_FUNCTION() | |
2481 | + | |
2482 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2483 | + if (d == NULL) | |
2484 | + return BAD_VALUE; | |
2485 | + | |
2486 | + d->available_output_buffer_infos.clear(); | |
2487 | + | |
2488 | + return d->media_codec->flush(); | |
2489 | +} | |
2490 | + | |
2491 | +size_t media_codec_get_input_buffers_size(MediaCodecDelegate delegate) | |
2492 | +{ | |
2493 | + REPORT_FUNCTION() | |
2494 | + | |
2495 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2496 | + if (d == NULL) | |
2497 | + return BAD_VALUE; | |
2498 | + | |
2499 | + status_t ret = d->media_codec->getInputBuffers(&d->input_buffers); | |
2500 | + if (ret != OK) | |
2501 | + { | |
2502 | + ALOGE("Failed to get input buffers size"); | |
2503 | + return 0; | |
2504 | + } | |
2505 | + ALOGD("Got %d input buffers", d->input_buffers.size()); | |
2506 | + | |
2507 | + return d->input_buffers.size(); | |
2508 | +} | |
2509 | + | |
2510 | +uint8_t *media_codec_get_nth_input_buffer(MediaCodecDelegate delegate, size_t n) | |
2511 | +{ | |
2512 | + REPORT_FUNCTION() | |
2513 | + | |
2514 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2515 | + if (d == NULL) | |
2516 | + return NULL; | |
2517 | + | |
2518 | + if (d->input_buffers.size() == 0) | |
2519 | + { | |
2520 | + status_t ret = d->media_codec->getInputBuffers(&d->input_buffers); | |
2521 | + if (ret != OK) | |
2522 | + { | |
2523 | + ALOGE("Failed to get input buffers"); | |
2524 | + return NULL; | |
2525 | + } | |
2526 | + } | |
2527 | + | |
2528 | + if (n > d->input_buffers.size()) | |
2529 | + { | |
2530 | + ALOGE("Failed to get %uth input buffer, n > total buffer size", n); | |
2531 | + return NULL; | |
2532 | + } | |
2533 | + | |
2534 | + return d->input_buffers.itemAt(n).get()->data(); | |
2535 | +} | |
2536 | + | |
2537 | +size_t media_codec_get_nth_input_buffer_capacity(MediaCodecDelegate delegate, size_t n) | |
2538 | +{ | |
2539 | + REPORT_FUNCTION() | |
2540 | + | |
2541 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2542 | + if (d == NULL) | |
2543 | + return BAD_VALUE; | |
2544 | + | |
2545 | + Vector<sp<ABuffer> > input_buffers; | |
2546 | + status_t ret = d->media_codec->getInputBuffers(&input_buffers); | |
2547 | + if (ret != OK) | |
2548 | + { | |
2549 | + ALOGE("Failed to get input buffers"); | |
2550 | + return 0; | |
2551 | + } | |
2552 | + | |
2553 | + if (n > input_buffers.size()) | |
2554 | + { | |
2555 | + ALOGE("Failed to get %uth input buffer capacity, n > total buffer size", n); | |
2556 | + return 0; | |
2557 | + } | |
2558 | + | |
2559 | + return input_buffers[n].get()->capacity(); | |
2560 | +} | |
2561 | + | |
2562 | +size_t media_codec_get_output_buffers_size(MediaCodecDelegate delegate) | |
2563 | +{ | |
2564 | + REPORT_FUNCTION() | |
2565 | + | |
2566 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2567 | + if (d == NULL) | |
2568 | + return BAD_VALUE; | |
2569 | + | |
2570 | + status_t ret = d->media_codec->getOutputBuffers(&d->output_buffers); | |
2571 | + if (ret != OK) | |
2572 | + { | |
2573 | + ALOGE("Failed to get output buffers size"); | |
2574 | + return 0; | |
2575 | + } | |
2576 | + ALOGD("Got %d output buffers", d->output_buffers.size()); | |
2577 | + | |
2578 | + return d->output_buffers.size(); | |
2579 | +} | |
2580 | + | |
2581 | +uint8_t *media_codec_get_nth_output_buffer(MediaCodecDelegate delegate, size_t n) | |
2582 | +{ | |
2583 | + REPORT_FUNCTION() | |
2584 | + | |
2585 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2586 | + if (d == NULL) | |
2587 | + return NULL; | |
2588 | + | |
2589 | + status_t ret = d->media_codec->getOutputBuffers(&d->output_buffers); | |
2590 | + if (ret != OK) | |
2591 | + { | |
2592 | + ALOGE("Failed to get output buffers"); | |
2593 | + return NULL; | |
2594 | + } | |
2595 | + | |
2596 | + if (n > d->output_buffers.size()) | |
2597 | + { | |
2598 | + ALOGE("Failed to get %uth output buffer, n > total buffer size", n); | |
2599 | + return NULL; | |
2600 | + } | |
2601 | + | |
2602 | + return d->output_buffers.itemAt(n).get()->data(); | |
2603 | +} | |
2604 | + | |
2605 | +size_t media_codec_get_nth_output_buffer_capacity(MediaCodecDelegate delegate, size_t n) | |
2606 | +{ | |
2607 | + REPORT_FUNCTION() | |
2608 | + | |
2609 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2610 | + if (d == NULL) | |
2611 | + return BAD_VALUE; | |
2612 | + | |
2613 | + status_t ret = d->media_codec->getOutputBuffers(&d->output_buffers); | |
2614 | + if (ret != OK) | |
2615 | + { | |
2616 | + ALOGE("Failed to get output buffers"); | |
2617 | + return 0; | |
2618 | + } | |
2619 | + | |
2620 | + if (n > d->output_buffers.size()) | |
2621 | + { | |
2622 | + ALOGE("Failed to get %uth output buffer capacity, n > total buffer size", n); | |
2623 | + return 0; | |
2624 | + } | |
2625 | + | |
2626 | + return d->output_buffers[n].get()->capacity(); | |
2627 | +} | |
2628 | + | |
2629 | +#define INFO_TRY_AGAIN_LATER -1 | |
2630 | +#define INFO_OUTPUT_FORMAT_CHANGED -2 | |
2631 | +#define INFO_OUTPUT_BUFFERS_CHANGED -4 | |
2632 | + | |
2633 | +int media_codec_dequeue_output_buffer(MediaCodecDelegate delegate, MediaCodecBufferInfo *info, int64_t timeout_us) | |
2634 | +{ | |
2635 | + REPORT_FUNCTION() | |
2636 | + | |
2637 | + if (info == NULL) | |
2638 | + { | |
2639 | + ALOGE("info must not be NULL"); | |
2640 | + return BAD_VALUE; | |
2641 | + } | |
2642 | + | |
2643 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2644 | + if (d == NULL) | |
2645 | + return BAD_VALUE; | |
2646 | + | |
2647 | + int ret = d->media_codec->dequeueOutputBuffer(&info->index, &info->offset, &info->size, &info->presentation_time_us, &info->flags, timeout_us); | |
2648 | + ALOGD("dequeueOutputBuffer() ret: %d", ret); | |
2649 | + info->render_retries = 0; | |
2650 | + | |
2651 | + if (ret == -EAGAIN) | |
2652 | + { | |
2653 | + ALOGD("dequeueOutputBuffer returned %d", ret); | |
2654 | + return INFO_TRY_AGAIN_LATER; | |
2655 | + } | |
2656 | + else if (ret & ~INFO_OUTPUT_BUFFERS_CHANGED) | |
2657 | + { | |
2658 | + ALOGD("Output buffers changed (ret: %d)", ret); | |
2659 | + return INFO_OUTPUT_BUFFERS_CHANGED + 1; | |
2660 | + } | |
2661 | + // FIXME: Get rid of the hardcoded -10 and replace with more elegant solution | |
2662 | + else if (ret & ~(INFO_FORMAT_CHANGED - 10)) | |
2663 | + { | |
2664 | + ALOGD("Output buffer format changed (ret: %d)", ret); | |
2665 | + d->output_format_changed = true; | |
2666 | + return -2; | |
2667 | + } | |
2668 | + | |
2669 | + ALOGD("Dequeued output buffer:\n-----------------------"); | |
2670 | + ALOGD("index: %u", info->index); | |
2671 | + ALOGD("offset: %d", info->offset); | |
2672 | + ALOGD("size: %d", info->size); | |
2673 | + ALOGD("presentation_time_us: %lld", info->presentation_time_us); | |
2674 | + ALOGD("flags: %d", info->flags); | |
2675 | + | |
2676 | + // Keep track of the used output buffer info | |
2677 | + d->available_output_buffer_infos.push_back(*info); | |
2678 | + | |
2679 | + return OK; | |
2680 | +} | |
2681 | + | |
2682 | +int media_codec_queue_input_buffer(MediaCodecDelegate delegate, const MediaCodecBufferInfo *info) | |
2683 | +{ | |
2684 | + REPORT_FUNCTION() | |
2685 | + | |
2686 | + if (info == NULL) | |
2687 | + { | |
2688 | + ALOGE("info must not be NULL"); | |
2689 | + return BAD_VALUE; | |
2690 | + } | |
2691 | + | |
2692 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2693 | + if (d == NULL) | |
2694 | + return BAD_VALUE; | |
2695 | + | |
2696 | + // Make sure that there is at least one dequeued input buffer available | |
2697 | + if (d->available_input_buffer_indices.empty()) | |
2698 | + { | |
2699 | + ALOGE("Input buffer index %d has not been dequeued, cannot queue input buffer", info->index); | |
2700 | + return BAD_VALUE; | |
2701 | + } | |
2702 | + | |
2703 | + const size_t index = *d->available_input_buffer_indices.begin(); | |
2704 | + d->available_input_buffer_indices.erase(d->available_input_buffer_indices.begin()); | |
2705 | + | |
2706 | + ALOGD("info->index: %d", index); | |
2707 | + ALOGD("info->offset: %d", info->offset); | |
2708 | + ALOGD("info->size: %d", info->size); | |
2709 | + ALOGD("info->presentation_time_us: %lld", info->presentation_time_us); | |
2710 | + ALOGD("info->flags: %d", info->flags); | |
2711 | + | |
2712 | + AString err_msg; | |
2713 | + status_t ret = d->media_codec->queueInputBuffer(index, info->offset, info->size, | |
2714 | + info->presentation_time_us, info->flags, &err_msg); | |
2715 | + if (ret != OK) | |
2716 | + { | |
2717 | + ALOGE("Failed to queue input buffer (err: %d, index: %d)", ret, index); | |
2718 | + ALOGE("Detailed error message: %s", err_msg.c_str()); | |
2719 | + } | |
2720 | + | |
2721 | + return ret; | |
2722 | +} | |
2723 | + | |
2724 | +int media_codec_dequeue_input_buffer(MediaCodecDelegate delegate, size_t *index, int64_t timeout_us) | |
2725 | +{ | |
2726 | + REPORT_FUNCTION() | |
2727 | + | |
2728 | + if (index == NULL) | |
2729 | + { | |
2730 | + ALOGE("index must not be NULL"); | |
2731 | + return BAD_VALUE; | |
2732 | + } | |
2733 | + | |
2734 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2735 | + if (d == NULL) | |
2736 | + return BAD_VALUE; | |
2737 | + | |
2738 | + status_t ret = d->media_codec->dequeueInputBuffer(index, timeout_us); | |
2739 | + if (ret == -EAGAIN) | |
2740 | + { | |
2741 | + ALOGD("dequeueInputBuffer returned %d, tried timeout: %d", ret, timeout_us); | |
2742 | + return INFO_TRY_AGAIN_LATER; | |
2743 | + } | |
2744 | + else if (ret == OK) | |
2745 | + { | |
2746 | + ALOGD("Dequeued input buffer (index: %d)", *index); | |
2747 | + d->available_input_buffer_indices.push_back(*index); | |
2748 | + } | |
2749 | + else | |
2750 | + ALOGE("Failed to dequeue input buffer (err: %d, index: %d)", ret, *index); | |
2751 | + | |
2752 | + return ret; | |
2753 | +} | |
2754 | + | |
2755 | +int media_codec_release_output_buffer(MediaCodecDelegate delegate, size_t index, uint8_t render) | |
2756 | +{ | |
2757 | + REPORT_FUNCTION() | |
2758 | + ALOGV("Requesting to release output buffer index: %d, render: %d", index, render); | |
2759 | + | |
2760 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2761 | + if (d == NULL) | |
2762 | + return BAD_VALUE; | |
2763 | + | |
2764 | + status_t ret = OK; | |
2765 | + | |
2766 | + auto it = d->available_output_buffer_infos.begin(); | |
2767 | + while (it != d->available_output_buffer_infos.end()) | |
2768 | + { | |
2769 | + MediaCodecBufferInfo *info = &*it; | |
2770 | + ALOGD("info index: %d", info->index); | |
2771 | + ALOGD("info render_retries: %u", info->render_retries); | |
2772 | + if (info->render_retries == 1) | |
2773 | + { | |
2774 | + ALOGV("Rendering and releasing output buffer %d from the available indices list", info->index); | |
2775 | + ret = d->media_codec->renderOutputBufferAndRelease(info->index); | |
2776 | + if (ret != OK) | |
2777 | + { | |
2778 | + ALOGE("Failed to release output buffer (ret: %d, index: %d)", ret, info->index); | |
2779 | + ++info->render_retries; | |
2780 | + } | |
2781 | + else | |
2782 | + { | |
2783 | + ALOGV("Successfully rendered output buffer %d on a second try.", info->index); | |
2784 | + d->available_output_buffer_infos.erase(it); | |
2785 | + } | |
2786 | + } | |
2787 | + else if (info->render_retries > 1) | |
2788 | + { | |
2789 | + ALOGV("Tried to render output buffer %d twice, dropping.", info->index); | |
2790 | + ret = d->media_codec->releaseOutputBuffer(info->index); | |
2791 | + d->available_output_buffer_infos.erase(d->available_output_buffer_infos.begin()); | |
2792 | + } | |
2793 | + | |
2794 | + ++it; | |
2795 | + } | |
2796 | + | |
2797 | + MediaCodecBufferInfo *info = &*d->available_output_buffer_infos.begin(); | |
2798 | + // Either render and release the output buffer, or just release. | |
2799 | + if (render) | |
2800 | + { | |
2801 | + ALOGV("Rendering and releasing output buffer %d from the available indices list", info->index); | |
2802 | + ret = d->media_codec->renderOutputBufferAndRelease(info->index); | |
2803 | + } | |
2804 | + else | |
2805 | + { | |
2806 | + ALOGV("Releasing output buffer %d from the available indices list", info->index); | |
2807 | + ret = d->media_codec->releaseOutputBuffer(info->index); | |
2808 | + } | |
2809 | + if (ret != OK) | |
2810 | + { | |
2811 | + ALOGE("Failed to release output buffer (ret: %d, index: %d)", ret, info->index); | |
2812 | + ++info->render_retries; | |
2813 | + } else { | |
2814 | + ALOGV("Released output buffer %d from the available buffer infos list", info->index); | |
2815 | + d->available_output_buffer_infos.erase(d->available_output_buffer_infos.begin()); | |
2816 | + } | |
2817 | + | |
2818 | + return ret; | |
2819 | +} | |
2820 | + | |
2821 | +MediaFormat media_codec_get_output_format(MediaCodecDelegate delegate) | |
2822 | +{ | |
2823 | + REPORT_FUNCTION() | |
2824 | + | |
2825 | + _MediaCodecDelegate *d = get_internal_delegate(delegate); | |
2826 | + if (d == NULL) | |
2827 | + return NULL; | |
2828 | + | |
2829 | + _MediaFormat *f = new _MediaFormat(); | |
2830 | + | |
2831 | + sp<AMessage> msg_format; | |
2832 | + status_t ret = d->media_codec->getOutputFormat(&msg_format); | |
2833 | + if (ret != OK) | |
2834 | + { | |
2835 | + ALOGE("Failed to get the output format"); | |
2836 | + return NULL; | |
2837 | + } | |
2838 | + | |
2839 | + ALOGD("Output format: %s", msg_format->debugString().c_str()); | |
2840 | + | |
2841 | + CHECK(msg_format->findString("mime", &f->mime)); | |
2842 | + CHECK(msg_format->findInt32("width", &f->width)); | |
2843 | + CHECK(msg_format->findInt32("height", &f->height)); | |
2844 | + CHECK(msg_format->findInt32("stride", &f->stride)); | |
2845 | + CHECK(msg_format->findInt32("slice-height", &f->slice_height)); | |
2846 | + CHECK(msg_format->findInt32("color-format", &f->color_format)); | |
2847 | + Rect crop; | |
2848 | + CHECK(msg_format->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)); | |
2849 | + | |
2850 | + return f; | |
2851 | +} | |
2852 | --- /dev/null | |
2853 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_codec_list.cpp | |
2854 | @@ -0,0 +1,228 @@ | |
2855 | +/* | |
2856 | + * Copyright (C) 2013 Canonical Ltd | |
2857 | + * | |
2858 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
2859 | + * you may not use this file except in compliance with the License. | |
2860 | + * You may obtain a copy of the License at | |
2861 | + * | |
2862 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
2863 | + * | |
2864 | + * Unless required by applicable law or agreed to in writing, software | |
2865 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
2866 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
2867 | + * See the License for the specific language governing permissions and | |
2868 | + * limitations under the License. | |
2869 | + * | |
2870 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
2871 | + */ | |
2872 | + | |
2873 | +// Uncomment to enable verbose debug output | |
2874 | +#define LOG_NDEBUG 0 | |
2875 | + | |
2876 | +#undef LOG_TAG | |
2877 | +#define LOG_TAG "MediaCodecList" | |
2878 | + | |
2879 | +#include <hybris/media/media_codec_list.h> | |
2880 | + | |
2881 | +#include <media/stagefright/foundation/AString.h> | |
2882 | +#include <media/stagefright/MediaCodecList.h> | |
2883 | + | |
2884 | +#include <utils/Log.h> | |
2885 | +#include <utils/Vector.h> | |
2886 | + | |
2887 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); | |
2888 | + | |
2889 | +using namespace android; | |
2890 | + | |
2891 | +ssize_t media_codec_list_find_codec_by_type(const char *type, bool encoder, size_t startIndex) | |
2892 | +{ | |
2893 | + REPORT_FUNCTION() | |
2894 | + return MediaCodecList::getInstance()->findCodecByType(type, encoder, startIndex); | |
2895 | +} | |
2896 | + | |
2897 | +ssize_t media_codec_list_find_codec_by_name(const char *name) | |
2898 | +{ | |
2899 | + REPORT_FUNCTION() | |
2900 | + return MediaCodecList::getInstance()->findCodecByName(name); | |
2901 | +} | |
2902 | + | |
2903 | +size_t media_codec_list_count_codecs() | |
2904 | +{ | |
2905 | + REPORT_FUNCTION() | |
2906 | + return MediaCodecList::getInstance()->countCodecs(); | |
2907 | +} | |
2908 | + | |
2909 | +void media_codec_list_get_codec_info_at_id(size_t index) | |
2910 | +{ | |
2911 | + REPORT_FUNCTION() | |
2912 | +} | |
2913 | + | |
2914 | +const char *media_codec_list_get_codec_name(size_t index) | |
2915 | +{ | |
2916 | + REPORT_FUNCTION() | |
2917 | + return MediaCodecList::getInstance()->getCodecName(index); | |
2918 | +} | |
2919 | + | |
2920 | +bool media_codec_list_is_encoder(size_t index) | |
2921 | +{ | |
2922 | + REPORT_FUNCTION() | |
2923 | + return MediaCodecList::getInstance()->isEncoder(index); | |
2924 | +} | |
2925 | + | |
2926 | +size_t media_codec_list_get_num_supported_types(size_t index) | |
2927 | +{ | |
2928 | + REPORT_FUNCTION() | |
2929 | + | |
2930 | + Vector<AString> types; | |
2931 | + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); | |
2932 | + if (err != OK) | |
2933 | + { | |
2934 | + ALOGE("Failed to get the number of supported codec types (err: %d)", err); | |
2935 | + return 0; | |
2936 | + } | |
2937 | + ALOGD("Number of supported codec types: %d", types.size()); | |
2938 | + | |
2939 | + return types.size(); | |
2940 | +} | |
2941 | + | |
2942 | +size_t media_codec_list_get_nth_supported_type_len(size_t index, size_t n) | |
2943 | +{ | |
2944 | + REPORT_FUNCTION() | |
2945 | + | |
2946 | + Vector<AString> types; | |
2947 | + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); | |
2948 | + | |
2949 | + return types[n].size(); | |
2950 | +} | |
2951 | + | |
2952 | +int media_codec_list_get_nth_supported_type(size_t index, char *type, size_t n) | |
2953 | +{ | |
2954 | + REPORT_FUNCTION() | |
2955 | + | |
2956 | + if (type == NULL) | |
2957 | + { | |
2958 | + ALOGE("types must not be NULL"); | |
2959 | + return BAD_VALUE; | |
2960 | + } | |
2961 | + | |
2962 | + Vector<AString> types; | |
2963 | + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); | |
2964 | + for (size_t i=0; i<types[n].size(); ++i) | |
2965 | + type[i] = types.itemAt(n).c_str()[i]; | |
2966 | + | |
2967 | + return err; | |
2968 | +} | |
2969 | + | |
2970 | +static void media_codec_list_get_num_codec_capabilities(size_t index, const char *type, size_t *num_profile_levels, size_t *num_color_formats) | |
2971 | +{ | |
2972 | + REPORT_FUNCTION() | |
2973 | + | |
2974 | + Vector<MediaCodecList::ProfileLevel> profile_levels; | |
2975 | + Vector<uint32_t> color_formats; | |
2976 | + ALOGD("index: %d, type: '%s'", index, type); | |
2977 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
2978 | + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &color_formats); | |
2979 | +#else | |
2980 | + uint32_t flags; | |
2981 | + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &color_formats, &flags); | |
2982 | +#endif | |
2983 | + if (err != OK) | |
2984 | + { | |
2985 | + ALOGE("Failed to get the number of supported codec capabilities (err: %d)", err); | |
2986 | + return; | |
2987 | + } | |
2988 | + | |
2989 | + if (num_profile_levels != NULL) | |
2990 | + { | |
2991 | + ALOGD("Number of codec profile levels: %d", profile_levels.size()); | |
2992 | + *num_profile_levels = profile_levels.size(); | |
2993 | + } | |
2994 | + if (num_color_formats != NULL) | |
2995 | + { | |
2996 | + ALOGD("Number of codec color formats: %d", color_formats.size()); | |
2997 | + *num_color_formats = color_formats.size(); | |
2998 | + } | |
2999 | +} | |
3000 | + | |
3001 | +size_t media_codec_list_get_num_profile_levels(size_t index, const char *type) | |
3002 | +{ | |
3003 | + REPORT_FUNCTION() | |
3004 | + | |
3005 | + size_t num = 0; | |
3006 | + media_codec_list_get_num_codec_capabilities(index, type, &num, NULL); | |
3007 | + | |
3008 | + return num; | |
3009 | +} | |
3010 | + | |
3011 | +size_t media_codec_list_get_num_color_formats(size_t index, const char *type) | |
3012 | +{ | |
3013 | + REPORT_FUNCTION() | |
3014 | + | |
3015 | + size_t num = 0; | |
3016 | + media_codec_list_get_num_codec_capabilities(index, type, NULL, &num); | |
3017 | + | |
3018 | + return num; | |
3019 | +} | |
3020 | + | |
3021 | +int media_codec_list_get_nth_codec_profile_level(size_t index, const char *type, profile_level *pro_level, size_t n) | |
3022 | +{ | |
3023 | + REPORT_FUNCTION() | |
3024 | + | |
3025 | + if (type == NULL) | |
3026 | + { | |
3027 | + ALOGE("types must not be NULL"); | |
3028 | + return BAD_VALUE; | |
3029 | + } | |
3030 | + | |
3031 | + if (pro_level == NULL) | |
3032 | + { | |
3033 | + ALOGE("pro_level must not be NULL"); | |
3034 | + return BAD_VALUE; | |
3035 | + } | |
3036 | + | |
3037 | + Vector<MediaCodecList::ProfileLevel> profile_levels; | |
3038 | + Vector<uint32_t> formats; | |
3039 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
3040 | + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats); | |
3041 | +#else | |
3042 | + uint32_t flags; | |
3043 | + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats, &flags); | |
3044 | +#endif | |
3045 | + if (err != OK) | |
3046 | + { | |
3047 | + ALOGE("Failed to get the nth codec profile level (err: %d)", err); | |
3048 | + return 0; | |
3049 | + } | |
3050 | + | |
3051 | + pro_level->profile = profile_levels[n].mProfile; | |
3052 | + pro_level->level = profile_levels[n].mLevel; | |
3053 | + | |
3054 | + return err; | |
3055 | +} | |
3056 | + | |
3057 | +int media_codec_list_get_codec_color_formats(size_t index, const char *type, uint32_t *color_formats) | |
3058 | +{ | |
3059 | + REPORT_FUNCTION() | |
3060 | + | |
3061 | + Vector<MediaCodecList::ProfileLevel> profile_levels; | |
3062 | + Vector<uint32_t> formats; | |
3063 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
3064 | + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats); | |
3065 | +#else | |
3066 | + uint32_t flags; | |
3067 | + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats, &flags); | |
3068 | +#endif | |
3069 | + if (err != OK) | |
3070 | + { | |
3071 | + ALOGE("Failed to get the number of supported codec types (err: %d)", err); | |
3072 | + return 0; | |
3073 | + } | |
3074 | + | |
3075 | + for (size_t i=0; i<formats.size(); ++i) | |
3076 | + { | |
3077 | + color_formats[i] = formats[i]; | |
3078 | + ALOGD("Color format [%d]: %d", i, formats[i]); | |
3079 | + } | |
3080 | + | |
3081 | + return OK; | |
3082 | +} | |
3083 | --- /dev/null | |
3084 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_compatibility_layer.cpp | |
3085 | @@ -0,0 +1,660 @@ | |
3086 | +/* | |
3087 | + * Copyright (C) 2013 Canonical Ltd | |
3088 | + * | |
3089 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
3090 | + * you may not use this file except in compliance with the License. | |
3091 | + * You may obtain a copy of the License at | |
3092 | + * | |
3093 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
3094 | + * | |
3095 | + * Unless required by applicable law or agreed to in writing, software | |
3096 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
3097 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
3098 | + * See the License for the specific language governing permissions and | |
3099 | + * limitations under the License. | |
3100 | + * | |
3101 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
3102 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
3103 | + */ | |
3104 | + | |
3105 | +// Uncomment to enable verbose debug output | |
3106 | +#define LOG_NDEBUG 0 | |
3107 | + | |
3108 | +#undef LOG_TAG | |
3109 | +#define LOG_TAG "MediaCompatibilityLayer" | |
3110 | + | |
3111 | +#include <hybris/media/media_compatibility_layer.h> | |
3112 | + | |
3113 | +#include <fcntl.h> | |
3114 | +#include <sys/stat.h> | |
3115 | + | |
3116 | +#include <media/mediaplayer.h> | |
3117 | + | |
3118 | +#include <binder/ProcessState.h> | |
3119 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
3120 | +#include <gui/SurfaceTexture.h> | |
3121 | +#else | |
3122 | +#include <gui/GLConsumer.h> | |
3123 | +#endif | |
3124 | + | |
3125 | +#include <GLES2/gl2.h> | |
3126 | +#include <GLES2/gl2ext.h> | |
3127 | + | |
3128 | +#include <ui/GraphicBuffer.h> | |
3129 | + | |
3130 | +#include <utils/Log.h> | |
3131 | + | |
3132 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) | |
3133 | + | |
3134 | +namespace android | |
3135 | +{ | |
3136 | +NativeBufferAlloc::NativeBufferAlloc() { | |
3137 | +} | |
3138 | + | |
3139 | +NativeBufferAlloc::~NativeBufferAlloc() { | |
3140 | +} | |
3141 | + | |
3142 | +sp<GraphicBuffer> NativeBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, | |
3143 | + PixelFormat format, uint32_t usage, status_t* error) { | |
3144 | + sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); | |
3145 | + status_t err = graphicBuffer->initCheck(); | |
3146 | + *error = err; | |
3147 | + if (err != 0 || graphicBuffer->handle == 0) { | |
3148 | + if (err == NO_MEMORY) { | |
3149 | + GraphicBuffer::dumpAllocationsToSystemLog(); | |
3150 | + } | |
3151 | + ALOGI("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " | |
3152 | + "failed (%s), handle=%p", | |
3153 | + w, h, strerror(-err), graphicBuffer->handle); | |
3154 | + return 0; | |
3155 | + } | |
3156 | + return graphicBuffer; | |
3157 | +} | |
3158 | +} | |
3159 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
3160 | +struct FrameAvailableListener : public android::SurfaceTexture::FrameAvailableListener | |
3161 | +#else | |
3162 | +struct FrameAvailableListener : public android::GLConsumer::FrameAvailableListener | |
3163 | +#endif | |
3164 | +{ | |
3165 | + public: | |
3166 | + FrameAvailableListener() | |
3167 | + : set_video_texture_needs_update_cb(NULL), | |
3168 | + video_texture_needs_update_context(NULL) | |
3169 | + { | |
3170 | + } | |
3171 | + | |
3172 | + // From android::GLConsumer/SurfaceTexture::FrameAvailableListener | |
3173 | + void onFrameAvailable() | |
3174 | + { | |
3175 | + if (set_video_texture_needs_update_cb != NULL) | |
3176 | + set_video_texture_needs_update_cb(video_texture_needs_update_context); | |
3177 | + } | |
3178 | + | |
3179 | + void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context) | |
3180 | + { | |
3181 | + set_video_texture_needs_update_cb = cb; | |
3182 | + video_texture_needs_update_context = context; | |
3183 | + } | |
3184 | + | |
3185 | + private: | |
3186 | + on_video_texture_needs_update set_video_texture_needs_update_cb; | |
3187 | + void *video_texture_needs_update_context; | |
3188 | +}; | |
3189 | + | |
3190 | +class MediaPlayerListenerWrapper : public android::MediaPlayerListener | |
3191 | +{ | |
3192 | + public: | |
3193 | + MediaPlayerListenerWrapper() | |
3194 | + : set_video_size_cb(NULL), | |
3195 | + video_size_context(NULL), | |
3196 | + error_cb(NULL), | |
3197 | + error_context(NULL), | |
3198 | + playback_complete_cb(NULL), | |
3199 | + playback_complete_context(NULL), | |
3200 | + media_prepared_cb(NULL), | |
3201 | + media_prepared_context(NULL) | |
3202 | + { | |
3203 | + } | |
3204 | + | |
3205 | + void notify(int msg, int ext1, int ext2, const android::Parcel *obj) | |
3206 | + { | |
3207 | + ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2); | |
3208 | + | |
3209 | + switch (msg) { | |
3210 | + case android::MEDIA_PREPARED: | |
3211 | + ALOGV("\tMEDIA_PREPARED msg\n"); | |
3212 | + if (media_prepared_cb != NULL) | |
3213 | + media_prepared_cb(media_prepared_context); | |
3214 | + else | |
3215 | + ALOGW("Failed to signal media prepared, callback not set."); | |
3216 | + break; | |
3217 | + case android::MEDIA_PLAYBACK_COMPLETE: | |
3218 | + ALOGV("\tMEDIA_PLAYBACK_COMPLETE msg\n"); | |
3219 | + if (playback_complete_cb != NULL) | |
3220 | + playback_complete_cb(playback_complete_context); | |
3221 | + else | |
3222 | + ALOGW("Failed to signal end of playback, callback not set."); | |
3223 | + break; | |
3224 | + case android::MEDIA_BUFFERING_UPDATE: | |
3225 | + ALOGV("\tMEDIA_BUFFERING_UPDATE msg\n"); | |
3226 | + break; | |
3227 | + case android::MEDIA_SEEK_COMPLETE: | |
3228 | + ALOGV("\tMEDIA_SEEK_COMPLETE msg\n"); | |
3229 | + break; | |
3230 | + case android::MEDIA_SET_VIDEO_SIZE: | |
3231 | + ALOGV("\tMEDIA_SET_VIDEO_SIZE msg\n"); | |
3232 | + if (set_video_size_cb != NULL) | |
3233 | + set_video_size_cb(ext2, ext1, video_size_context); | |
3234 | + else | |
3235 | + ALOGE("Failed to set video size. set_video_size_cb is NULL."); | |
3236 | + break; | |
3237 | + case android::MEDIA_TIMED_TEXT: | |
3238 | + ALOGV("\tMEDIA_TIMED_TEXT msg\n"); | |
3239 | + break; | |
3240 | + case android::MEDIA_ERROR: | |
3241 | + ALOGV("\tMEDIA_ERROR msg\n"); | |
3242 | + // TODO: Extend this cb to include the error message | |
3243 | + if (error_cb != NULL) | |
3244 | + error_cb(error_context); | |
3245 | + else | |
3246 | + ALOGE("Failed to signal error to app layer, callback not set."); | |
3247 | + break; | |
3248 | + case android::MEDIA_INFO: | |
3249 | + ALOGV("\tMEDIA_INFO msg\n"); | |
3250 | + break; | |
3251 | + default: | |
3252 | + ALOGV("\tUnknown media msg\n"); | |
3253 | + } | |
3254 | + } | |
3255 | + | |
3256 | + void setVideoSizeCb(on_msg_set_video_size cb, void *context) | |
3257 | + { | |
3258 | + REPORT_FUNCTION(); | |
3259 | + | |
3260 | + set_video_size_cb = cb; | |
3261 | + video_size_context = context; | |
3262 | + } | |
3263 | + | |
3264 | + void setErrorCb(on_msg_error cb, void *context) | |
3265 | + { | |
3266 | + REPORT_FUNCTION(); | |
3267 | + | |
3268 | + error_cb = cb; | |
3269 | + error_context = context; | |
3270 | + } | |
3271 | + | |
3272 | + void setPlaybackCompleteCb(on_playback_complete cb, void *context) | |
3273 | + { | |
3274 | + REPORT_FUNCTION(); | |
3275 | + | |
3276 | + playback_complete_cb = cb; | |
3277 | + playback_complete_context = context; | |
3278 | + } | |
3279 | + | |
3280 | + void setMediaPreparedCb(on_media_prepared cb, void *context) | |
3281 | + { | |
3282 | + REPORT_FUNCTION(); | |
3283 | + | |
3284 | + media_prepared_cb = cb; | |
3285 | + media_prepared_context = context; | |
3286 | + } | |
3287 | + | |
3288 | + private: | |
3289 | + on_msg_set_video_size set_video_size_cb; | |
3290 | + void *video_size_context; | |
3291 | + on_msg_error error_cb; | |
3292 | + void *error_context; | |
3293 | + on_playback_complete playback_complete_cb; | |
3294 | + void *playback_complete_context; | |
3295 | + on_media_prepared media_prepared_cb; | |
3296 | + void *media_prepared_context; | |
3297 | +}; | |
3298 | + | |
3299 | +// ----- MediaPlayer Wrapper ----- // | |
3300 | + | |
3301 | +struct MediaPlayerWrapper : public android::MediaPlayer | |
3302 | +{ | |
3303 | + public: | |
3304 | + MediaPlayerWrapper() | |
3305 | + : MediaPlayer(), | |
3306 | + texture(NULL), | |
3307 | + media_player_listener(new MediaPlayerListenerWrapper()), | |
3308 | + frame_listener(new FrameAvailableListener), | |
3309 | + left_volume(1), // Set vol to 100% for this track by default | |
3310 | + right_volume(1), | |
3311 | + source_fd(-1) | |
3312 | + { | |
3313 | + setListener(media_player_listener); | |
3314 | + // Update the live volume with the cached values | |
3315 | + MediaPlayer::setVolume(left_volume, right_volume); | |
3316 | + } | |
3317 | + | |
3318 | + ~MediaPlayerWrapper() | |
3319 | + { | |
3320 | + reset(); | |
3321 | + source_fd = -1; | |
3322 | + } | |
3323 | + | |
3324 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
3325 | + android::status_t setVideoSurfaceTexture(const android::sp<android::SurfaceTexture> &surfaceTexture) | |
3326 | +#else | |
3327 | + android::status_t setVideoSurfaceTexture(android::sp<android::BufferQueue> bq, const android::sp<android::GLConsumer> &surfaceTexture) | |
3328 | +#endif | |
3329 | + { | |
3330 | + REPORT_FUNCTION(); | |
3331 | + | |
3332 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
3333 | + surfaceTexture->getBufferQueue()->setBufferCount(5); | |
3334 | +#else | |
3335 | + bq->setBufferCount(5); | |
3336 | +#endif | |
3337 | + texture = surfaceTexture; | |
3338 | + texture->setFrameAvailableListener(frame_listener); | |
3339 | + | |
3340 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
3341 | + return MediaPlayer::setVideoSurfaceTexture(surfaceTexture->getBufferQueue()); | |
3342 | +#else | |
3343 | + return MediaPlayer::setVideoSurfaceTexture(bq); | |
3344 | +#endif | |
3345 | + } | |
3346 | + | |
3347 | + void updateGLConsumer() | |
3348 | + { | |
3349 | + assert(texture != NULL); | |
3350 | + texture->updateTexImage(); | |
3351 | + } | |
3352 | + | |
3353 | + void get_transformation_matrix_for_surface_texture(GLfloat* matrix) | |
3354 | + { | |
3355 | + assert(texture != NULL); | |
3356 | + texture->getTransformMatrix(matrix); | |
3357 | + } | |
3358 | + | |
3359 | + void setVideoSizeCb(on_msg_set_video_size cb, void *context) | |
3360 | + { | |
3361 | + REPORT_FUNCTION(); | |
3362 | + | |
3363 | + assert(media_player_listener != NULL); | |
3364 | + media_player_listener->setVideoSizeCb(cb, context); | |
3365 | + } | |
3366 | + | |
3367 | + void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context) | |
3368 | + { | |
3369 | + REPORT_FUNCTION(); | |
3370 | + | |
3371 | + assert(frame_listener != NULL); | |
3372 | + frame_listener->setVideoTextureNeedsUpdateCb(cb, context); | |
3373 | + } | |
3374 | + | |
3375 | + void setErrorCb(on_msg_error cb, void *context) | |
3376 | + { | |
3377 | + REPORT_FUNCTION(); | |
3378 | + | |
3379 | + assert(media_player_listener != NULL); | |
3380 | + media_player_listener->setErrorCb(cb, context); | |
3381 | + } | |
3382 | + | |
3383 | + void setPlaybackCompleteCb(on_playback_complete cb, void *context) | |
3384 | + { | |
3385 | + REPORT_FUNCTION(); | |
3386 | + | |
3387 | + assert(media_player_listener != NULL); | |
3388 | + media_player_listener->setPlaybackCompleteCb(cb, context); | |
3389 | + } | |
3390 | + | |
3391 | + void setMediaPreparedCb(on_media_prepared cb, void *context) | |
3392 | + { | |
3393 | + REPORT_FUNCTION(); | |
3394 | + | |
3395 | + assert(media_player_listener != NULL); | |
3396 | + media_player_listener->setMediaPreparedCb(cb, context); | |
3397 | + } | |
3398 | + | |
3399 | + void getVolume(float *leftVolume, float *rightVolume) | |
3400 | + { | |
3401 | + *leftVolume = left_volume; | |
3402 | + *rightVolume = right_volume; | |
3403 | + } | |
3404 | + | |
3405 | + android::status_t setVolume(float leftVolume, float rightVolume) | |
3406 | + { | |
3407 | + REPORT_FUNCTION(); | |
3408 | + | |
3409 | + left_volume = leftVolume; | |
3410 | + right_volume = rightVolume; | |
3411 | + return MediaPlayer::setVolume(leftVolume, rightVolume); | |
3412 | + } | |
3413 | + | |
3414 | + int getSourceFd() const { return source_fd; } | |
3415 | + void setSourceFd(int fd) { source_fd = fd; } | |
3416 | + | |
3417 | + private: | |
3418 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
3419 | + android::sp<android::SurfaceTexture> texture; | |
3420 | +#else | |
3421 | + android::sp<android::GLConsumer> texture; | |
3422 | +#endif | |
3423 | + android::sp<MediaPlayerListenerWrapper> media_player_listener; | |
3424 | + android::sp<FrameAvailableListener> frame_listener; | |
3425 | + float left_volume; | |
3426 | + float right_volume; | |
3427 | + int source_fd; | |
3428 | +}; // MediaPlayerWrapper | |
3429 | + | |
3430 | +using namespace android; | |
3431 | + | |
3432 | +// ----- Media Player C API Implementation ----- // | |
3433 | + | |
3434 | +void android_media_set_video_size_cb(MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context) | |
3435 | +{ | |
3436 | + REPORT_FUNCTION(); | |
3437 | + | |
3438 | + if (mp == NULL) { | |
3439 | + ALOGE("mp must not be NULL"); | |
3440 | + return; | |
3441 | + } | |
3442 | + | |
3443 | + mp->setVideoSizeCb(cb, context); | |
3444 | +} | |
3445 | + | |
3446 | +void android_media_set_video_texture_needs_update_cb(MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context) | |
3447 | +{ | |
3448 | + REPORT_FUNCTION(); | |
3449 | + | |
3450 | + if (mp == NULL) { | |
3451 | + ALOGE("mp must not be NULL"); | |
3452 | + return; | |
3453 | + } | |
3454 | + | |
3455 | + mp->setVideoTextureNeedsUpdateCb(cb, context); | |
3456 | +} | |
3457 | + | |
3458 | +void android_media_set_error_cb(MediaPlayerWrapper *mp, on_msg_error cb, void *context) | |
3459 | +{ | |
3460 | + REPORT_FUNCTION(); | |
3461 | + | |
3462 | + if (mp == NULL) { | |
3463 | + ALOGE("mp must not be NULL"); | |
3464 | + return; | |
3465 | + } | |
3466 | + | |
3467 | + mp->setErrorCb(cb, context); | |
3468 | +} | |
3469 | + | |
3470 | +void android_media_set_playback_complete_cb(MediaPlayerWrapper *mp, on_playback_complete cb, void *context) | |
3471 | +{ | |
3472 | + REPORT_FUNCTION(); | |
3473 | + | |
3474 | + if (mp == NULL) { | |
3475 | + ALOGE("mp must not be NULL"); | |
3476 | + return; | |
3477 | + } | |
3478 | + | |
3479 | + mp->setPlaybackCompleteCb(cb, context); | |
3480 | +} | |
3481 | + | |
3482 | +void android_media_set_media_prepared_cb(MediaPlayerWrapper *mp, on_media_prepared cb, void *context) | |
3483 | +{ | |
3484 | + REPORT_FUNCTION(); | |
3485 | + | |
3486 | + if (mp == NULL) { | |
3487 | + ALOGE("mp must not be NULL"); | |
3488 | + return; | |
3489 | + } | |
3490 | + | |
3491 | + mp->setMediaPreparedCb(cb, context); | |
3492 | +} | |
3493 | + | |
3494 | +MediaPlayerWrapper *android_media_new_player() | |
3495 | +{ | |
3496 | + REPORT_FUNCTION(); | |
3497 | + | |
3498 | + MediaPlayerWrapper *mp = new MediaPlayerWrapper(); | |
3499 | + if (mp == NULL) { | |
3500 | + ALOGE("Failed to create new MediaPlayerWrapper instance."); | |
3501 | + return NULL; | |
3502 | + } | |
3503 | + | |
3504 | + // Required for internal player state processing. Without this, prepare() and start() hang. | |
3505 | + ProcessState::self()->startThreadPool(); | |
3506 | + | |
3507 | + return mp; | |
3508 | +} | |
3509 | + | |
3510 | +int android_media_set_data_source(MediaPlayerWrapper *mp, const char* url) | |
3511 | +{ | |
3512 | + REPORT_FUNCTION(); | |
3513 | + | |
3514 | + if (mp == NULL) { | |
3515 | + ALOGE("mp must not be NULL"); | |
3516 | + return BAD_VALUE; | |
3517 | + } | |
3518 | + | |
3519 | + if (url == NULL) { | |
3520 | + ALOGE("url must not be NULL"); | |
3521 | + return BAD_VALUE; | |
3522 | + } | |
3523 | + | |
3524 | + ALOGD("url: %s", url); | |
3525 | + | |
3526 | + String16 src(url); | |
3527 | + if (src.startsWith(String16("http://")) == true) { | |
3528 | + ALOGD("HTTP source URL detected"); | |
3529 | + mp->setDataSource(url, NULL); | |
3530 | + } else { | |
3531 | + ALOGD("File source URL detected"); | |
3532 | + int fd = open(url, O_RDONLY); | |
3533 | + if (fd < 0) | |
3534 | + { | |
3535 | + ALOGE("Failed to open source data at: %s\n", url); | |
3536 | + return BAD_VALUE; | |
3537 | + } | |
3538 | + | |
3539 | + mp->setSourceFd(fd); | |
3540 | + | |
3541 | + struct stat st; | |
3542 | + stat(url, &st); | |
3543 | + | |
3544 | + ALOGD("source file length: %lld\n", st.st_size); | |
3545 | + | |
3546 | + mp->setDataSource(fd, 0, st.st_size); | |
3547 | + } | |
3548 | + mp->prepare(); | |
3549 | + | |
3550 | + return OK; | |
3551 | +} | |
3552 | + | |
3553 | +int android_media_set_preview_texture(MediaPlayerWrapper *mp, int texture_id) | |
3554 | +{ | |
3555 | + REPORT_FUNCTION(); | |
3556 | + | |
3557 | + if (mp == NULL) { | |
3558 | + ALOGE("mp must not be NULL"); | |
3559 | + return BAD_VALUE; | |
3560 | + } | |
3561 | + | |
3562 | + android::sp<android::NativeBufferAlloc> native_alloc( | |
3563 | + new android::NativeBufferAlloc() | |
3564 | + ); | |
3565 | + | |
3566 | + android::sp<android::BufferQueue> buffer_queue( | |
3567 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
3568 | + new android::BufferQueue(false, NULL, native_alloc) | |
3569 | +#else | |
3570 | + new android::BufferQueue(NULL, native_alloc) | |
3571 | +#endif | |
3572 | + ); | |
3573 | + | |
3574 | + static const bool allow_synchronous_mode = true; | |
3575 | + // Create a new GLConsumer/SurfaceTexture from the texture_id in synchronous mode (don't wait on all data in the buffer) | |
3576 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
3577 | + mp->setVideoSurfaceTexture(android::sp<android::SurfaceTexture>( | |
3578 | + new android::SurfaceTexture( | |
3579 | +#else | |
3580 | + mp->setVideoSurfaceTexture(buffer_queue, android::sp<android::GLConsumer>( | |
3581 | + new android::GLConsumer( | |
3582 | +#endif | |
3583 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
3584 | + texture_id, | |
3585 | + allow_synchronous_mode, | |
3586 | + GL_TEXTURE_EXTERNAL_OES, | |
3587 | + true, | |
3588 | + buffer_queue))); | |
3589 | +#else | |
3590 | + buffer_queue, | |
3591 | + texture_id, | |
3592 | + GL_TEXTURE_EXTERNAL_OES, | |
3593 | + true, | |
3594 | + false))); | |
3595 | +#endif | |
3596 | + | |
3597 | + return OK; | |
3598 | +} | |
3599 | + | |
3600 | +void android_media_update_surface_texture(MediaPlayerWrapper *mp) | |
3601 | +{ | |
3602 | + if (mp == NULL) { | |
3603 | + ALOGE("mp must not be NULL"); | |
3604 | + return; | |
3605 | + } | |
3606 | + | |
3607 | + mp->updateGLConsumer(); | |
3608 | +} | |
3609 | + | |
3610 | +void android_media_surface_texture_get_transformation_matrix(MediaPlayerWrapper *mp, GLfloat* matrix) | |
3611 | +{ | |
3612 | + if (mp == NULL) { | |
3613 | + ALOGE("mp must not be NULL"); | |
3614 | + return; | |
3615 | + } | |
3616 | + | |
3617 | + mp->get_transformation_matrix_for_surface_texture(matrix); | |
3618 | +} | |
3619 | + | |
3620 | +int android_media_play(MediaPlayerWrapper *mp) | |
3621 | +{ | |
3622 | + REPORT_FUNCTION(); | |
3623 | + | |
3624 | + if (mp == NULL) { | |
3625 | + ALOGE("mp must not be NULL"); | |
3626 | + return BAD_VALUE; | |
3627 | + } | |
3628 | + | |
3629 | + mp->start(); | |
3630 | + const char *tmp = mp->isPlaying() ? "yes" : "no"; | |
3631 | + ALOGV("Is playing?: %s\n", tmp); | |
3632 | + | |
3633 | + return OK; | |
3634 | +} | |
3635 | + | |
3636 | +int android_media_pause(MediaPlayerWrapper *mp) | |
3637 | +{ | |
3638 | + REPORT_FUNCTION(); | |
3639 | + | |
3640 | + if (mp == NULL) { | |
3641 | + ALOGE("mp must not be NULL"); | |
3642 | + return BAD_VALUE; | |
3643 | + } | |
3644 | + | |
3645 | + mp->pause(); | |
3646 | + | |
3647 | + return OK; | |
3648 | +} | |
3649 | + | |
3650 | +int android_media_stop(MediaPlayerWrapper *mp) | |
3651 | +{ | |
3652 | + REPORT_FUNCTION(); | |
3653 | + | |
3654 | + if (mp == NULL) { | |
3655 | + ALOGE("mp must not be NULL"); | |
3656 | + return BAD_VALUE; | |
3657 | + } | |
3658 | + | |
3659 | + mp->stop(); | |
3660 | + | |
3661 | + int fd = mp->getSourceFd(); | |
3662 | + if (fd > -1) | |
3663 | + close(fd); | |
3664 | + | |
3665 | + return OK; | |
3666 | +} | |
3667 | + | |
3668 | +bool android_media_is_playing(MediaPlayerWrapper *mp) | |
3669 | +{ | |
3670 | + if (mp != NULL) { | |
3671 | + if (mp->isPlaying()) | |
3672 | + return true; | |
3673 | + } | |
3674 | + | |
3675 | + return false; | |
3676 | +} | |
3677 | + | |
3678 | +int android_media_seek_to(MediaPlayerWrapper *mp, int msec) | |
3679 | +{ | |
3680 | + REPORT_FUNCTION(); | |
3681 | + | |
3682 | + if (mp == NULL) { | |
3683 | + ALOGE("mp must not be NULL"); | |
3684 | + return BAD_VALUE; | |
3685 | + } | |
3686 | + | |
3687 | + return mp->seekTo(msec); | |
3688 | +} | |
3689 | + | |
3690 | +int android_media_get_current_position(MediaPlayerWrapper *mp, int *msec) | |
3691 | +{ | |
3692 | + if (mp == NULL) { | |
3693 | + ALOGE("mp must not be NULL"); | |
3694 | + return BAD_VALUE; | |
3695 | + } | |
3696 | + | |
3697 | + return mp->getCurrentPosition(msec); | |
3698 | +} | |
3699 | + | |
3700 | +int android_media_get_duration(MediaPlayerWrapper *mp, int *msec) | |
3701 | +{ | |
3702 | + REPORT_FUNCTION(); | |
3703 | + | |
3704 | + if (mp == NULL) { | |
3705 | + ALOGE("mp must not be NULL"); | |
3706 | + return BAD_VALUE; | |
3707 | + } | |
3708 | + | |
3709 | + return mp->getDuration(msec); | |
3710 | +} | |
3711 | + | |
3712 | +int android_media_get_volume(MediaPlayerWrapper *mp, int *volume) | |
3713 | +{ | |
3714 | + REPORT_FUNCTION(); | |
3715 | + | |
3716 | + if (volume == NULL) { | |
3717 | + ALOGE("volume must not be NULL"); | |
3718 | + return BAD_VALUE; | |
3719 | + } | |
3720 | + | |
3721 | + if (mp == NULL) { | |
3722 | + ALOGE("mp must not be NULL"); | |
3723 | + return BAD_VALUE; | |
3724 | + } | |
3725 | + | |
3726 | + float left_volume = 0, right_volume = 0; | |
3727 | + mp->getVolume(&left_volume, &right_volume); | |
3728 | + *volume = left_volume * 100; | |
3729 | + | |
3730 | + return OK; | |
3731 | +} | |
3732 | + | |
3733 | +int android_media_set_volume(MediaPlayerWrapper *mp, int volume) | |
3734 | +{ | |
3735 | + REPORT_FUNCTION(); | |
3736 | + | |
3737 | + if (mp == NULL) { | |
3738 | + ALOGE("mp must not be NULL"); | |
3739 | + return BAD_VALUE; | |
3740 | + } | |
3741 | + | |
3742 | + float left_volume = float(volume / 100); | |
3743 | + float right_volume = float(volume / 100); | |
3744 | + return mp->setVolume(left_volume, right_volume); | |
3745 | +} | |
3746 | --- /dev/null | |
3747 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer.cpp | |
3748 | @@ -0,0 +1,245 @@ | |
3749 | +/* | |
3750 | + * Copyright (C) 2013 Canonical Ltd | |
3751 | + * | |
3752 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
3753 | + * you may not use this file except in compliance with the License. | |
3754 | + * You may obtain a copy of the License at | |
3755 | + * | |
3756 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
3757 | + * | |
3758 | + * Unless required by applicable law or agreed to in writing, software | |
3759 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
3760 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
3761 | + * See the License for the specific language governing permissions and | |
3762 | + * limitations under the License. | |
3763 | + * | |
3764 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
3765 | + */ | |
3766 | + | |
3767 | +// Uncomment to enable verbose debug output | |
3768 | +#define LOG_NDEBUG 0 | |
3769 | + | |
3770 | +#undef LOG_TAG | |
3771 | +#define LOG_TAG "MediaFormatLayer" | |
3772 | + | |
3773 | +#include <hybris/media/media_format_layer.h> | |
3774 | +#include "media_format_layer_priv.h" | |
3775 | + | |
3776 | +#include <assert.h> | |
3777 | + | |
3778 | +#include <utils/Log.h> | |
3779 | + | |
3780 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); | |
3781 | + | |
3782 | +using namespace android; | |
3783 | + | |
3784 | +static inline _MediaFormat *get_internal_format(MediaFormat format) | |
3785 | +{ | |
3786 | + if (format == NULL) | |
3787 | + { | |
3788 | + ALOGE("format must not be NULL"); | |
3789 | + return NULL; | |
3790 | + } | |
3791 | + | |
3792 | + _MediaFormat *mf = static_cast<_MediaFormat*>(format); | |
3793 | + assert(mf->refcount >= 1); | |
3794 | + | |
3795 | + return mf; | |
3796 | +} | |
3797 | + | |
3798 | +MediaFormat media_format_create_video_format(const char *mime, int32_t width, int32_t height, int64_t duration_us, int32_t max_input_size) | |
3799 | +{ | |
3800 | + REPORT_FUNCTION() | |
3801 | + | |
3802 | + _MediaFormat *format = new _MediaFormat(); | |
3803 | + format->mime = AString(mime); | |
3804 | + format->width = width; | |
3805 | + format->height = height; | |
3806 | + format->duration_us = duration_us; | |
3807 | + format->max_input_size = max_input_size; | |
3808 | + | |
3809 | + return format; | |
3810 | +} | |
3811 | + | |
3812 | +void media_format_destroy(MediaFormat format) | |
3813 | +{ | |
3814 | + REPORT_FUNCTION() | |
3815 | + | |
3816 | + _MediaFormat *mf = get_internal_format(format); | |
3817 | + if (mf == NULL) | |
3818 | + return; | |
3819 | + | |
3820 | + if (mf->refcount) | |
3821 | + return; | |
3822 | + | |
3823 | + delete mf; | |
3824 | +} | |
3825 | + | |
3826 | +void media_format_ref(MediaFormat format) | |
3827 | +{ | |
3828 | + REPORT_FUNCTION() | |
3829 | + | |
3830 | + _MediaFormat *mf = get_internal_format(format); | |
3831 | + if (mf == NULL) | |
3832 | + return; | |
3833 | + | |
3834 | + mf->refcount++; | |
3835 | +} | |
3836 | + | |
3837 | +void media_format_unref(MediaFormat format) | |
3838 | +{ | |
3839 | + REPORT_FUNCTION() | |
3840 | + | |
3841 | + _MediaFormat *mf = get_internal_format(format); | |
3842 | + if (mf == NULL) | |
3843 | + return; | |
3844 | + | |
3845 | + if (mf->refcount) | |
3846 | + mf->refcount--; | |
3847 | +} | |
3848 | + | |
3849 | +void media_format_set_byte_buffer(MediaFormat format, const char *key, uint8_t *data, size_t size) | |
3850 | +{ | |
3851 | + REPORT_FUNCTION() | |
3852 | + | |
3853 | + _MediaFormat *mf = get_internal_format(format); | |
3854 | + if (mf == NULL) | |
3855 | + return; | |
3856 | + if (key == NULL || data == NULL || size == 0) | |
3857 | + return; | |
3858 | + | |
3859 | + mf->csd_key_name = AString(key); | |
3860 | + mf->csd = sp<ABuffer>(new ABuffer(data, size)); | |
3861 | +} | |
3862 | + | |
3863 | +const char* media_format_get_mime(MediaFormat format) | |
3864 | +{ | |
3865 | + REPORT_FUNCTION() | |
3866 | + | |
3867 | + _MediaFormat *mf = get_internal_format(format); | |
3868 | + if (mf == NULL) | |
3869 | + return NULL; | |
3870 | + | |
3871 | + return mf->mime.c_str(); | |
3872 | +} | |
3873 | + | |
3874 | +int64_t media_format_get_duration_us(MediaFormat format) | |
3875 | +{ | |
3876 | + REPORT_FUNCTION() | |
3877 | + | |
3878 | + _MediaFormat *mf = get_internal_format(format); | |
3879 | + if (mf == NULL) | |
3880 | + return 0; | |
3881 | + | |
3882 | + return mf->duration_us; | |
3883 | +} | |
3884 | + | |
3885 | +int32_t media_format_get_width(MediaFormat format) | |
3886 | +{ | |
3887 | + REPORT_FUNCTION() | |
3888 | + | |
3889 | + _MediaFormat *mf = get_internal_format(format); | |
3890 | + if (mf == NULL) | |
3891 | + return 0; | |
3892 | + | |
3893 | + return mf->width; | |
3894 | +} | |
3895 | + | |
3896 | +int32_t media_format_get_height(MediaFormat format) | |
3897 | +{ | |
3898 | + REPORT_FUNCTION() | |
3899 | + | |
3900 | + _MediaFormat *mf = get_internal_format(format); | |
3901 | + if (mf == NULL) | |
3902 | + return 0; | |
3903 | + | |
3904 | + return mf->height; | |
3905 | +} | |
3906 | + | |
3907 | +int32_t media_format_get_max_input_size(MediaFormat format) | |
3908 | +{ | |
3909 | + REPORT_FUNCTION() | |
3910 | + | |
3911 | + _MediaFormat *mf = get_internal_format(format); | |
3912 | + if (mf == NULL) | |
3913 | + return 0; | |
3914 | + | |
3915 | + return mf->max_input_size; | |
3916 | +} | |
3917 | + | |
3918 | +int32_t media_format_get_stride(MediaFormat format) | |
3919 | +{ | |
3920 | + REPORT_FUNCTION() | |
3921 | + | |
3922 | + _MediaFormat *mf = get_internal_format(format); | |
3923 | + if (mf == NULL) | |
3924 | + return 0; | |
3925 | + | |
3926 | + return mf->stride; | |
3927 | +} | |
3928 | + | |
3929 | +int32_t media_format_get_slice_height(MediaFormat format) | |
3930 | +{ | |
3931 | + REPORT_FUNCTION() | |
3932 | + | |
3933 | + _MediaFormat *mf = get_internal_format(format); | |
3934 | + if (mf == NULL) | |
3935 | + return 0; | |
3936 | + | |
3937 | + return mf->height; | |
3938 | +} | |
3939 | + | |
3940 | +int32_t media_format_get_color_format(MediaFormat format) | |
3941 | +{ | |
3942 | + REPORT_FUNCTION() | |
3943 | + | |
3944 | + _MediaFormat *mf = get_internal_format(format); | |
3945 | + if (mf == NULL) | |
3946 | + return 0; | |
3947 | + | |
3948 | + return mf->color_format; | |
3949 | +} | |
3950 | + | |
3951 | +int32_t media_format_get_crop_left(MediaFormat format) | |
3952 | +{ | |
3953 | + REPORT_FUNCTION() | |
3954 | + | |
3955 | + _MediaFormat *mf = get_internal_format(format); | |
3956 | + if (mf == NULL) | |
3957 | + return 0; | |
3958 | + | |
3959 | + return mf->crop_left; | |
3960 | +} | |
3961 | + | |
3962 | +int32_t media_format_get_crop_right(MediaFormat format) | |
3963 | +{ | |
3964 | + REPORT_FUNCTION() | |
3965 | + | |
3966 | + _MediaFormat *mf = get_internal_format(format); | |
3967 | + if (mf == NULL) | |
3968 | + return 0; | |
3969 | + | |
3970 | + return mf->crop_right; | |
3971 | +} | |
3972 | + | |
3973 | +int32_t media_format_get_crop_top(MediaFormat format) | |
3974 | +{ | |
3975 | + REPORT_FUNCTION() | |
3976 | + | |
3977 | + _MediaFormat *mf = get_internal_format(format); | |
3978 | + if (mf == NULL) | |
3979 | + return 0; | |
3980 | + | |
3981 | + return mf->crop_top; | |
3982 | +} | |
3983 | + | |
3984 | +int32_t media_format_get_crop_bottom(MediaFormat format) | |
3985 | +{ | |
3986 | + REPORT_FUNCTION() | |
3987 | + | |
3988 | + _MediaFormat *mf = get_internal_format(format); | |
3989 | + if (mf == NULL) | |
3990 | + return 0; | |
3991 | + | |
3992 | + return mf->crop_bottom; | |
3993 | +} | |
3994 | --- /dev/null | |
3995 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer_priv.cpp | |
3996 | @@ -0,0 +1,50 @@ | |
3997 | +/* | |
3998 | + * Copyright (C) 2013 Canonical Ltd | |
3999 | + * | |
4000 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
4001 | + * you may not use this file except in compliance with the License. | |
4002 | + * You may obtain a copy of the License at | |
4003 | + * | |
4004 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
4005 | + * | |
4006 | + * Unless required by applicable law or agreed to in writing, software | |
4007 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
4008 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
4009 | + * See the License for the specific language governing permissions and | |
4010 | + * limitations under the License. | |
4011 | + * | |
4012 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
4013 | + */ | |
4014 | + | |
4015 | +#include <stddef.h> | |
4016 | +#include <unistd.h> | |
4017 | + | |
4018 | +#include <media/stagefright/foundation/AString.h> | |
4019 | + | |
4020 | +#include <utils/RefBase.h> | |
4021 | + | |
4022 | +#ifdef __cplusplus | |
4023 | +extern "C" { | |
4024 | +#endif | |
4025 | + | |
4026 | +struct _MediaFormat : public RefBase | |
4027 | +{ | |
4028 | + _MediaFormat() | |
4029 | + : refcount(1) | |
4030 | + { | |
4031 | + } | |
4032 | + | |
4033 | + AString mime; | |
4034 | + int64_t duration_us; | |
4035 | + int32_t width; | |
4036 | + int32_t height; | |
4037 | + int32_t max_input_size; | |
4038 | + | |
4039 | + unsigned int refcount; | |
4040 | +}; | |
4041 | + | |
4042 | +#ifdef __cplusplus | |
4043 | +} | |
4044 | +#endif | |
4045 | + | |
4046 | +#endif | |
4047 | --- /dev/null | |
4048 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer_priv.h | |
4049 | @@ -0,0 +1,68 @@ | |
4050 | +/* | |
4051 | + * Copyright (C) 2013 Canonical Ltd | |
4052 | + * | |
4053 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
4054 | + * you may not use this file except in compliance with the License. | |
4055 | + * You may obtain a copy of the License at | |
4056 | + * | |
4057 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
4058 | + * | |
4059 | + * Unless required by applicable law or agreed to in writing, software | |
4060 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
4061 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
4062 | + * See the License for the specific language governing permissions and | |
4063 | + * limitations under the License. | |
4064 | + * | |
4065 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
4066 | + */ | |
4067 | + | |
4068 | +#ifndef MEDIA_FORMAT_LAYER_PRIV_H_ | |
4069 | +#define MEDIA_FORMAT_LAYER_PRIV_H_ | |
4070 | + | |
4071 | +#include <stddef.h> | |
4072 | +#include <unistd.h> | |
4073 | + | |
4074 | +#include <media/stagefright/foundation/AString.h> | |
4075 | +#include <media/stagefright/foundation/ABuffer.h> | |
4076 | + | |
4077 | +#include <utils/RefBase.h> | |
4078 | + | |
4079 | +struct _MediaFormat : public android::RefBase | |
4080 | +{ | |
4081 | + _MediaFormat() | |
4082 | + : duration_us(0), | |
4083 | + width(0), | |
4084 | + height(0), | |
4085 | + max_input_size(0), | |
4086 | + csd(NULL), | |
4087 | + stride(0), | |
4088 | + slice_height(0), | |
4089 | + color_format(0), | |
4090 | + crop_left(0), | |
4091 | + crop_right(0), | |
4092 | + crop_top(0), | |
4093 | + crop_bottom(0), | |
4094 | + refcount(1) | |
4095 | + { | |
4096 | + } | |
4097 | + | |
4098 | + android::AString mime; | |
4099 | + int64_t duration_us; | |
4100 | + int32_t width; | |
4101 | + int32_t height; | |
4102 | + int32_t max_input_size; | |
4103 | + android::AString csd_key_name; | |
4104 | + android::sp<android::ABuffer> csd; | |
4105 | + | |
4106 | + int32_t stride; | |
4107 | + int32_t slice_height; | |
4108 | + int32_t color_format; | |
4109 | + int32_t crop_left; | |
4110 | + int32_t crop_right; | |
4111 | + int32_t crop_top; | |
4112 | + int32_t crop_bottom; | |
4113 | + | |
4114 | + unsigned int refcount; | |
4115 | +}; | |
4116 | + | |
4117 | +#endif // MEDIA_FORMAT_LAYER_PRIV_H_ | |
4118 | --- /dev/null | |
4119 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/recorder_compatibility_layer.cpp | |
4120 | @@ -0,0 +1,457 @@ | |
4121 | +/* | |
4122 | + * Copyright (C) 2013 Canonical Ltd | |
4123 | + * | |
4124 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
4125 | + * you may not use this file except in compliance with the License. | |
4126 | + * You may obtain a copy of the License at | |
4127 | + * | |
4128 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
4129 | + * | |
4130 | + * Unless required by applicable law or agreed to in writing, software | |
4131 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
4132 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
4133 | + * See the License for the specific language governing permissions and | |
4134 | + * limitations under the License. | |
4135 | + * | |
4136 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
4137 | + * Guenter Schwann <guenter.schwann@canonical.com> | |
4138 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
4139 | + */ | |
4140 | + | |
4141 | +#include <hybris/internal/camera_control.h> | |
4142 | +#include <hybris/media/recorder_compatibility_layer.h> | |
4143 | + | |
4144 | +#include <camera/Camera.h> | |
4145 | +#include <camera/ICamera.h> | |
4146 | +#include <media/mediarecorder.h> | |
4147 | + | |
4148 | +//#define LOG_NDEBUG 0 | |
4149 | +#undef LOG_TAG | |
4150 | +#define LOG_TAG "MediaRecorderCompatibilityLayer" | |
4151 | +#include <utils/KeyedVector.h> | |
4152 | +#include <utils/Log.h> | |
4153 | + | |
4154 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) | |
4155 | + | |
4156 | +/*! | |
4157 | + * \brief The MediaRecorderListenerWrapper class is used to listen to events | |
4158 | + * from the MediaRecorder | |
4159 | + */ | |
4160 | +class MediaRecorderListenerWrapper : public android::MediaRecorderListener | |
4161 | +{ | |
4162 | + public: | |
4163 | + MediaRecorderListenerWrapper() | |
4164 | + : error_cb(NULL), | |
4165 | + error_context(NULL) | |
4166 | + { | |
4167 | + } | |
4168 | + | |
4169 | + void notify(int msg, int ext1, int ext2) | |
4170 | + { | |
4171 | + ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2); | |
4172 | + | |
4173 | + switch (msg) { | |
4174 | + case android::MEDIA_RECORDER_EVENT_ERROR: | |
4175 | + ALOGV("\tMEDIA_RECORDER_EVENT_ERROR msg\n"); | |
4176 | + // TODO: Extend this cb to include the error message | |
4177 | + if (error_cb != NULL) | |
4178 | + error_cb(error_context); | |
4179 | + else | |
4180 | + ALOGE("Failed to signal error to app layer, callback not set."); | |
4181 | + break; | |
4182 | + default: | |
4183 | + ALOGV("\tUnknown notification\n"); | |
4184 | + } | |
4185 | + } | |
4186 | + | |
4187 | + void setErrorCb(on_recorder_msg_error cb, void *context) | |
4188 | + { | |
4189 | + REPORT_FUNCTION(); | |
4190 | + error_cb = cb; | |
4191 | + error_context = context; | |
4192 | + } | |
4193 | + | |
4194 | + private: | |
4195 | + on_recorder_msg_error error_cb; | |
4196 | + void *error_context; | |
4197 | +}; | |
4198 | + | |
4199 | +/*! | |
4200 | + * \brief The MediaRecorderWrapper struct wraps the MediaRecorder class | |
4201 | + */ | |
4202 | +struct MediaRecorderWrapper : public android::MediaRecorder | |
4203 | +{ | |
4204 | + public: | |
4205 | + MediaRecorderWrapper() | |
4206 | + : MediaRecorder(), | |
4207 | + media_recorder_listener(new MediaRecorderListenerWrapper()) | |
4208 | + { | |
4209 | + setListener(media_recorder_listener); | |
4210 | + } | |
4211 | + | |
4212 | + ~MediaRecorderWrapper() | |
4213 | + { | |
4214 | + reset(); | |
4215 | + } | |
4216 | + | |
4217 | + void setErrorCb(on_recorder_msg_error cb, void *context) | |
4218 | + { | |
4219 | + REPORT_FUNCTION(); | |
4220 | + | |
4221 | + assert(media_recorder_listener != NULL); | |
4222 | + media_recorder_listener->setErrorCb(cb, context); | |
4223 | + } | |
4224 | + | |
4225 | + private: | |
4226 | + android::sp<MediaRecorderListenerWrapper> media_recorder_listener; | |
4227 | +}; | |
4228 | + | |
4229 | + | |
4230 | +using namespace android; | |
4231 | + | |
4232 | +/*! | |
4233 | + * \brief android_recorder_set_error_cb | |
4234 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4235 | + * \param cb The callback function to be called when a recording error occurs | |
4236 | + * \param context | |
4237 | + */ | |
4238 | +void android_recorder_set_error_cb(MediaRecorderWrapper *mr, on_recorder_msg_error cb, | |
4239 | + void *context) | |
4240 | +{ | |
4241 | + REPORT_FUNCTION(); | |
4242 | + | |
4243 | + if (mr == NULL) { | |
4244 | + ALOGE("mr must not be NULL"); | |
4245 | + return; | |
4246 | + } | |
4247 | + | |
4248 | + mr->setErrorCb(cb, context); | |
4249 | +} | |
4250 | + | |
4251 | +/*! | |
4252 | + * \brief android_media_new_recorder creates a new MediaRecorder | |
4253 | + * \return New MediaRecorder object, or NULL if the object could not be created. | |
4254 | + */ | |
4255 | +MediaRecorderWrapper *android_media_new_recorder() | |
4256 | +{ | |
4257 | + REPORT_FUNCTION(); | |
4258 | + | |
4259 | + MediaRecorderWrapper *mr = new MediaRecorderWrapper; | |
4260 | + if (mr == NULL) { | |
4261 | + ALOGE("Failed to create new MediaRecorderWrapper instance."); | |
4262 | + return NULL; | |
4263 | + } | |
4264 | + | |
4265 | + return mr; | |
4266 | +} | |
4267 | + | |
4268 | +/*! | |
4269 | + * \brief android_recorder_initCheck | |
4270 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4271 | + * \return negative value if an error occured | |
4272 | + */ | |
4273 | +int android_recorder_initCheck(MediaRecorderWrapper *mr) | |
4274 | +{ | |
4275 | + REPORT_FUNCTION(); | |
4276 | + | |
4277 | + if (mr == NULL) { | |
4278 | + ALOGE("mr must not be NULL"); | |
4279 | + return BAD_VALUE; | |
4280 | + } | |
4281 | + | |
4282 | + return mr->initCheck(); | |
4283 | +} | |
4284 | + | |
4285 | +/*! | |
4286 | + * \brief android_recorder_setCamera sets the camera object for recording videos | |
4287 | + * from the camera | |
4288 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4289 | + * \param control Wrapper for the camera (see camera in hybris) | |
4290 | + * \return negative value if an error occured | |
4291 | + */ | |
4292 | +int android_recorder_setCamera(MediaRecorderWrapper *mr, CameraControl* control) | |
4293 | +{ | |
4294 | + REPORT_FUNCTION(); | |
4295 | + | |
4296 | + if (mr == NULL) { | |
4297 | + ALOGE("mr must not be NULL"); | |
4298 | + return BAD_VALUE; | |
4299 | + } | |
4300 | + if (control == NULL) { | |
4301 | + ALOGE("control must not be NULL"); | |
4302 | + return BAD_VALUE; | |
4303 | + } | |
4304 | + | |
4305 | + return mr->setCamera(control->camera->remote(), control->camera->getRecordingProxy()); | |
4306 | +} | |
4307 | + | |
4308 | +/*! | |
4309 | + * \brief android_recorder_setVideoSource sets the video source. | |
4310 | + * If no video source is set, only audio is recorded. | |
4311 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4312 | + * \param vs The video source. It's either the camera of gralloc buffer | |
4313 | + * \return negative value if an error occured | |
4314 | + */ | |
4315 | +int android_recorder_setVideoSource(MediaRecorderWrapper *mr, VideoSource vs) | |
4316 | +{ | |
4317 | + REPORT_FUNCTION(); | |
4318 | + | |
4319 | + if (mr == NULL) { | |
4320 | + ALOGE("mr must not be NULL"); | |
4321 | + return BAD_VALUE; | |
4322 | + } | |
4323 | + | |
4324 | + return mr->setVideoSource(static_cast<int>(vs)); | |
4325 | +} | |
4326 | + | |
4327 | +/*! | |
4328 | + * \brief android_recorder_setAudioSource | |
4329 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4330 | + * \param as The audio source. | |
4331 | + * \return negative value if an error occured | |
4332 | + */ | |
4333 | +int android_recorder_setAudioSource(MediaRecorderWrapper *mr, AudioSource as) | |
4334 | +{ | |
4335 | + REPORT_FUNCTION(); | |
4336 | + | |
4337 | + if (mr == NULL) { | |
4338 | + ALOGE("mr must not be NULL"); | |
4339 | + return BAD_VALUE; | |
4340 | + } | |
4341 | + | |
4342 | + return mr->setAudioSource(static_cast<int>(as)); | |
4343 | +} | |
4344 | + | |
4345 | +/*! | |
4346 | + * \brief android_recorder_setOutputFormat | |
4347 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4348 | + * \param of The output file format | |
4349 | + * \return negative value if an error occured | |
4350 | + */ | |
4351 | +int android_recorder_setOutputFormat(MediaRecorderWrapper *mr, OutputFormat of) | |
4352 | +{ | |
4353 | + REPORT_FUNCTION(); | |
4354 | + | |
4355 | + if (mr == NULL) { | |
4356 | + ALOGE("mr must not be NULL"); | |
4357 | + return BAD_VALUE; | |
4358 | + } | |
4359 | + | |
4360 | + return mr->setOutputFormat(static_cast<int>(of)); | |
4361 | +} | |
4362 | + | |
4363 | +/*! | |
4364 | + * \brief android_recorder_setVideoEncoder | |
4365 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4366 | + * \param ve The video encoder sets the codec for the video | |
4367 | + * \return negative value if an error occured | |
4368 | + */ | |
4369 | +int android_recorder_setVideoEncoder(MediaRecorderWrapper *mr, VideoEncoder ve) | |
4370 | +{ | |
4371 | + REPORT_FUNCTION(); | |
4372 | + | |
4373 | + if (mr == NULL) { | |
4374 | + ALOGE("mr must not be NULL"); | |
4375 | + return BAD_VALUE; | |
4376 | + } | |
4377 | + | |
4378 | + return mr->setVideoEncoder(static_cast<int>(ve)); | |
4379 | +} | |
4380 | + | |
4381 | +/*! | |
4382 | + * \brief android_recorder_setAudioEncoder | |
4383 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4384 | + * \param ae The audio encoder sets the codec for the audio | |
4385 | + * \return negative value if an error occured | |
4386 | + */ | |
4387 | +int android_recorder_setAudioEncoder(MediaRecorderWrapper *mr, AudioEncoder ae) | |
4388 | +{ | |
4389 | + REPORT_FUNCTION(); | |
4390 | + | |
4391 | + if (mr == NULL) { | |
4392 | + ALOGE("mr must not be NULL"); | |
4393 | + return BAD_VALUE; | |
4394 | + } | |
4395 | + | |
4396 | + return mr->setAudioEncoder(static_cast<int>(ae)); | |
4397 | +} | |
4398 | + | |
4399 | +/*! | |
4400 | + * \brief android_recorder_setOutputFile sets the output file to the given file descriptor | |
4401 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4402 | + * \param fd File descriptor of an open file, that the stream can be written to | |
4403 | + * \return negative value if an error occured | |
4404 | + */ | |
4405 | +int android_recorder_setOutputFile(MediaRecorderWrapper *mr, int fd) | |
4406 | +{ | |
4407 | + REPORT_FUNCTION(); | |
4408 | + | |
4409 | + if (mr == NULL) { | |
4410 | + ALOGE("mr must not be NULL"); | |
4411 | + return BAD_VALUE; | |
4412 | + } | |
4413 | + | |
4414 | + return mr->setOutputFile(fd, 0, 0); | |
4415 | +} | |
4416 | + | |
4417 | +/*! | |
4418 | + * \brief android_recorder_setVideoSize | |
4419 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4420 | + * \param width width for the video to record | |
4421 | + * \param height height for the video to record | |
4422 | + * \return negative value if an error occured | |
4423 | + */ | |
4424 | +int android_recorder_setVideoSize(MediaRecorderWrapper *mr, int width, int height) | |
4425 | +{ | |
4426 | + REPORT_FUNCTION(); | |
4427 | + | |
4428 | + if (mr == NULL) { | |
4429 | + ALOGE("mr must not be NULL"); | |
4430 | + return BAD_VALUE; | |
4431 | + } | |
4432 | + | |
4433 | + return mr->setVideoSize(width, height); | |
4434 | +} | |
4435 | + | |
4436 | +/*! | |
4437 | + * \brief android_recorder_setVideoFrameRate | |
4438 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4439 | + * \param frames_per_second Frames per second has typical values for a movie clip in 720p is 30 | |
4440 | + * \return negative value if an error occured | |
4441 | + */ | |
4442 | +int android_recorder_setVideoFrameRate(MediaRecorderWrapper *mr, int frames_per_second) | |
4443 | +{ | |
4444 | + REPORT_FUNCTION(); | |
4445 | + | |
4446 | + if (mr == NULL) { | |
4447 | + ALOGE("mr must not be NULL"); | |
4448 | + return BAD_VALUE; | |
4449 | + } | |
4450 | + | |
4451 | + return mr->setVideoFrameRate(frames_per_second); | |
4452 | +} | |
4453 | + | |
4454 | +/*! | |
4455 | + * \brief android_recorder_setParameters sets a parameter. Even those without | |
4456 | + * explicit function. | |
4457 | + * For possible parameters look for example in StagefrightRecorder::setParameter() | |
4458 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4459 | + * \param parameters list of parameters. format is "parameter1=value;parameter2=value" | |
4460 | + * \return negative value if an error occured | |
4461 | + */ | |
4462 | +int android_recorder_setParameters(MediaRecorderWrapper *mr, const char* parameters) | |
4463 | +{ | |
4464 | + REPORT_FUNCTION(); | |
4465 | + | |
4466 | + if (mr == NULL) { | |
4467 | + ALOGE("mr must not be NULL"); | |
4468 | + return BAD_VALUE; | |
4469 | + } | |
4470 | + | |
4471 | + String8 params(parameters); | |
4472 | + return mr->setParameters(params); | |
4473 | +} | |
4474 | + | |
4475 | +/*! | |
4476 | + * \brief android_recorder_start starts the recording. | |
4477 | + * The MediaRecorder has to be in state "prepared" | |
4478 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4479 | + * \return negative value if an error occured | |
4480 | + */ | |
4481 | +int android_recorder_start(MediaRecorderWrapper *mr) | |
4482 | +{ | |
4483 | + REPORT_FUNCTION(); | |
4484 | + | |
4485 | + if (mr == NULL) { | |
4486 | + ALOGE("mr must not be NULL"); | |
4487 | + return BAD_VALUE; | |
4488 | + } | |
4489 | + | |
4490 | + return mr->start(); | |
4491 | +} | |
4492 | + | |
4493 | +/*! | |
4494 | + * \brief android_recorder_stop Stops a running recording. | |
4495 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4496 | + * \return negative value if an error occured | |
4497 | + */ | |
4498 | +int android_recorder_stop(MediaRecorderWrapper *mr) | |
4499 | +{ | |
4500 | + REPORT_FUNCTION(); | |
4501 | + | |
4502 | + if (mr == NULL) { | |
4503 | + ALOGE("mr must not be NULL"); | |
4504 | + return BAD_VALUE; | |
4505 | + } | |
4506 | + | |
4507 | + return mr->stop(); | |
4508 | +} | |
4509 | + | |
4510 | +/*! | |
4511 | + * \brief android_recorder_prepare put the MediaRecorder into state "prepare" | |
4512 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4513 | + * \return negative value if an error occured | |
4514 | + */ | |
4515 | +int android_recorder_prepare(MediaRecorderWrapper *mr) | |
4516 | +{ | |
4517 | + REPORT_FUNCTION(); | |
4518 | + | |
4519 | + if (mr == NULL) { | |
4520 | + ALOGE("mr must not be NULL"); | |
4521 | + return BAD_VALUE; | |
4522 | + } | |
4523 | + | |
4524 | + return mr->prepare(); | |
4525 | +} | |
4526 | + | |
4527 | +/*! | |
4528 | + * \brief android_recorder_reset resets the MediaRecorder | |
4529 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4530 | + * \return negative value if an error occured | |
4531 | + */ | |
4532 | +int android_recorder_reset(MediaRecorderWrapper *mr) | |
4533 | +{ | |
4534 | + REPORT_FUNCTION(); | |
4535 | + | |
4536 | + if (mr == NULL) { | |
4537 | + ALOGE("mr must not be NULL"); | |
4538 | + return BAD_VALUE; | |
4539 | + } | |
4540 | + | |
4541 | + return mr->reset(); | |
4542 | +} | |
4543 | + | |
4544 | +/*! | |
4545 | + * \brief android_recorder_close closes the MediaRecorder | |
4546 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4547 | + * \return negative value if an error occured | |
4548 | + */ | |
4549 | +int android_recorder_close(MediaRecorderWrapper *mr) | |
4550 | +{ | |
4551 | + REPORT_FUNCTION(); | |
4552 | + | |
4553 | + if (mr == NULL) { | |
4554 | + ALOGE("mr must not be NULL"); | |
4555 | + return BAD_VALUE; | |
4556 | + } | |
4557 | + | |
4558 | + return mr->close(); | |
4559 | +} | |
4560 | + | |
4561 | +/*! | |
4562 | + * \brief android_recorder_release releases the MediaRecorder resources | |
4563 | + * This deletes the object. So don't use it after calling this function. | |
4564 | + * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder() | |
4565 | + * \return negative value if an error occured | |
4566 | + */ | |
4567 | +int android_recorder_release(MediaRecorderWrapper *mr) | |
4568 | +{ | |
4569 | + REPORT_FUNCTION(); | |
4570 | + | |
4571 | + if (mr == NULL) { | |
4572 | + ALOGE("mr must not be NULL"); | |
4573 | + return BAD_VALUE; | |
4574 | + } | |
4575 | + | |
4576 | + return mr->release(); | |
4577 | +} | |
4578 | --- /dev/null | |
4579 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/surface_texture_client_hybris.cpp | |
4580 | @@ -0,0 +1,333 @@ | |
4581 | +/* | |
4582 | + * Copyright (C) 2013 Canonical Ltd | |
4583 | + * | |
4584 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
4585 | + * you may not use this file except in compliance with the License. | |
4586 | + * You may obtain a copy of the License at | |
4587 | + * | |
4588 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
4589 | + * | |
4590 | + * Unless required by applicable law or agreed to in writing, software | |
4591 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
4592 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
4593 | + * See the License for the specific language governing permissions and | |
4594 | + * limitations under the License. | |
4595 | + * | |
4596 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
4597 | + */ | |
4598 | + | |
4599 | +// Uncomment to enable verbose debug output | |
4600 | +#define LOG_NDEBUG 0 | |
4601 | + | |
4602 | +#undef LOG_TAG | |
4603 | +#define LOG_TAG "SurfaceTextureClientHybris" | |
4604 | + | |
4605 | +#include <hybris/media/surface_texture_client_hybris.h> | |
4606 | +#include "surface_texture_client_hybris_priv.h" | |
4607 | + | |
4608 | +#include <ui/GraphicBuffer.h> | |
4609 | +#include <utils/Log.h> | |
4610 | +#include <ui/Region.h> | |
4611 | +#include <gui/Surface.h> | |
4612 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4613 | +#include <gui/SurfaceTextureClient.h> | |
4614 | +#endif | |
4615 | + | |
4616 | +#include <GLES2/gl2.h> | |
4617 | +#include <GLES2/gl2ext.h> | |
4618 | + | |
4619 | +#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); | |
4620 | + | |
4621 | +using namespace android; | |
4622 | + | |
4623 | +// ----- Begin _SurfaceTextureClientHybris API ----- // | |
4624 | + | |
4625 | +static inline _SurfaceTextureClientHybris *get_internal_stch(SurfaceTextureClientHybris stc, const char * func) | |
4626 | +{ | |
4627 | + if (stc == NULL) | |
4628 | + { | |
4629 | + ALOGE("stc must not be NULL (%s)", func); | |
4630 | + return NULL; | |
4631 | + } | |
4632 | + | |
4633 | + _SurfaceTextureClientHybris *s = static_cast<_SurfaceTextureClientHybris*>(stc); | |
4634 | + assert(s->refcount >= 1); | |
4635 | + | |
4636 | + return s; | |
4637 | +} | |
4638 | + | |
4639 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4640 | +_SurfaceTextureClientHybris::_SurfaceTextureClientHybris() | |
4641 | + : refcount(1), | |
4642 | + ready(false) | |
4643 | +{ | |
4644 | + REPORT_FUNCTION() | |
4645 | +} | |
4646 | +#endif | |
4647 | + | |
4648 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=4 | |
4649 | +_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp<BufferQueue> &bq) | |
4650 | + : Surface::Surface(bq, true), | |
4651 | + refcount(1), | |
4652 | + ready(false) | |
4653 | +{ | |
4654 | + REPORT_FUNCTION() | |
4655 | +} | |
4656 | +#endif | |
4657 | + | |
4658 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4659 | +_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch) | |
4660 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4661 | + : SurfaceTextureClient::SurfaceTextureClient(), | |
4662 | +#else | |
4663 | + : Surface::Surface(new BufferQueue(), true), | |
4664 | +#endif | |
4665 | + refcount(stch.refcount), | |
4666 | + ready(false) | |
4667 | +{ | |
4668 | + REPORT_FUNCTION() | |
4669 | +} | |
4670 | + | |
4671 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4672 | +_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp<ISurfaceTexture> &st) | |
4673 | + : SurfaceTextureClient::SurfaceTextureClient(st), | |
4674 | +#else | |
4675 | +_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp<IGraphicBufferProducer> &st) | |
4676 | + : Surface::Surface(st, true), | |
4677 | +#endif | |
4678 | + refcount(1), | |
4679 | + ready(false) | |
4680 | +{ | |
4681 | + REPORT_FUNCTION() | |
4682 | +} | |
4683 | +#endif | |
4684 | + | |
4685 | +_SurfaceTextureClientHybris::~_SurfaceTextureClientHybris() | |
4686 | +{ | |
4687 | + REPORT_FUNCTION() | |
4688 | + | |
4689 | + ready = false; | |
4690 | +} | |
4691 | + | |
4692 | +bool _SurfaceTextureClientHybris::isReady() const | |
4693 | +{ | |
4694 | + return ready; | |
4695 | +} | |
4696 | + | |
4697 | +int _SurfaceTextureClientHybris::dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) | |
4698 | +{ | |
4699 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4700 | + return SurfaceTextureClient::dequeueBuffer(buffer, fenceFd); | |
4701 | +#else | |
4702 | + return Surface::dequeueBuffer(buffer, fenceFd); | |
4703 | +#endif | |
4704 | +} | |
4705 | + | |
4706 | +int _SurfaceTextureClientHybris::queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) | |
4707 | +{ | |
4708 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4709 | + return SurfaceTextureClient::queueBuffer(buffer, fenceFd); | |
4710 | +#else | |
4711 | + return Surface::queueBuffer(buffer, fenceFd); | |
4712 | +#endif | |
4713 | +} | |
4714 | + | |
4715 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4716 | +void _SurfaceTextureClientHybris::setISurfaceTexture(const sp<ISurfaceTexture>& surface_texture) | |
4717 | +{ | |
4718 | + SurfaceTextureClient::setISurfaceTexture(surface_texture); | |
4719 | +#else | |
4720 | +void _SurfaceTextureClientHybris::setISurfaceTexture(const sp<IGraphicBufferProducer>& surface_texture) | |
4721 | +{ | |
4722 | + // We don't need to set up the IGraphicBufferProducer as stc needs it when created | |
4723 | +#endif | |
4724 | + | |
4725 | + // Ready for rendering | |
4726 | + ready = true; | |
4727 | +} | |
4728 | + | |
4729 | +void _SurfaceTextureClientHybris::setHardwareRendering(bool do_hardware_rendering) | |
4730 | +{ | |
4731 | + hardware_rendering = do_hardware_rendering; | |
4732 | +} | |
4733 | + | |
4734 | +bool _SurfaceTextureClientHybris::hardwareRendering() | |
4735 | +{ | |
4736 | + return hardware_rendering; | |
4737 | +} | |
4738 | + | |
4739 | +// ----- End _SurfaceTextureClientHybris API ----- // | |
4740 | + | |
4741 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4742 | +static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp<SurfaceTexture> &surface_texture) | |
4743 | +#else | |
4744 | +static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp<GLConsumer> &surface_texture) | |
4745 | +#endif | |
4746 | +{ | |
4747 | + REPORT_FUNCTION() | |
4748 | + | |
4749 | + if (stch == NULL) | |
4750 | + return; | |
4751 | + | |
4752 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4753 | + stch->setISurfaceTexture(surface_texture->getBufferQueue()); | |
4754 | +#else | |
4755 | + stch->setISurfaceTexture(stch->getIGraphicBufferProducer()); | |
4756 | +#endif | |
4757 | +} | |
4758 | + | |
4759 | +SurfaceTextureClientHybris surface_texture_client_create_by_id(unsigned int texture_id) | |
4760 | +{ | |
4761 | + REPORT_FUNCTION() | |
4762 | + | |
4763 | + if (texture_id == 0) | |
4764 | + { | |
4765 | + ALOGE("Cannot create new SurfaceTextureClientHybris, texture id must be > 0."); | |
4766 | + return NULL; | |
4767 | + } | |
4768 | + | |
4769 | + // Use a new native buffer allocator vs the default one, which means it'll use the proper one | |
4770 | + // that will allow rendering to work with Mir | |
4771 | + sp<NativeBufferAlloc> native_alloc(new NativeBufferAlloc()); | |
4772 | + | |
4773 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
4774 | + sp<BufferQueue> buffer_queue(new BufferQueue(false, NULL, native_alloc)); | |
4775 | + _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris); | |
4776 | +#else | |
4777 | + sp<BufferQueue> buffer_queue(new BufferQueue(NULL, native_alloc)); | |
4778 | + _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris(buffer_queue)); | |
4779 | +#endif | |
4780 | + | |
4781 | + ALOGD("stch: %p (%s)", stch, __PRETTY_FUNCTION__); | |
4782 | + | |
4783 | + if (stch->surface_texture != NULL) | |
4784 | + stch->surface_texture.clear(); | |
4785 | + | |
4786 | + const bool allow_synchronous_mode = true; | |
4787 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4788 | + stch->surface_texture = new SurfaceTexture(texture_id, allow_synchronous_mode, GL_TEXTURE_EXTERNAL_OES, true, buffer_queue); | |
4789 | + set_surface(stch, stch->surface_texture); | |
4790 | +#else | |
4791 | + stch->surface_texture = new GLConsumer(buffer_queue, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true); | |
4792 | +#endif | |
4793 | + set_surface(stch, stch->surface_texture); | |
4794 | + | |
4795 | + return stch; | |
4796 | +} | |
4797 | + | |
4798 | +uint8_t surface_texture_client_is_ready_for_rendering(SurfaceTextureClientHybris stc) | |
4799 | +{ | |
4800 | + REPORT_FUNCTION() | |
4801 | + | |
4802 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4803 | + if (s == NULL) | |
4804 | + return false; | |
4805 | + | |
4806 | + return static_cast<uint8_t>(s->isReady()); | |
4807 | +} | |
4808 | + | |
4809 | +uint8_t surface_texture_client_hardware_rendering(SurfaceTextureClientHybris stc) | |
4810 | +{ | |
4811 | + REPORT_FUNCTION() | |
4812 | + | |
4813 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4814 | + if (s == NULL) | |
4815 | + return false; | |
4816 | + | |
4817 | + return s->hardwareRendering(); | |
4818 | +} | |
4819 | + | |
4820 | +void surface_texture_client_set_hardware_rendering(SurfaceTextureClientHybris stc, uint8_t hardware_rendering) | |
4821 | +{ | |
4822 | + REPORT_FUNCTION() | |
4823 | + | |
4824 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4825 | + if (s == NULL) | |
4826 | + return; | |
4827 | + | |
4828 | + s->setHardwareRendering(static_cast<bool>(hardware_rendering)); | |
4829 | +} | |
4830 | + | |
4831 | +void surface_texture_client_get_transformation_matrix(SurfaceTextureClientHybris stc, float *matrix) | |
4832 | +{ | |
4833 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4834 | + if (s == NULL) | |
4835 | + return; | |
4836 | + | |
4837 | + s->surface_texture->getTransformMatrix(static_cast<GLfloat*>(matrix)); | |
4838 | +} | |
4839 | + | |
4840 | +void surface_texture_client_update_texture(SurfaceTextureClientHybris stc) | |
4841 | +{ | |
4842 | + REPORT_FUNCTION() | |
4843 | + | |
4844 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4845 | + if (s == NULL) | |
4846 | + return; | |
4847 | + | |
4848 | + s->surface_texture->updateTexImage(); | |
4849 | +} | |
4850 | + | |
4851 | +void surface_texture_client_destroy(SurfaceTextureClientHybris stc) | |
4852 | +{ | |
4853 | + REPORT_FUNCTION() | |
4854 | + | |
4855 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4856 | + if (s == NULL) | |
4857 | + { | |
4858 | + ALOGE("s == NULL, cannot destroy SurfaceTextureClientHybris instance"); | |
4859 | + return; | |
4860 | + } | |
4861 | + | |
4862 | + s->refcount = 0; | |
4863 | + | |
4864 | + delete s; | |
4865 | +} | |
4866 | + | |
4867 | +void surface_texture_client_ref(SurfaceTextureClientHybris stc) | |
4868 | +{ | |
4869 | + REPORT_FUNCTION() | |
4870 | + | |
4871 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4872 | + if (s == NULL) | |
4873 | + return; | |
4874 | + | |
4875 | + s->refcount++; | |
4876 | +} | |
4877 | + | |
4878 | +void surface_texture_client_unref(SurfaceTextureClientHybris stc) | |
4879 | +{ | |
4880 | + REPORT_FUNCTION() | |
4881 | + | |
4882 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4883 | + if (s == NULL) | |
4884 | + { | |
4885 | + ALOGE("s == NULL, cannot unref SurfaceTextureClientHybris instance"); | |
4886 | + return; | |
4887 | + } | |
4888 | + | |
4889 | + if (s->refcount > 1) | |
4890 | + s->refcount--; | |
4891 | + else | |
4892 | + surface_texture_client_destroy (stc); | |
4893 | +} | |
4894 | + | |
4895 | +void surface_texture_client_set_surface_texture(SurfaceTextureClientHybris stc, EGLNativeWindowType native_window) | |
4896 | +{ | |
4897 | + _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); | |
4898 | + if (s == NULL) | |
4899 | + return; | |
4900 | + | |
4901 | + if (native_window == NULL) | |
4902 | + { | |
4903 | + ALOGE("native_window must not be NULL"); | |
4904 | + return; | |
4905 | + } | |
4906 | + | |
4907 | + sp<Surface> surface = static_cast<Surface*>(native_window); | |
4908 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4909 | + s->setISurfaceTexture(surface->getSurfaceTexture()); | |
4910 | +#else | |
4911 | + s->setISurfaceTexture(surface->getIGraphicBufferProducer()); | |
4912 | +#endif | |
4913 | +} | |
4914 | --- /dev/null | |
4915 | +++ libhybris-0.1.0+git20131207+e452e83/compat/media/surface_texture_client_hybris_priv.h | |
4916 | @@ -0,0 +1,68 @@ | |
4917 | +/* | |
4918 | + * Copyright (C) 2013 Canonical Ltd | |
4919 | + * | |
4920 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
4921 | + * you may not use this file except in compliance with the License. | |
4922 | + * You may obtain a copy of the License at | |
4923 | + * | |
4924 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
4925 | + * | |
4926 | + * Unless required by applicable law or agreed to in writing, software | |
4927 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
4928 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
4929 | + * See the License for the specific language governing permissions and | |
4930 | + * limitations under the License. | |
4931 | + * | |
4932 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
4933 | + */ | |
4934 | + | |
4935 | +#include <gui/Surface.h> | |
4936 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4937 | +#include <gui/SurfaceTextureClient.h> | |
4938 | +#else | |
4939 | +#include <gui/GLConsumer.h> | |
4940 | +#endif | |
4941 | + | |
4942 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4943 | +struct _SurfaceTextureClientHybris : public android::SurfaceTextureClient | |
4944 | +#else | |
4945 | +struct _SurfaceTextureClientHybris : public android::Surface | |
4946 | +#endif | |
4947 | +{ | |
4948 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4949 | + _SurfaceTextureClientHybris(); | |
4950 | +#endif | |
4951 | + _SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch); | |
4952 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4953 | + _SurfaceTextureClientHybris(const android::sp<android::ISurfaceTexture> &st); | |
4954 | +#else | |
4955 | + _SurfaceTextureClientHybris(const android::sp<android::BufferQueue> &bq); | |
4956 | +#endif | |
4957 | + ~_SurfaceTextureClientHybris(); | |
4958 | + | |
4959 | + /** Has a texture id or EGLNativeWindowType been passed in, meaning rendering will function? **/ | |
4960 | + bool isReady() const; | |
4961 | + | |
4962 | +public: | |
4963 | + int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd); | |
4964 | + int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd); | |
4965 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4966 | + void setISurfaceTexture(const android::sp<android::ISurfaceTexture>& surface_texture); | |
4967 | +#else | |
4968 | + void setISurfaceTexture(const android::sp<android::IGraphicBufferProducer>& surface_texture); | |
4969 | +#endif | |
4970 | + void setHardwareRendering(bool do_hardware_rendering); | |
4971 | + bool hardwareRendering(); | |
4972 | + | |
4973 | + unsigned int refcount; | |
4974 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
4975 | + android::sp<android::SurfaceTexture> surface_texture; | |
4976 | +#else | |
4977 | + android::sp<android::GLConsumer> surface_texture; | |
4978 | +#endif | |
4979 | + | |
4980 | +private: | |
4981 | + bool ready; | |
4982 | + bool hardware_rendering; | |
4983 | +}; | |
4984 | + | |
4985 | --- libhybris-0.1.0+git20131207+e452e83.orig/compat/ui/Android.mk | |
4986 | +++ libhybris-0.1.0+git20131207+e452e83/compat/ui/Android.mk | |
4987 | @@ -1,5 +1,6 @@ | |
4988 | LOCAL_PATH:= $(call my-dir) | |
4989 | include $(CLEAR_VARS) | |
4990 | +include $(LOCAL_PATH)/../Android.common.mk | |
4991 | ||
4992 | HYBRIS_PATH := $(LOCAL_PATH)/../../hybris | |
4993 | ||
4994 | --- libhybris-0.1.0+git20131207+e452e83.orig/compat/ui/ui_compatibility_layer.cpp | |
4995 | +++ libhybris-0.1.0+git20131207+e452e83/compat/ui/ui_compatibility_layer.cpp | |
4996 | @@ -126,6 +126,7 @@ void* graphic_buffer_get_native_buffer(s | |
4997 | return buffer->self->getNativeBuffer(); | |
4998 | } | |
4999 | ||
5000 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
5001 | void graphic_buffer_set_index(struct graphic_buffer *buffer, int index) | |
5002 | { | |
5003 | return buffer->self->setIndex(index); | |
5004 | @@ -135,6 +136,7 @@ int graphic_buffer_get_index(struct grap | |
5005 | { | |
5006 | return buffer->self->getIndex(); | |
5007 | } | |
5008 | +#endif | |
5009 | ||
5010 | int graphic_buffer_init_check(struct graphic_buffer *buffer) | |
5011 | { | |
5012 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/Makefile.am | |
5013 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/Makefile.am | |
5014 | @@ -4,7 +4,7 @@ if HAS_ANDROID_4_2_0 | |
5015 | SUBDIRS += libsync | |
5016 | endif | |
5017 | ||
5018 | -SUBDIRS += egl glesv1 glesv2 ui sf input camera | |
5019 | +SUBDIRS += egl glesv1 glesv2 ui sf input camera media | |
5020 | if HAS_LIBNFC_NXP_HEADERS | |
5021 | SUBDIRS += libnfc_nxp libnfc_ndef_nxp | |
5022 | endif | |
5023 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks.c | |
5024 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks.c | |
5025 | @@ -27,6 +27,7 @@ | |
5026 | #include <stdio_ext.h> | |
5027 | #include <stddef.h> | |
5028 | #include <stdlib.h> | |
5029 | +#include <limits.h> | |
5030 | #include <malloc.h> | |
5031 | #include <string.h> | |
5032 | #include <strings.h> | |
5033 | @@ -42,6 +43,10 @@ | |
5034 | #include <sys/ipc.h> | |
5035 | #include <sys/shm.h> | |
5036 | ||
5037 | +#include <linux/futex.h> | |
5038 | +#include <sys/syscall.h> | |
5039 | +#include <sys/time.h> | |
5040 | + | |
5041 | #include <netdb.h> | |
5042 | #include <unistd.h> | |
5043 | #include <syslog.h> | |
5044 | @@ -64,8 +69,12 @@ static int locale_inited = 0; | |
5045 | ||
5046 | #define ANDROID_MUTEX_SHARED_MASK 0x2000 | |
5047 | #define ANDROID_COND_SHARED_MASK 0x0001 | |
5048 | +#define ANDROID_COND_COUNTER_INCREMENT 0x0002 | |
5049 | +#define ANDROID_COND_COUNTER_MASK (~ANDROID_COND_SHARED_MASK) | |
5050 | #define ANDROID_RWLOCKATTR_SHARED_MASK 0x0010 | |
5051 | ||
5052 | +#define ANDROID_COND_IS_SHARED(c) (((c)->value & ANDROID_COND_SHARED_MASK) != 0) | |
5053 | + | |
5054 | /* For the static initializer types */ | |
5055 | #define ANDROID_PTHREAD_MUTEX_INITIALIZER 0 | |
5056 | #define ANDROID_PTHREAD_RECURSIVE_MUTEX_INITIALIZER 0x4000 | |
5057 | @@ -87,6 +96,11 @@ struct _hook { | |
5058 | void *func; | |
5059 | }; | |
5060 | ||
5061 | +/* pthread cond struct as done in Android */ | |
5062 | +typedef struct { | |
5063 | + int volatile value; | |
5064 | +} android_cond_t; | |
5065 | + | |
5066 | /* Helpers */ | |
5067 | static int hybris_check_android_shared_mutex(unsigned int mutex_addr) | |
5068 | { | |
5069 | @@ -109,9 +123,59 @@ static int hybris_check_android_shared_c | |
5070 | (cond_addr & ANDROID_COND_SHARED_MASK)) | |
5071 | return 1; | |
5072 | ||
5073 | + /* In case android is setting up cond_addr with a negative value, | |
5074 | + * used for error control */ | |
5075 | + if (cond_addr > HYBRIS_SHM_MASK_TOP) | |
5076 | + return 1; | |
5077 | + | |
5078 | + return 0; | |
5079 | +} | |
5080 | + | |
5081 | +/* Based on Android's Bionic pthread implementation. | |
5082 | + * This is just needed when we have a shared cond with Android */ | |
5083 | +static int __android_pthread_cond_pulse(android_cond_t *cond, int counter) | |
5084 | +{ | |
5085 | + long flags; | |
5086 | + int fret; | |
5087 | + | |
5088 | + if (cond == NULL) | |
5089 | + return EINVAL; | |
5090 | + | |
5091 | + flags = (cond->value & ~ANDROID_COND_COUNTER_MASK); | |
5092 | + for (;;) { | |
5093 | + long oldval = cond->value; | |
5094 | + long newval = 0; | |
5095 | + /* In our case all we need to do is make sure the negative value | |
5096 | + * is under our range, which is the last 0xF from SHM_MASK */ | |
5097 | + if (oldval < -12) | |
5098 | + newval = ((oldval + ANDROID_COND_COUNTER_INCREMENT) & | |
5099 | + ANDROID_COND_COUNTER_MASK) | flags; | |
5100 | + else | |
5101 | + newval = ((oldval - ANDROID_COND_COUNTER_INCREMENT) & | |
5102 | + ANDROID_COND_COUNTER_MASK) | flags; | |
5103 | + if (__sync_bool_compare_and_swap(&cond->value, oldval, newval)) | |
5104 | + break; | |
5105 | + } | |
5106 | + | |
5107 | + int pshared = cond->value & ANDROID_COND_SHARED_MASK; | |
5108 | + fret = syscall(SYS_futex , &cond->value, | |
5109 | + pshared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, counter, | |
5110 | + NULL, NULL, NULL); | |
5111 | + LOGD("futex based pthread_cond_*, value %d, counter %d, ret %d", | |
5112 | + cond->value, counter, fret); | |
5113 | return 0; | |
5114 | } | |
5115 | ||
5116 | +int android_pthread_cond_broadcast(android_cond_t *cond) | |
5117 | +{ | |
5118 | + return __android_pthread_cond_pulse(cond, INT_MAX); | |
5119 | +} | |
5120 | + | |
5121 | +int android_pthread_cond_signal(android_cond_t *cond) | |
5122 | +{ | |
5123 | + return __android_pthread_cond_pulse(cond, 1); | |
5124 | +} | |
5125 | + | |
5126 | static void hybris_set_mutex_attr(unsigned int android_value, pthread_mutexattr_t *attr) | |
5127 | { | |
5128 | /* Init already sets as PTHREAD_MUTEX_NORMAL */ | |
5129 | @@ -577,8 +641,8 @@ static int my_pthread_cond_broadcast(pth | |
5130 | { | |
5131 | unsigned int value = (*(unsigned int *) cond); | |
5132 | if (hybris_check_android_shared_cond(value)) { | |
5133 | - LOGD("shared condition with Android, not broadcasting."); | |
5134 | - return 0; | |
5135 | + LOGD("Shared condition with Android, broadcasting with futex."); | |
5136 | + return android_pthread_cond_broadcast((android_cond_t *) cond); | |
5137 | } | |
5138 | ||
5139 | pthread_cond_t *realcond = (pthread_cond_t *) value; | |
5140 | @@ -598,8 +662,8 @@ static int my_pthread_cond_signal(pthrea | |
5141 | unsigned int value = (*(unsigned int *) cond); | |
5142 | ||
5143 | if (hybris_check_android_shared_cond(value)) { | |
5144 | - LOGD("Shared condition with Android, not signaling."); | |
5145 | - return 0; | |
5146 | + LOGD("Shared condition with Android, broadcasting with futex."); | |
5147 | + return android_pthread_cond_signal((android_cond_t *) cond); | |
5148 | } | |
5149 | ||
5150 | pthread_cond_t *realcond = (pthread_cond_t *) value; | |
5151 | @@ -1217,6 +1281,56 @@ FP_ATTRIB static double my_strtod(const | |
5152 | return strtod_l(nptr, endptr, hybris_locale); | |
5153 | } | |
5154 | ||
5155 | +static int __my_system_property_read(const void *pi, char *name, char *value) | |
5156 | +{ | |
5157 | + return property_get(name, value, NULL); | |
5158 | +} | |
5159 | + | |
5160 | +static int __my_system_property_get(const char *name, char *value) | |
5161 | +{ | |
5162 | + return property_get(name, value, NULL); | |
5163 | +} | |
5164 | + | |
5165 | +static int __my_system_property_foreach(void (*propfn)(const void *pi, void *cookie), void *cookie) | |
5166 | +{ | |
5167 | + return 0; | |
5168 | +} | |
5169 | + | |
5170 | +static const void *__my_system_property_find(const char *name) | |
5171 | +{ | |
5172 | + return NULL; | |
5173 | +} | |
5174 | + | |
5175 | +static unsigned int __my_system_property_serial(const void *pi) | |
5176 | +{ | |
5177 | + return 0; | |
5178 | +} | |
5179 | + | |
5180 | +static int __my_system_property_wait(const void *pi) | |
5181 | +{ | |
5182 | + return 0; | |
5183 | +} | |
5184 | + | |
5185 | +static int __my_system_property_update(void *pi, const char *value, unsigned int len) | |
5186 | +{ | |
5187 | + return 0; | |
5188 | +} | |
5189 | + | |
5190 | +static int __my_system_property_add(const char *name, unsigned int namelen, const char *value, unsigned int valuelen) | |
5191 | +{ | |
5192 | + return 0; | |
5193 | +} | |
5194 | + | |
5195 | +static unsigned int __my_system_property_wait_any(unsigned int serial) | |
5196 | +{ | |
5197 | + return 0; | |
5198 | +} | |
5199 | + | |
5200 | +static const void *__my_system_property_find_nth(unsigned n) | |
5201 | +{ | |
5202 | + return NULL; | |
5203 | +} | |
5204 | + | |
5205 | extern int __cxa_atexit(void (*)(void*), void*, void*); | |
5206 | ||
5207 | static struct _hook hooks[] = { | |
5208 | @@ -1449,6 +1563,17 @@ static struct _hook hooks[] = { | |
5209 | /* grp.h */ | |
5210 | {"getgrgid", getgrgid}, | |
5211 | {"__cxa_atexit", __cxa_atexit}, | |
5212 | + {"__system_property_read", __my_system_property_read}, | |
5213 | + {"__system_property_get", __my_system_property_get}, | |
5214 | + {"__system_property_set", property_set}, | |
5215 | + {"__system_property_foreach", __my_system_property_foreach}, | |
5216 | + {"__system_property_find", __my_system_property_find}, | |
5217 | + {"__system_property_serial", __my_system_property_serial}, | |
5218 | + {"__system_property_wait", __my_system_property_wait}, | |
5219 | + {"__system_property_update", __my_system_property_update}, | |
5220 | + {"__system_property_add", __my_system_property_add}, | |
5221 | + {"__system_property_wait_any", __my_system_property_wait_any}, | |
5222 | + {"__system_property_find_nth", __my_system_property_find_nth}, | |
5223 | {NULL, NULL}, | |
5224 | }; | |
5225 | ||
5226 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks_shm.c | |
5227 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks_shm.c | |
5228 | @@ -123,7 +123,9 @@ static void _hybris_shm_init() | |
5229 | else { | |
5230 | LOGD("Creating a new shared memory segment."); | |
5231 | ||
5232 | - _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0660); | |
5233 | + mode_t pumask = umask(0); | |
5234 | + _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0666); | |
5235 | + umask(pumask); | |
5236 | if (_hybris_shm_fd >= 0) { | |
5237 | ftruncate( _hybris_shm_fd, size_to_map ); | |
5238 | /* Map the memory object */ | |
5239 | @@ -171,11 +173,12 @@ static void _hybris_shm_extend_region() | |
5240 | ||
5241 | /* | |
5242 | * Determine if the pointer that has been extracted by hybris is | |
5243 | - * pointing to an address in the shared memory | |
5244 | + * pointing to an address in the shared memory. | |
5245 | */ | |
5246 | int hybris_is_pointer_in_shm(void *ptr) | |
5247 | { | |
5248 | - if ((unsigned int)ptr >= HYBRIS_SHM_MASK) | |
5249 | + if (((unsigned int) ptr >= HYBRIS_SHM_MASK) && | |
5250 | + ((unsigned int) ptr <= HYBRIS_SHM_MASK_TOP)) | |
5251 | return 1; | |
5252 | ||
5253 | return 0; | |
5254 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks_shm.h | |
5255 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks_shm.h | |
5256 | @@ -20,6 +20,9 @@ | |
5257 | ||
5258 | #include <stddef.h> | |
5259 | ||
5260 | +/* Leave space to workaround the issue that Android might pass negative int values */ | |
5261 | +#define HYBRIS_SHM_MASK_TOP 0xFFFFFFF0UL | |
5262 | + | |
5263 | typedef unsigned int hybris_shm_pointer_t; | |
5264 | ||
5265 | /* | |
5266 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/dlfcn.c | |
5267 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/dlfcn.c | |
5268 | @@ -78,7 +78,7 @@ const char *android_dlerror(void) | |
5269 | void *android_dlsym(void *handle, const char *symbol) | |
5270 | { | |
5271 | soinfo *found; | |
5272 | - Elf32_Sym *sym; | |
5273 | + Elf_Sym *sym; | |
5274 | unsigned bind; | |
5275 | ||
5276 | pthread_mutex_lock(&dl_lock); | |
5277 | @@ -142,7 +142,7 @@ int android_dladdr(const void *addr, Dl_ | |
5278 | info->dli_fbase = (void*)si->base; | |
5279 | ||
5280 | /* Determine if any symbol in the library contains the specified address */ | |
5281 | - Elf32_Sym *sym = find_containing_symbol(addr, si); | |
5282 | + Elf_Sym *sym = find_containing_symbol(addr, si); | |
5283 | ||
5284 | if(sym != NULL) { | |
5285 | info->dli_sname = si->strtab + sym->st_name; | |
5286 | @@ -192,7 +192,7 @@ int android_dl_iterate_phdr(int (*cb)(st | |
5287 | #endif | |
5288 | ||
5289 | ||
5290 | -static Elf32_Sym libdl_symtab[] = { | |
5291 | +static Elf_Sym libdl_symtab[] = { | |
5292 | // total length of libdl_info.strtab, including trailing 0 | |
5293 | // This is actually the the STH_UNDEF entry. Technically, it's | |
5294 | // supposed to have st_name == 0, but instead, it points to an index | |
5295 | @@ -200,45 +200,45 @@ static Elf32_Sym libdl_symtab[] = { | |
5296 | { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, | |
5297 | }, | |
5298 | { st_name: 0, // starting index of the name in libdl_info.strtab | |
5299 | - st_value: (Elf32_Addr) &android_dlopen, | |
5300 | + st_value: (Elf_Addr) &android_dlopen, | |
5301 | st_info: STB_GLOBAL << 4, | |
5302 | st_shndx: 1, | |
5303 | }, | |
5304 | { st_name: 7, | |
5305 | - st_value: (Elf32_Addr) &android_dlclose, | |
5306 | + st_value: (Elf_Addr) &android_dlclose, | |
5307 | st_info: STB_GLOBAL << 4, | |
5308 | st_shndx: 1, | |
5309 | }, | |
5310 | { st_name: 15, | |
5311 | - st_value: (Elf32_Addr) &android_dlsym, | |
5312 | + st_value: (Elf_Addr) &android_dlsym, | |
5313 | st_info: STB_GLOBAL << 4, | |
5314 | st_shndx: 1, | |
5315 | }, | |
5316 | { st_name: 21, | |
5317 | - st_value: (Elf32_Addr) &android_dlerror, | |
5318 | + st_value: (Elf_Addr) &android_dlerror, | |
5319 | st_info: STB_GLOBAL << 4, | |
5320 | st_shndx: 1, | |
5321 | }, | |
5322 | { st_name: 29, | |
5323 | - st_value: (Elf32_Addr) &android_dladdr, | |
5324 | + st_value: (Elf_Addr) &android_dladdr, | |
5325 | st_info: STB_GLOBAL << 4, | |
5326 | st_shndx: 1, | |
5327 | }, | |
5328 | #ifdef ANDROID_ARM_LINKER | |
5329 | { st_name: 36, | |
5330 | - st_value: (Elf32_Addr) &android_dl_unwind_find_exidx, | |
5331 | + st_value: (Elf_Addr) &android_dl_unwind_find_exidx, | |
5332 | st_info: STB_GLOBAL << 4, | |
5333 | st_shndx: 1, | |
5334 | }, | |
5335 | #elif defined(ANDROID_X86_LINKER) | |
5336 | { st_name: 36, | |
5337 | - st_value: (Elf32_Addr) &android_dl_iterate_phdr, | |
5338 | + st_value: (Elf_Addr) &android_dl_iterate_phdr, | |
5339 | st_info: STB_GLOBAL << 4, | |
5340 | st_shndx: 1, | |
5341 | }, | |
5342 | #elif defined(ANDROID_SH_LINKER) | |
5343 | { st_name: 36, | |
5344 | - st_value: (Elf32_Addr) &android_dl_iterate_phdr, | |
5345 | + st_value: (Elf_Addr) &android_dl_iterate_phdr, | |
5346 | st_info: STB_GLOBAL << 4, | |
5347 | st_shndx: 1, | |
5348 | }, | |
5349 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker.c | |
5350 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.c | |
5351 | @@ -381,10 +381,10 @@ android_dl_iterate_phdr(int (*cb)(struct | |
5352 | } | |
5353 | #endif | |
5354 | ||
5355 | -static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) | |
5356 | +static Elf_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) | |
5357 | { | |
5358 | - Elf32_Sym *s; | |
5359 | - Elf32_Sym *symtab = si->symtab; | |
5360 | + Elf_Sym *s; | |
5361 | + Elf_Sym *symtab = si->symtab; | |
5362 | const char *strtab = si->strtab; | |
5363 | unsigned n; | |
5364 | ||
5365 | @@ -426,11 +426,11 @@ static unsigned elfhash(const char *_nam | |
5366 | return h; | |
5367 | } | |
5368 | ||
5369 | -static Elf32_Sym * | |
5370 | +static Elf_Sym * | |
5371 | _do_lookup(soinfo *si, const char *name, unsigned *base) | |
5372 | { | |
5373 | unsigned elf_hash = elfhash(name); | |
5374 | - Elf32_Sym *s; | |
5375 | + Elf_Sym *s; | |
5376 | unsigned *d; | |
5377 | soinfo *lsi = si; | |
5378 | int i; | |
5379 | @@ -502,17 +502,17 @@ done: | |
5380 | /* This is used by dl_sym(). It performs symbol lookup only within the | |
5381 | specified soinfo object and not in any of its dependencies. | |
5382 | */ | |
5383 | -Elf32_Sym *lookup_in_library(soinfo *si, const char *name) | |
5384 | +Elf_Sym *lookup_in_library(soinfo *si, const char *name) | |
5385 | { | |
5386 | return _elf_lookup(si, elfhash(name), name); | |
5387 | } | |
5388 | ||
5389 | /* This is used by dl_sym(). It performs a global symbol lookup. | |
5390 | */ | |
5391 | -Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start) | |
5392 | +Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start) | |
5393 | { | |
5394 | unsigned elf_hash = elfhash(name); | |
5395 | - Elf32_Sym *s = NULL; | |
5396 | + Elf_Sym *s = NULL; | |
5397 | soinfo *si; | |
5398 | ||
5399 | if(start == NULL) { | |
5400 | @@ -553,7 +553,7 @@ soinfo *find_containing_library(const vo | |
5401 | return NULL; | |
5402 | } | |
5403 | ||
5404 | -Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si) | |
5405 | +Elf_Sym *find_containing_symbol(const void *addr, soinfo *si) | |
5406 | { | |
5407 | unsigned int i; | |
5408 | unsigned soaddr = (unsigned)addr - si->base; | |
5409 | @@ -561,7 +561,7 @@ Elf32_Sym *find_containing_symbol(const | |
5410 | /* Search the library's symbol table for any defined symbol which | |
5411 | * contains this address */ | |
5412 | for(i=0; i<si->nchain; i++) { | |
5413 | - Elf32_Sym *sym = &si->symtab[i]; | |
5414 | + Elf_Sym *sym = &si->symtab[i]; | |
5415 | ||
5416 | if(sym->st_shndx != SHN_UNDEF && | |
5417 | soaddr >= sym->st_value && | |
5418 | @@ -576,7 +576,7 @@ Elf32_Sym *find_containing_symbol(const | |
5419 | #if 0 | |
5420 | static void dump(soinfo *si) | |
5421 | { | |
5422 | - Elf32_Sym *s = si->symtab; | |
5423 | + Elf_Sym *s = si->symtab; | |
5424 | unsigned n; | |
5425 | ||
5426 | for(n = 0; n < si->nchain; n++) { | |
5427 | @@ -705,7 +705,7 @@ is_prelinked(int fd, const char *name) | |
5428 | static int | |
5429 | verify_elf_object(void *base, const char *name) | |
5430 | { | |
5431 | - Elf32_Ehdr *hdr = (Elf32_Ehdr *) base; | |
5432 | + Elf_Ehdr *hdr = (Elf_Ehdr *) base; | |
5433 | ||
5434 | if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1; | |
5435 | if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; | |
5436 | @@ -750,8 +750,8 @@ get_lib_extents(int fd, const char *name | |
5437 | unsigned min_vaddr = 0xffffffff; | |
5438 | unsigned max_vaddr = 0; | |
5439 | unsigned char *_hdr = (unsigned char *)__hdr; | |
5440 | - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; | |
5441 | - Elf32_Phdr *phdr; | |
5442 | + Elf_Ehdr *ehdr = (Elf_Ehdr *)_hdr; | |
5443 | + Elf_Phdr *phdr; | |
5444 | int cnt; | |
5445 | ||
5446 | TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); | |
5447 | @@ -770,7 +770,7 @@ get_lib_extents(int fd, const char *name | |
5448 | TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name); | |
5449 | } | |
5450 | ||
5451 | - phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); | |
5452 | + phdr = (Elf_Phdr *)(_hdr + ehdr->e_phoff); | |
5453 | ||
5454 | /* find the min/max p_vaddrs from all the PT_LOAD segments so we can | |
5455 | * get the range. */ | |
5456 | @@ -885,12 +885,12 @@ err: | |
5457 | static int | |
5458 | load_segments(int fd, void *header, soinfo *si) | |
5459 | { | |
5460 | - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; | |
5461 | - Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); | |
5462 | - Elf32_Addr base = (Elf32_Addr) si->base; | |
5463 | + Elf_Ehdr *ehdr = (Elf_Ehdr *)header; | |
5464 | + Elf_Phdr *phdr = (Elf_Phdr *)((unsigned char *)header + ehdr->e_phoff); | |
5465 | + Elf_Addr base = (Elf_Addr) si->base; | |
5466 | int cnt; | |
5467 | unsigned len; | |
5468 | - Elf32_Addr tmp; | |
5469 | + Elf_Addr tmp; | |
5470 | unsigned char *pbase; | |
5471 | unsigned char *extra_base; | |
5472 | unsigned extra_len; | |
5473 | @@ -956,7 +956,7 @@ load_segments(int fd, void *header, soin | |
5474 | * | | | |
5475 | * _+---------------------+ page boundary | |
5476 | */ | |
5477 | - tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & | |
5478 | + tmp = (Elf_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & | |
5479 | (~PAGE_MASK)); | |
5480 | if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) { | |
5481 | extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; | |
5482 | @@ -1020,7 +1020,7 @@ load_segments(int fd, void *header, soin | |
5483 | phdr->p_vaddr, phdr->p_memsz); | |
5484 | goto fail; | |
5485 | } | |
5486 | - si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr); | |
5487 | + si->gnu_relro_start = (Elf_Addr) (base + phdr->p_vaddr); | |
5488 | si->gnu_relro_len = (unsigned) phdr->p_memsz; | |
5489 | } else { | |
5490 | #ifdef ANDROID_ARM_LINKER | |
5491 | @@ -1067,11 +1067,11 @@ fail: | |
5492 | */ | |
5493 | #if 0 | |
5494 | static unsigned | |
5495 | -get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) | |
5496 | +get_wr_offset(int fd, const char *name, Elf_Ehdr *ehdr) | |
5497 | { | |
5498 | - Elf32_Shdr *shdr_start; | |
5499 | - Elf32_Shdr *shdr; | |
5500 | - int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr); | |
5501 | + Elf_Shdr *shdr_start; | |
5502 | + Elf_Shdr *shdr; | |
5503 | + int shdr_sz = ehdr->e_shnum * sizeof(Elf_Shdr); | |
5504 | int cnt; | |
5505 | unsigned wr_offset = 0xffffffff; | |
5506 | ||
5507 | @@ -1104,7 +1104,7 @@ load_library(const char *name) | |
5508 | unsigned req_base; | |
5509 | const char *bname; | |
5510 | soinfo *si = NULL; | |
5511 | - Elf32_Ehdr *hdr; | |
5512 | + Elf_Ehdr *hdr; | |
5513 | ||
5514 | if(fd == -1) { | |
5515 | DL_ERR("Library '%s' not found", name); | |
5516 | @@ -1161,8 +1161,8 @@ load_library(const char *name) | |
5517 | ||
5518 | /* this might not be right. Technically, we don't even need this info | |
5519 | * once we go through 'load_segments'. */ | |
5520 | - hdr = (Elf32_Ehdr *)si->base; | |
5521 | - si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); | |
5522 | + hdr = (Elf_Ehdr *)si->base; | |
5523 | + si->phdr = (Elf_Phdr *)((unsigned char *)si->base + hdr->e_phoff); | |
5524 | si->phnum = hdr->e_phnum; | |
5525 | /**/ | |
5526 | ||
5527 | @@ -1261,7 +1261,7 @@ unsigned unload_library(soinfo *si) | |
5528 | * in link_image. This is needed to undo the DT_NEEDED hack below. | |
5529 | */ | |
5530 | if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) { | |
5531 | - Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); | |
5532 | + Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); | |
5533 | unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; | |
5534 | if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0) | |
5535 | DL_ERR("%5d %s: could not undo GNU_RELRO protections. " | |
5536 | @@ -1304,16 +1304,16 @@ unsigned unload_library(soinfo *si) | |
5537 | } | |
5538 | ||
5539 | /* TODO: don't use unsigned for addrs below. It works, but is not | |
5540 | - * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned | |
5541 | + * ideal. They should probably be either uint32_t, Elf_Addr, or unsigned | |
5542 | * long. | |
5543 | */ | |
5544 | -static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) | |
5545 | +static int reloc_library(soinfo *si, Elf_Rel *rel, unsigned count) | |
5546 | { | |
5547 | - Elf32_Sym *symtab = si->symtab; | |
5548 | + Elf_Sym *symtab = si->symtab; | |
5549 | const char *strtab = si->strtab; | |
5550 | - Elf32_Sym *s; | |
5551 | + Elf_Sym *s; | |
5552 | unsigned base; | |
5553 | - Elf32_Rel *start = rel; | |
5554 | + Elf_Rel *start = rel; | |
5555 | unsigned idx; | |
5556 | ||
5557 | for (idx = 0; idx < count; ++idx) { | |
5558 | @@ -1712,7 +1712,7 @@ static int nullify_closed_stdio (void) | |
5559 | static int link_image(soinfo *si, unsigned wr_offset) | |
5560 | { | |
5561 | unsigned *d; | |
5562 | - Elf32_Phdr *phdr = si->phdr; | |
5563 | + Elf_Phdr *phdr = si->phdr; | |
5564 | int phnum = si->phnum; | |
5565 | ||
5566 | INFO("[ %5d linking %s ]\n", pid, si->name); | |
5567 | @@ -1795,7 +1795,7 @@ static int link_image(soinfo *si, unsign | |
5568 | phdr->p_vaddr, phdr->p_memsz); | |
5569 | goto fail; | |
5570 | } | |
5571 | - si->gnu_relro_start = (Elf32_Addr) (si->base + phdr->p_vaddr); | |
5572 | + si->gnu_relro_start = (Elf_Addr) (si->base + phdr->p_vaddr); | |
5573 | si->gnu_relro_len = (unsigned) phdr->p_memsz; | |
5574 | } | |
5575 | } | |
5576 | @@ -1822,7 +1822,7 @@ static int link_image(soinfo *si, unsign | |
5577 | si->strtab = (const char *) (si->base + *d); | |
5578 | break; | |
5579 | case DT_SYMTAB: | |
5580 | - si->symtab = (Elf32_Sym *) (si->base + *d); | |
5581 | + si->symtab = (Elf_Sym *) (si->base + *d); | |
5582 | break; | |
5583 | case DT_PLTREL: | |
5584 | if(*d != DT_REL) { | |
5585 | @@ -1831,13 +1831,13 @@ static int link_image(soinfo *si, unsign | |
5586 | } | |
5587 | break; | |
5588 | case DT_JMPREL: | |
5589 | - si->plt_rel = (Elf32_Rel*) (si->base + *d); | |
5590 | + si->plt_rel = (Elf_Rel*) (si->base + *d); | |
5591 | break; | |
5592 | case DT_PLTRELSZ: | |
5593 | si->plt_rel_count = *d / 8; | |
5594 | break; | |
5595 | case DT_REL: | |
5596 | - si->rel = (Elf32_Rel*) (si->base + *d); | |
5597 | + si->rel = (Elf_Rel*) (si->base + *d); | |
5598 | break; | |
5599 | case DT_RELSZ: | |
5600 | si->rel_count = *d / 8; | |
5601 | @@ -1869,7 +1869,7 @@ static int link_image(soinfo *si, unsign | |
5602 | pid, si->name, si->init_array); | |
5603 | break; | |
5604 | case DT_INIT_ARRAYSZ: | |
5605 | - si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); | |
5606 | + si->init_array_count = ((unsigned)*d) / sizeof(Elf_Addr); | |
5607 | break; | |
5608 | case DT_FINI_ARRAY: | |
5609 | si->fini_array = (unsigned *)(si->base + *d); | |
5610 | @@ -1877,7 +1877,7 @@ static int link_image(soinfo *si, unsign | |
5611 | pid, si->name, si->fini_array); | |
5612 | break; | |
5613 | case DT_FINI_ARRAYSZ: | |
5614 | - si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); | |
5615 | + si->fini_array_count = ((unsigned)*d) / sizeof(Elf_Addr); | |
5616 | break; | |
5617 | case DT_PREINIT_ARRAY: | |
5618 | si->preinit_array = (unsigned *)(si->base + *d); | |
5619 | @@ -1885,7 +1885,7 @@ static int link_image(soinfo *si, unsign | |
5620 | pid, si->name, si->preinit_array); | |
5621 | break; | |
5622 | case DT_PREINIT_ARRAYSZ: | |
5623 | - si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); | |
5624 | + si->preinit_array_count = ((unsigned)*d) / sizeof(Elf_Addr); | |
5625 | break; | |
5626 | case DT_TEXTREL: | |
5627 | /* TODO: make use of this. */ | |
5628 | @@ -1987,7 +1987,7 @@ static int link_image(soinfo *si, unsign | |
5629 | #endif | |
5630 | ||
5631 | if (si->gnu_relro_start != 0 && si->gnu_relro_len != 0) { | |
5632 | - Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); | |
5633 | + Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); | |
5634 | unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; | |
5635 | if (mprotect((void *) start, len, PROT_READ) < 0) { | |
5636 | DL_ERR("%5d GNU_RELRO mprotect of library '%s' failed: %d (%s)\n", | |
5637 | @@ -2170,7 +2170,7 @@ sanitize: | |
5638 | while(vecs[0] != 0){ | |
5639 | switch(vecs[0]){ | |
5640 | case AT_PHDR: | |
5641 | - si->phdr = (Elf32_Phdr*) vecs[1]; | |
5642 | + si->phdr = (Elf_Phdr*) vecs[1]; | |
5643 | break; | |
5644 | case AT_PHNUM: | |
5645 | si->phnum = (int) vecs[1]; | |
5646 | @@ -2190,7 +2190,7 @@ sanitize: | |
5647 | si->base = 0; | |
5648 | for ( nn = 0; nn < si->phnum; nn++ ) { | |
5649 | if (si->phdr[nn].p_type == PT_PHDR) { | |
5650 | - si->base = (Elf32_Addr) si->phdr - si->phdr[nn].p_vaddr; | |
5651 | + si->base = (Elf_Addr) si->phdr - si->phdr[nn].p_vaddr; | |
5652 | break; | |
5653 | } | |
5654 | } | |
5655 | @@ -2303,9 +2303,9 @@ static unsigned find_linker_base(unsigne | |
5656 | */ | |
5657 | unsigned __linker_init(unsigned **elfdata) { | |
5658 | unsigned linker_addr = find_linker_base(elfdata); | |
5659 | - Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_addr; | |
5660 | - Elf32_Phdr *phdr = | |
5661 | - (Elf32_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); | |
5662 | + Elf_Ehdr *elf_hdr = (Elf_Ehdr *) linker_addr; | |
5663 | + Elf_Phdr *phdr = | |
5664 | + (Elf_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); | |
5665 | ||
5666 | soinfo linker_so; | |
5667 | memset(&linker_so, 0, sizeof(soinfo)); | |
5668 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker.h | |
5669 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.h | |
5670 | @@ -38,6 +38,26 @@ | |
5671 | #define PAGE_SIZE 4096 | |
5672 | #define PAGE_MASK 4095 | |
5673 | ||
5674 | +#if defined(__x86_64__) | |
5675 | +typedef Elf64_Ehdr Elf_Ehdr; | |
5676 | +typedef Elf64_Shdr Elf_Shdr; | |
5677 | +typedef Elf64_Sym Elf_Sym; | |
5678 | +typedef Elf64_Addr Elf_Addr; | |
5679 | +typedef Elf64_Phdr Elf_Phdr; | |
5680 | +typedef Elf64_Half Elf_Half; | |
5681 | +typedef Elf64_Rel Elf_Rel; | |
5682 | +typedef Elf64_Rela Elf_Rela; | |
5683 | +#else | |
5684 | +typedef Elf32_Ehdr Elf_Ehdr; | |
5685 | +typedef Elf32_Shdr Elf_Shdr; | |
5686 | +typedef Elf32_Sym Elf_Sym; | |
5687 | +typedef Elf32_Addr Elf_Addr; | |
5688 | +typedef Elf32_Phdr Elf_Phdr; | |
5689 | +typedef Elf32_Half Elf_Half; | |
5690 | +typedef Elf32_Rel Elf_Rel; | |
5691 | +typedef Elf32_Rela Elf_Rela; | |
5692 | +#endif | |
5693 | + | |
5694 | void debugger_init(); | |
5695 | const char *addr_to_name(unsigned addr); | |
5696 | ||
5697 | @@ -55,10 +75,10 @@ struct link_map | |
5698 | /* needed for dl_iterate_phdr to be passed to the callbacks provided */ | |
5699 | struct dl_phdr_info | |
5700 | { | |
5701 | - Elf32_Addr dlpi_addr; | |
5702 | + Elf_Addr dlpi_addr; | |
5703 | const char *dlpi_name; | |
5704 | - const Elf32_Phdr *dlpi_phdr; | |
5705 | - Elf32_Half dlpi_phnum; | |
5706 | + const Elf_Phdr *dlpi_phdr; | |
5707 | + Elf_Half dlpi_phnum; | |
5708 | }; | |
5709 | ||
5710 | ||
5711 | @@ -90,7 +110,7 @@ typedef struct soinfo soinfo; | |
5712 | struct soinfo | |
5713 | { | |
5714 | const char name[SOINFO_NAME_LEN]; | |
5715 | - Elf32_Phdr *phdr; | |
5716 | + Elf_Phdr *phdr; | |
5717 | int phnum; | |
5718 | unsigned entry; | |
5719 | unsigned base; | |
5720 | @@ -107,7 +127,7 @@ struct soinfo | |
5721 | unsigned flags; | |
5722 | ||
5723 | const char *strtab; | |
5724 | - Elf32_Sym *symtab; | |
5725 | + Elf_Sym *symtab; | |
5726 | ||
5727 | unsigned nbucket; | |
5728 | unsigned nchain; | |
5729 | @@ -116,10 +136,10 @@ struct soinfo | |
5730 | ||
5731 | unsigned *plt_got; | |
5732 | ||
5733 | - Elf32_Rel *plt_rel; | |
5734 | + Elf_Rel *plt_rel; | |
5735 | unsigned plt_rel_count; | |
5736 | ||
5737 | - Elf32_Rel *rel; | |
5738 | + Elf_Rel *rel; | |
5739 | unsigned rel_count; | |
5740 | ||
5741 | unsigned *preinit_array; | |
5742 | @@ -144,7 +164,7 @@ struct soinfo | |
5743 | ||
5744 | int constructors_called; | |
5745 | ||
5746 | - Elf32_Addr gnu_relro_start; | |
5747 | + Elf_Addr gnu_relro_start; | |
5748 | unsigned gnu_relro_len; | |
5749 | ||
5750 | }; | |
5751 | @@ -202,10 +222,10 @@ extern soinfo libdl_info; | |
5752 | ||
5753 | soinfo *find_library(const char *name); | |
5754 | unsigned unload_library(soinfo *si); | |
5755 | -Elf32_Sym *lookup_in_library(soinfo *si, const char *name); | |
5756 | -Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start); | |
5757 | +Elf_Sym *lookup_in_library(soinfo *si, const char *name); | |
5758 | +Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start); | |
5759 | soinfo *find_containing_library(const void *addr); | |
5760 | -Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si); | |
5761 | +Elf_Sym *find_containing_symbol(const void *addr, soinfo *si); | |
5762 | const char *linker_get_error(void); | |
5763 | void call_constructors_recursive(soinfo *si); | |
5764 | ||
5765 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker_format.c | |
5766 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker_format.c | |
5767 | @@ -268,7 +268,7 @@ static int log_vprint(int prio, const ch | |
5768 | result = vformat_buffer(buf, sizeof buf, fmt, args); | |
5769 | ||
5770 | if (log_fd < 0) { | |
5771 | - log_fd = open("/dev/log/main", O_WRONLY); | |
5772 | + log_fd = open("/dev/alog/main", O_WRONLY); | |
5773 | if (log_fd < 0) { | |
5774 | log_fd = fileno(stdout); // kernel doesn't have android log | |
5775 | return result; | |
5776 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/configure.ac | |
5777 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/configure.ac | |
5778 | @@ -184,6 +184,8 @@ AC_CONFIG_FILES([ | |
5779 | input/libis.pc | |
5780 | camera/Makefile | |
5781 | camera/libcamera.pc | |
5782 | + media/Makefile | |
5783 | + media/libmedia.pc | |
5784 | include/Makefile | |
5785 | utils/Makefile | |
5786 | tests/Makefile | |
5787 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/hardware/hardware.c | |
5788 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/hardware/hardware.c | |
5789 | @@ -17,6 +17,7 @@ | |
5790 | ||
5791 | #include <dlfcn.h> | |
5792 | #include <stddef.h> | |
5793 | +#include <errno.h> | |
5794 | #include <android/hardware/hardware.h> | |
5795 | #include <hybris/internal/binding.h> | |
5796 | ||
5797 | @@ -26,15 +27,20 @@ static int (*_hw_get_module)(const char | |
5798 | ||
5799 | static int (*_hw_get_module_by_class)(const char *class_id, const char *inst, const struct hw_module_t **module) = NULL; | |
5800 | ||
5801 | -#define HARDWARE_DLSYM(fptr, sym) do { if (_libhardware == NULL) { _init_lib_hardware(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libhardware, sym); } } while (0) | |
5802 | +#define HARDWARE_DLSYM(fptr, sym) do { if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libhardware, sym); } } while (0) | |
5803 | ||
5804 | -static void _init_lib_hardware() | |
5805 | +static void *_init_lib_hardware() | |
5806 | { | |
5807 | - _libhardware = (void *) android_dlopen("/system/lib/libhardware.so", RTLD_LAZY); | |
5808 | + if (!_libhardware) | |
5809 | + _libhardware = (void *) android_dlopen("/system/lib/libhardware.so", RTLD_LAZY); | |
5810 | + return _libhardware; | |
5811 | } | |
5812 | ||
5813 | int hw_get_module(const char *id, const struct hw_module_t **module) | |
5814 | { | |
5815 | + if (!_init_lib_hardware()) | |
5816 | + return -EINVAL; | |
5817 | + | |
5818 | HARDWARE_DLSYM(&_hw_get_module, "hw_get_module"); | |
5819 | return (*_hw_get_module)(id, module); | |
5820 | } | |
5821 | @@ -42,6 +48,9 @@ int hw_get_module(const char *id, const | |
5822 | int hw_get_module_by_class(const char *class_id, const char *inst, | |
5823 | const struct hw_module_t **module) | |
5824 | { | |
5825 | + if (!_init_lib_hardware()) | |
5826 | + return -EINVAL; | |
5827 | + | |
5828 | HARDWARE_DLSYM(&_hw_get_module_by_class, "hw_get_module_by_class"); | |
5829 | return (*_hw_get_module_by_class)(class_id, inst, module); | |
5830 | } | |
5831 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/Makefile.am | |
5832 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/Makefile.am | |
5833 | @@ -65,6 +65,15 @@ propertiesincludedir = $(includedir)/hyb | |
5834 | propertiesinclude_HEADERS = \ | |
5835 | hybris/properties/properties.h | |
5836 | ||
5837 | +mediaincludedir = $(includedir)/hybris/media | |
5838 | +mediainclude_HEADERS = \ | |
5839 | + hybris/media/media_compatibility_layer.h \ | |
5840 | + hybris/media/media_codec_layer.h \ | |
5841 | + hybris/media/media_codec_list.h \ | |
5842 | + hybris/media/media_format_layer.h \ | |
5843 | + hybris/media/surface_texture_client_hybris.h \ | |
5844 | + hybris/media/recorder_compatibility_layer.h | |
5845 | + | |
5846 | dlfcnincludedir = $(includedir)/hybris/dlfcn | |
5847 | dlfcninclude_HEADERS = \ | |
5848 | hybris/dlfcn/dlfcn.h | |
5849 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/input/input_stack_compatibility_layer.h | |
5850 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/input/input_stack_compatibility_layer.h | |
5851 | @@ -109,6 +109,7 @@ extern "C" { | |
5852 | int input_area_height; | |
5853 | }; | |
5854 | ||
5855 | + int android_input_check_availability(); | |
5856 | void android_input_stack_initialize( | |
5857 | struct AndroidEventListener* listener, | |
5858 | struct InputStackConfiguration* input_stack_configuration); | |
5859 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/internal/camera_control.h | |
5860 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/camera_control.h | |
5861 | @@ -19,7 +19,11 @@ | |
5862 | ||
5863 | #include <camera/Camera.h> | |
5864 | #include <camera/CameraParameters.h> | |
5865 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
5866 | #include <gui/SurfaceTexture.h> | |
5867 | +#else | |
5868 | +#include <gui/GLConsumer.h> | |
5869 | +#endif | |
5870 | ||
5871 | #include <stdint.h> | |
5872 | #include <unistd.h> | |
5873 | @@ -31,15 +35,22 @@ extern "C" { | |
5874 | struct CameraControlListener; | |
5875 | ||
5876 | struct CameraControl : public android::CameraListener, | |
5877 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
5878 | public android::SurfaceTexture::FrameAvailableListener | |
5879 | +#else | |
5880 | + public android::GLConsumer::FrameAvailableListener | |
5881 | +#endif | |
5882 | { | |
5883 | android::Mutex guard; | |
5884 | CameraControlListener* listener; | |
5885 | android::sp<android::Camera> camera; | |
5886 | android::CameraParameters camera_parameters; | |
5887 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 | |
5888 | android::sp<android::SurfaceTexture> preview_texture; | |
5889 | - | |
5890 | - // From android::SurfaceTexture::FrameAvailableListener | |
5891 | +#else | |
5892 | + android::sp<android::GLConsumer> preview_texture; | |
5893 | +#endif | |
5894 | + // From android::SurfaceTexture/GLConsumer::FrameAvailableListener | |
5895 | void onFrameAvailable(); | |
5896 | ||
5897 | // From android::CameraListener | |
5898 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h | |
5899 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h | |
5900 | @@ -25,6 +25,7 @@ | |
5901 | ||
5902 | #include <utils/misc.h> | |
5903 | ||
5904 | +#include <gui/Surface.h> | |
5905 | #include <gui/SurfaceComposerClient.h> | |
5906 | #include <ui/PixelFormat.h> | |
5907 | #include <ui/Region.h> | |
5908 | --- /dev/null | |
5909 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_codec_layer.h | |
5910 | @@ -0,0 +1,93 @@ | |
5911 | +/* | |
5912 | + * Copyright (C) 2013 Canonical Ltd | |
5913 | + * | |
5914 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5915 | + * you may not use this file except in compliance with the License. | |
5916 | + * You may obtain a copy of the License at | |
5917 | + * | |
5918 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
5919 | + * | |
5920 | + * Unless required by applicable law or agreed to in writing, software | |
5921 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
5922 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
5923 | + * See the License for the specific language governing permissions and | |
5924 | + * limitations under the License. | |
5925 | + * | |
5926 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
5927 | + */ | |
5928 | + | |
5929 | +#ifndef MEDIA_CODEC_LAYER_H_ | |
5930 | +#define MEDIA_CODEC_LAYER_H_ | |
5931 | + | |
5932 | +#include <stdint.h> | |
5933 | +#include <unistd.h> | |
5934 | + | |
5935 | +#ifdef SIMPLE_PLAYER | |
5936 | +#include <media/stagefright/MediaCodec.h> | |
5937 | +#endif | |
5938 | + | |
5939 | +#include <hybris/media/media_format_layer.h> | |
5940 | +#include <hybris/media/surface_texture_client_hybris.h> | |
5941 | + | |
5942 | +#ifdef __cplusplus | |
5943 | +extern "C" { | |
5944 | +#endif | |
5945 | + | |
5946 | + typedef void* MediaCodecDelegate; | |
5947 | + | |
5948 | + typedef void (*on_texture_needs_update)(void *context); | |
5949 | + void media_codec_set_texture_needs_update_cb(MediaCodecDelegate delegate, on_texture_needs_update cb, void *context); | |
5950 | + | |
5951 | + MediaCodecDelegate media_codec_create_by_codec_name(const char *name); | |
5952 | + MediaCodecDelegate media_codec_create_by_codec_type(const char *type); | |
5953 | + | |
5954 | +#ifdef SIMPLE_PLAYER | |
5955 | + android::MediaCodec* media_codec_get(MediaCodecDelegate delegate); | |
5956 | +#endif | |
5957 | + | |
5958 | + void media_codec_delegate_destroy(MediaCodecDelegate delegate); | |
5959 | + void media_codec_delegate_ref(MediaCodecDelegate delegate); | |
5960 | + void media_codec_delegate_unref(MediaCodecDelegate delegate); | |
5961 | + | |
5962 | +#ifdef SIMPLE_PLAYER | |
5963 | + int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, void *nativeWindow, uint32_t flags); | |
5964 | +#else | |
5965 | + int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, SurfaceTextureClientHybris stc, uint32_t flags); | |
5966 | +#endif | |
5967 | + int media_codec_set_surface_texture_client(MediaCodecDelegate delegate, SurfaceTextureClientHybris stc); | |
5968 | + | |
5969 | + int media_codec_queue_csd(MediaCodecDelegate delegate, MediaFormat format); | |
5970 | + int media_codec_start(MediaCodecDelegate delegate); | |
5971 | + int media_codec_stop(MediaCodecDelegate delegate); | |
5972 | + int media_codec_release(MediaCodecDelegate delegate); | |
5973 | + int media_codec_flush(MediaCodecDelegate delegate); | |
5974 | + size_t media_codec_get_input_buffers_size(MediaCodecDelegate delegate); | |
5975 | + uint8_t *media_codec_get_nth_input_buffer(MediaCodecDelegate delegate, size_t n); | |
5976 | + size_t media_codec_get_nth_input_buffer_capacity(MediaCodecDelegate delegate, size_t n); | |
5977 | + size_t media_codec_get_output_buffers_size(MediaCodecDelegate delegate); | |
5978 | + uint8_t *media_codec_get_nth_output_buffer(MediaCodecDelegate delegate, size_t n); | |
5979 | + size_t media_codec_get_nth_output_buffer_capacity(MediaCodecDelegate delegate, size_t n); | |
5980 | + | |
5981 | + struct _MediaCodecBufferInfo | |
5982 | + { | |
5983 | + size_t index; | |
5984 | + size_t offset; | |
5985 | + size_t size; | |
5986 | + int64_t presentation_time_us; | |
5987 | + uint32_t flags; | |
5988 | + uint8_t render_retries; | |
5989 | + }; | |
5990 | + typedef struct _MediaCodecBufferInfo MediaCodecBufferInfo; | |
5991 | + | |
5992 | + int media_codec_dequeue_output_buffer(MediaCodecDelegate delegate, MediaCodecBufferInfo *info, int64_t timeout_us); | |
5993 | + int media_codec_queue_input_buffer(MediaCodecDelegate delegate, const MediaCodecBufferInfo *info); | |
5994 | + int media_codec_dequeue_input_buffer(MediaCodecDelegate delegate, size_t *index, int64_t timeout_us); | |
5995 | + int media_codec_release_output_buffer(MediaCodecDelegate delegate, size_t index, uint8_t render); | |
5996 | + | |
5997 | + MediaFormat media_codec_get_output_format(MediaCodecDelegate delegate); | |
5998 | + | |
5999 | +#ifdef __cplusplus | |
6000 | +} | |
6001 | +#endif | |
6002 | + | |
6003 | +#endif // MEDIA_CODEC_LAYER_H_ | |
6004 | --- /dev/null | |
6005 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_codec_list.h | |
6006 | @@ -0,0 +1,56 @@ | |
6007 | +/* | |
6008 | + * Copyright (C) 2013 Canonical Ltd | |
6009 | + * | |
6010 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6011 | + * you may not use this file except in compliance with the License. | |
6012 | + * You may obtain a copy of the License at | |
6013 | + * | |
6014 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
6015 | + * | |
6016 | + * Unless required by applicable law or agreed to in writing, software | |
6017 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
6018 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
6019 | + * See the License for the specific language governing permissions and | |
6020 | + * limitations under the License. | |
6021 | + * | |
6022 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
6023 | + */ | |
6024 | + | |
6025 | +#ifndef MEDIA_CODEC_LIST_PRIV_H_ | |
6026 | +#define MEDIA_CODEC_LIST_PRIV_H_ | |
6027 | + | |
6028 | +#include <stddef.h> | |
6029 | +#include <stdbool.h> | |
6030 | +#include <unistd.h> | |
6031 | + | |
6032 | +#ifdef __cplusplus | |
6033 | +extern "C" { | |
6034 | +#endif | |
6035 | + | |
6036 | + ssize_t media_codec_list_find_codec_by_type(const char *type, bool encoder, size_t startIndex); | |
6037 | + ssize_t media_codec_list_find_codec_by_name(const char *name); | |
6038 | + size_t media_codec_list_count_codecs(); | |
6039 | + void media_codec_list_get_codec_info_at_id(size_t index); | |
6040 | + const char *media_codec_list_get_codec_name(size_t index); | |
6041 | + bool media_codec_list_is_encoder(size_t index); | |
6042 | + size_t media_codec_list_get_num_supported_types(size_t index); | |
6043 | + size_t media_codec_list_get_nth_supported_type_len(size_t index, size_t n); | |
6044 | + int media_codec_list_get_nth_supported_type(size_t index, char *type, size_t n); | |
6045 | + | |
6046 | + struct _profile_level | |
6047 | + { | |
6048 | + uint32_t profile; | |
6049 | + uint32_t level; | |
6050 | + }; | |
6051 | + typedef struct _profile_level profile_level; | |
6052 | + | |
6053 | + size_t media_codec_list_get_num_profile_levels(size_t index, const char*); | |
6054 | + size_t media_codec_list_get_num_color_formats(size_t index, const char*); | |
6055 | + int media_codec_list_get_nth_codec_profile_level(size_t index, const char *type, profile_level *pro_level, size_t n); | |
6056 | + int media_codec_list_get_codec_color_formats(size_t index, const char *type, uint32_t *color_formats); | |
6057 | + | |
6058 | +#ifdef __cplusplus | |
6059 | +} | |
6060 | +#endif | |
6061 | + | |
6062 | +#endif // MEDIA_CODEC_LIST_PRIV_H_ | |
6063 | --- /dev/null | |
6064 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_compatibility_layer.h | |
6065 | @@ -0,0 +1,75 @@ | |
6066 | +/* | |
6067 | + * Copyright (C) 2013 Canonical Ltd | |
6068 | + * | |
6069 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6070 | + * you may not use this file except in compliance with the License. | |
6071 | + * You may obtain a copy of the License at | |
6072 | + * | |
6073 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
6074 | + * | |
6075 | + * Unless required by applicable law or agreed to in writing, software | |
6076 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
6077 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
6078 | + * See the License for the specific language governing permissions and | |
6079 | + * limitations under the License. | |
6080 | + * | |
6081 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
6082 | + */ | |
6083 | + | |
6084 | +#ifndef MEDIA_COMPATIBILITY_LAYER_H_ | |
6085 | +#define MEDIA_COMPATIBILITY_LAYER_H_ | |
6086 | + | |
6087 | +#include <stdint.h> | |
6088 | +#include <unistd.h> | |
6089 | +#include <stdbool.h> | |
6090 | + | |
6091 | +#include <GLES2/gl2.h> | |
6092 | + | |
6093 | +#ifdef __cplusplus | |
6094 | +extern "C" { | |
6095 | +#endif | |
6096 | + | |
6097 | + // Common compat calls | |
6098 | + int media_compat_check_availability(); | |
6099 | + | |
6100 | + // Callback types | |
6101 | + typedef void (*on_msg_set_video_size)(int height, int width, void *context); | |
6102 | + typedef void (*on_video_texture_needs_update)(void *context); | |
6103 | + typedef void (*on_msg_error)(void *context); | |
6104 | + typedef void (*on_playback_complete)(void *context); | |
6105 | + typedef void (*on_media_prepared)(void *context); | |
6106 | + | |
6107 | + struct MediaPlayerWrapper; | |
6108 | + | |
6109 | + // ----- Start of C API ----- // | |
6110 | + | |
6111 | + // Callback setters | |
6112 | + void android_media_set_video_size_cb(struct MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context); | |
6113 | + void android_media_set_video_texture_needs_update_cb(struct MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context); | |
6114 | + void android_media_set_error_cb(struct MediaPlayerWrapper *mp, on_msg_error cb, void *context); | |
6115 | + void android_media_set_playback_complete_cb(struct MediaPlayerWrapper *mp, on_playback_complete cb, void *context); | |
6116 | + void android_media_set_media_prepared_cb(struct MediaPlayerWrapper *mp, on_media_prepared cb, void *context); | |
6117 | + | |
6118 | + // Main player control API | |
6119 | + struct MediaPlayerWrapper *android_media_new_player(); | |
6120 | + int android_media_set_data_source(struct MediaPlayerWrapper *mp, const char* url); | |
6121 | + int android_media_set_preview_texture(struct MediaPlayerWrapper *mp, int texture_id); | |
6122 | + void android_media_update_surface_texture(struct MediaPlayerWrapper *mp); | |
6123 | + void android_media_surface_texture_get_transformation_matrix(struct MediaPlayerWrapper *mp, GLfloat*matrix); | |
6124 | + int android_media_play(struct MediaPlayerWrapper *mp); | |
6125 | + int android_media_pause(struct MediaPlayerWrapper *mp); | |
6126 | + int android_media_stop(struct MediaPlayerWrapper *mp); | |
6127 | + bool android_media_is_playing(struct MediaPlayerWrapper *mp); | |
6128 | + | |
6129 | + int android_media_seek_to(struct MediaPlayerWrapper *mp, int msec); | |
6130 | + int android_media_get_current_position(struct MediaPlayerWrapper *mp, int *msec); | |
6131 | + int android_media_get_duration(struct MediaPlayerWrapper *mp, int *msec); | |
6132 | + | |
6133 | + int android_media_get_volume(struct MediaPlayerWrapper *mp, int *volume); | |
6134 | + int android_media_set_volume(struct MediaPlayerWrapper *mp, int volume); | |
6135 | + | |
6136 | +#ifdef __cplusplus | |
6137 | +} | |
6138 | +#endif | |
6139 | + | |
6140 | +#endif // MEDIA_COMPATIBILITY_LAYER_H_ | |
6141 | --- /dev/null | |
6142 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_format_layer.h | |
6143 | @@ -0,0 +1,58 @@ | |
6144 | +/* | |
6145 | + * Copyright (C) 2013 Canonical Ltd | |
6146 | + * | |
6147 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6148 | + * you may not use this file except in compliance with the License. | |
6149 | + * You may obtain a copy of the License at | |
6150 | + * | |
6151 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
6152 | + * | |
6153 | + * Unless required by applicable law or agreed to in writing, software | |
6154 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
6155 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
6156 | + * See the License for the specific language governing permissions and | |
6157 | + * limitations under the License. | |
6158 | + * | |
6159 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
6160 | + */ | |
6161 | + | |
6162 | +#ifndef MEDIA_FORMAT_LAYER_H_ | |
6163 | +#define MEDIA_FORMAT_LAYER_H_ | |
6164 | + | |
6165 | +#include <stddef.h> | |
6166 | +#include <unistd.h> | |
6167 | + | |
6168 | +#ifdef __cplusplus | |
6169 | +extern "C" { | |
6170 | +#endif | |
6171 | + | |
6172 | + typedef void* MediaFormat; | |
6173 | + | |
6174 | + MediaFormat media_format_create_video_format(const char *mime, int32_t width, int32_t height, int64_t duration_us, int32_t max_input_size); | |
6175 | + | |
6176 | + void media_format_destroy(MediaFormat format); | |
6177 | + void media_format_ref(MediaFormat format); | |
6178 | + void media_format_unref(MediaFormat format); | |
6179 | + | |
6180 | + void media_format_set_byte_buffer(MediaFormat format, const char *key, uint8_t *data, size_t size); | |
6181 | + | |
6182 | + const char* media_format_get_mime(MediaFormat format); | |
6183 | + int64_t media_format_get_duration_us(MediaFormat format); | |
6184 | + int32_t media_format_get_width(MediaFormat format); | |
6185 | + int32_t media_format_get_height(MediaFormat format); | |
6186 | + int32_t media_format_get_max_input_size(MediaFormat format); | |
6187 | + int32_t media_format_get_stride(MediaFormat format); | |
6188 | + int32_t media_format_get_slice_height(MediaFormat format); | |
6189 | + int32_t media_format_get_color_format(MediaFormat format); | |
6190 | + int32_t media_format_get_crop_left(MediaFormat format); | |
6191 | + int32_t media_format_get_crop_right(MediaFormat format); | |
6192 | + int32_t media_format_get_crop_top(MediaFormat format); | |
6193 | + int32_t media_format_get_crop_bottom(MediaFormat format); | |
6194 | + | |
6195 | + // TODO: Add getter for CSD buffer | |
6196 | + | |
6197 | +#ifdef __cplusplus | |
6198 | +} | |
6199 | +#endif | |
6200 | + | |
6201 | +#endif // MEDIA_FORMAT_LAYER_H_ | |
6202 | --- /dev/null | |
6203 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/recorder_compatibility_layer.h | |
6204 | @@ -0,0 +1,126 @@ | |
6205 | +/* | |
6206 | + * Copyright (C) 2013 Canonical Ltd | |
6207 | + * | |
6208 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6209 | + * you may not use this file except in compliance with the License. | |
6210 | + * You may obtain a copy of the License at | |
6211 | + * | |
6212 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
6213 | + * | |
6214 | + * Unless required by applicable law or agreed to in writing, software | |
6215 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
6216 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
6217 | + * See the License for the specific language governing permissions and | |
6218 | + * limitations under the License. | |
6219 | + */ | |
6220 | + | |
6221 | +#ifndef RECORDER_COMPATIBILITY_LAYER_H_ | |
6222 | +#define RECORDER_COMPATIBILITY_LAYER_H_ | |
6223 | + | |
6224 | +#include <stdint.h> | |
6225 | +#include <unistd.h> | |
6226 | +#include <stdint.h> | |
6227 | +#include <stdbool.h> | |
6228 | + | |
6229 | +#ifdef __cplusplus | |
6230 | +extern "C" { | |
6231 | +#endif | |
6232 | + | |
6233 | + struct MediaRecorderWrapper; | |
6234 | + struct CameraControl; | |
6235 | + | |
6236 | + // values are from andoid /frameworks/av/include/media/mediarecorder.h | |
6237 | + typedef enum | |
6238 | + { | |
6239 | + ANDROID_VIDEO_SOURCE_DEFAULT = 0, | |
6240 | + ANDROID_VIDEO_SOURCE_CAMERA = 1, | |
6241 | + ANDROID_VIDEO_SOURCE_GRALLOC_BUFFER = 2 | |
6242 | + } VideoSource; | |
6243 | + | |
6244 | + // values are from andoid /system/core/include/system/audio.h | |
6245 | + typedef enum | |
6246 | + { | |
6247 | + ANDROID_AUDIO_SOURCE_DEFAULT = 0, | |
6248 | + ANDROID_AUDIO_SOURCE_MIC = 1, | |
6249 | + ANDROID_AUDIO_SOURCE_VOICE_UPLINK = 2, | |
6250 | + ANDROID_AUDIO_SOURCE_VOICE_DOWNLINK = 3, | |
6251 | + ANDROID_AUDIO_SOURCE_VOICE_CALL = 4, | |
6252 | + ANDROID_AUDIO_SOURCE_CAMCORDER = 5, | |
6253 | + ANDROID_AUDIO_SOURCE_VOICE_RECOGNITION = 6, | |
6254 | + ANDROID_AUDIO_SOURCE_VOICE_COMMUNICATION = 7, | |
6255 | + ANDROID_AUDIO_SOURCE_REMOTE_SUBMIX = 8, | |
6256 | + ANDROID_AUDIO_SOURCE_CNT, | |
6257 | + ANDROID_AUDIO_SOURCE_MAX = ANDROID_AUDIO_SOURCE_CNT - 1 | |
6258 | + } AudioSource; | |
6259 | + | |
6260 | + // values are from andoid /frameworks/av/include/media/mediarecorder.h | |
6261 | + typedef enum | |
6262 | + { | |
6263 | + ANDROID_OUTPUT_FORMAT_DEFAULT = 0, | |
6264 | + ANDROID_OUTPUT_FORMAT_THREE_GPP = 1, | |
6265 | + ANDROID_OUTPUT_FORMAT_MPEG_4 = 2, | |
6266 | + ANDROID_OUTPUT_FORMAT_AUDIO_ONLY_START = 3, | |
6267 | + /* These are audio only file formats */ | |
6268 | + ANDROID_OUTPUT_FORMAT_RAW_AMR = 3, //to be backward compatible | |
6269 | + ANDROID_OUTPUT_FORMAT_AMR_NB = 3, | |
6270 | + ANDROID_OUTPUT_FORMAT_AMR_WB = 4, | |
6271 | + ANDROID_OUTPUT_FORMAT_AAC_ADIF = 5, | |
6272 | + ANDROID_OUTPUT_FORMAT_AAC_ADTS = 6, | |
6273 | + /* Stream over a socket, limited to a single stream */ | |
6274 | + ANDROID_OUTPUT_FORMAT_RTP_AVP = 7, | |
6275 | + /* H.264/AAC data encapsulated in MPEG2/TS */ | |
6276 | + ANDROID_OUTPUT_FORMAT_MPEG2TS = 8 | |
6277 | + } OutputFormat; | |
6278 | + | |
6279 | + // values are from andoid /frameworks/av/include/media/mediarecorder.h | |
6280 | + typedef enum | |
6281 | + { | |
6282 | + ANDROID_VIDEO_ENCODER_DEFAULT = 0, | |
6283 | + ANDROID_VIDEO_ENCODER_H263 = 1, | |
6284 | + ANDROID_VIDEO_ENCODER_H264 = 2, | |
6285 | + ANDROID_VIDEO_ENCODER_MPEG_4_SP = 3 | |
6286 | + } VideoEncoder; | |
6287 | + | |
6288 | + // values are from andoid /frameworks/av/include/media/mediarecorder.h | |
6289 | + typedef enum | |
6290 | + { | |
6291 | + ANDROID_AUDIO_ENCODER_DEFAULT = 0, | |
6292 | + ANDROID_AUDIO_ENCODER_AMR_NB = 1, | |
6293 | + ANDROID_AUDIO_ENCODER_AMR_WB = 2, | |
6294 | + ANDROID_AUDIO_ENCODER_AAC = 3, | |
6295 | + ANDROID_AUDIO_ENCODER_HE_AAC = 4, | |
6296 | + ANDROID_AUDIO_ENCODER_AAC_ELD = 5 | |
6297 | + } AudioEncoder; | |
6298 | + | |
6299 | + // Callback types | |
6300 | + typedef void (*on_recorder_msg_error)(void *context); | |
6301 | + | |
6302 | + // Callback setters | |
6303 | + void android_recorder_set_error_cb(struct MediaRecorderWrapper *mr, on_recorder_msg_error cb, | |
6304 | + void *context); | |
6305 | + | |
6306 | + // Main recorder control API | |
6307 | + struct MediaRecorderWrapper *android_media_new_recorder(); | |
6308 | + int android_recorder_initCheck(struct MediaRecorderWrapper *mr); | |
6309 | + int android_recorder_setCamera(struct MediaRecorderWrapper *mr, struct CameraControl* control); | |
6310 | + int android_recorder_setVideoSource(struct MediaRecorderWrapper *mr, VideoSource vs); | |
6311 | + int android_recorder_setAudioSource(struct MediaRecorderWrapper *mr, AudioSource as); | |
6312 | + int android_recorder_setOutputFormat(struct MediaRecorderWrapper *mr, OutputFormat of); | |
6313 | + int android_recorder_setVideoEncoder(struct MediaRecorderWrapper *mr, VideoEncoder ve); | |
6314 | + int android_recorder_setAudioEncoder(struct MediaRecorderWrapper *mr, AudioEncoder ae); | |
6315 | + int android_recorder_setOutputFile(struct MediaRecorderWrapper *mr, int fd); | |
6316 | + int android_recorder_setVideoSize(struct MediaRecorderWrapper *mr, int width, int height); | |
6317 | + int android_recorder_setVideoFrameRate(struct MediaRecorderWrapper *mr, int frames_per_second); | |
6318 | + int android_recorder_setParameters(struct MediaRecorderWrapper *mr, const char* parameters); | |
6319 | + int android_recorder_start(struct MediaRecorderWrapper *mr); | |
6320 | + int android_recorder_stop(struct MediaRecorderWrapper *mr); | |
6321 | + int android_recorder_prepare(struct MediaRecorderWrapper *mr); | |
6322 | + int android_recorder_reset(struct MediaRecorderWrapper *mr); | |
6323 | + int android_recorder_close(struct MediaRecorderWrapper *mr); | |
6324 | + int android_recorder_release(struct MediaRecorderWrapper *mr); | |
6325 | + | |
6326 | +#ifdef __cplusplus | |
6327 | +} | |
6328 | +#endif | |
6329 | + | |
6330 | +#endif | |
6331 | --- /dev/null | |
6332 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/surface_texture_client_hybris.h | |
6333 | @@ -0,0 +1,63 @@ | |
6334 | +/* | |
6335 | + * Copyright (C) 2013 Canonical Ltd | |
6336 | + * | |
6337 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6338 | + * you may not use this file except in compliance with the License. | |
6339 | + * You may obtain a copy of the License at | |
6340 | + * | |
6341 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
6342 | + * | |
6343 | + * Unless required by applicable law or agreed to in writing, software | |
6344 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
6345 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
6346 | + * See the License for the specific language governing permissions and | |
6347 | + * limitations under the License. | |
6348 | + * | |
6349 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
6350 | + */ | |
6351 | + | |
6352 | +#ifndef SURFACE_TEXTURE_CLIENT_HYBRIS_H_ | |
6353 | +#define SURFACE_TEXTURE_CLIENT_HYBRIS_H_ | |
6354 | + | |
6355 | +#include <stdint.h> | |
6356 | +#include <unistd.h> | |
6357 | + | |
6358 | +#include <EGL/egl.h> | |
6359 | + | |
6360 | +#ifdef __ARM_PCS_VFP | |
6361 | +#define FP_ATTRIB __attribute__((pcs("aapcs"))) | |
6362 | +#else | |
6363 | +#define FP_ATTRIB | |
6364 | +#endif | |
6365 | + | |
6366 | +#ifdef __cplusplus | |
6367 | +extern "C" { | |
6368 | +#endif | |
6369 | + | |
6370 | + // Taken from native_window.h | |
6371 | + enum { | |
6372 | + WINDOW_FORMAT_RGBA_8888 = 1, | |
6373 | + WINDOW_FORMAT_RGBX_8888 = 2, | |
6374 | + WINDOW_FORMAT_RGB_565 = 4, | |
6375 | + }; | |
6376 | + | |
6377 | + typedef void* SurfaceTextureClientHybris; | |
6378 | + | |
6379 | + //SurfaceTextureClientHybris surface_texture_client_get_instance(); | |
6380 | + SurfaceTextureClientHybris surface_texture_client_create(EGLNativeWindowType native_window); | |
6381 | + SurfaceTextureClientHybris surface_texture_client_create_by_id(unsigned int texture_id); | |
6382 | + uint8_t surface_texture_client_is_ready_for_rendering(SurfaceTextureClientHybris stc); | |
6383 | + uint8_t surface_texture_client_hardware_rendering(SurfaceTextureClientHybris stc); | |
6384 | + void surface_texture_client_set_hardware_rendering(SurfaceTextureClientHybris stc, uint8_t hardware_rendering); | |
6385 | + void surface_texture_client_get_transformation_matrix(SurfaceTextureClientHybris stc, float *matrix) FP_ATTRIB; | |
6386 | + void surface_texture_client_update_texture(SurfaceTextureClientHybris stc); | |
6387 | + void surface_texture_client_destroy(SurfaceTextureClientHybris stc); | |
6388 | + void surface_texture_client_ref(SurfaceTextureClientHybris stc); | |
6389 | + void surface_texture_client_unref(SurfaceTextureClientHybris stc); | |
6390 | + void surface_texture_client_set_surface_texture(SurfaceTextureClientHybris stc, EGLNativeWindowType native_window); | |
6391 | + | |
6392 | +#ifdef __cplusplus | |
6393 | +} | |
6394 | +#endif | |
6395 | + | |
6396 | +#endif // SURFACE_TEXTURE_CLIENT_HYBRIS_H_ | |
6397 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/ui/ui_compatibility_layer.h | |
6398 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/ui/ui_compatibility_layer.h | |
6399 | @@ -50,8 +50,10 @@ extern "C" { | |
6400 | ||
6401 | void* graphic_buffer_get_native_buffer(struct graphic_buffer *buffer); | |
6402 | ||
6403 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
6404 | void graphic_buffer_set_index(struct graphic_buffer *buffer, int index); | |
6405 | int graphic_buffer_get_index(struct graphic_buffer *buffer); | |
6406 | +#endif | |
6407 | ||
6408 | int graphic_buffer_init_check(struct graphic_buffer *buffer); | |
6409 | ||
6410 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/input/is.c | |
6411 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/input/is.c | |
6412 | @@ -28,6 +28,14 @@ | |
6413 | ||
6414 | HYBRIS_LIBRARY_INITIALIZE(is, COMPAT_LIBRARY_PATH); | |
6415 | ||
6416 | +int android_input_check_availability() | |
6417 | +{ | |
6418 | + /* Both are defined via HYBRIS_LIBRARY_INITIALIZE */ | |
6419 | + if (!is_handle) | |
6420 | + hybris_is_initialize(); | |
6421 | + return is_handle ? 1 : 0; | |
6422 | +} | |
6423 | + | |
6424 | HYBRIS_IMPLEMENT_VOID_FUNCTION2(is, android_input_stack_initialize, | |
6425 | struct AndroidEventListener*, struct InputStackConfiguration*); | |
6426 | HYBRIS_IMPLEMENT_VOID_FUNCTION0(is, android_input_stack_start); | |
6427 | --- /dev/null | |
6428 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/media/Makefile.am | |
6429 | @@ -0,0 +1,17 @@ | |
6430 | +lib_LTLIBRARIES = \ | |
6431 | + libmedia.la | |
6432 | + | |
6433 | +libmedia_la_SOURCES = media.c | |
6434 | +libmedia_la_CFLAGS = -I$(top_srcdir)/include | |
6435 | +if WANT_TRACE | |
6436 | +libmedia_la_CFLAGS += -DDEBUG | |
6437 | +endif | |
6438 | +if WANT_DEBUG | |
6439 | +libmedia_la_CFLAGS += -ggdb -O0 | |
6440 | +endif | |
6441 | +libmedia_la_LDFLAGS = \ | |
6442 | + $(top_builddir)/common/libhybris-common.la \ | |
6443 | + -version-info "1":"0":"0" | |
6444 | + | |
6445 | +pkgconfigdir = $(libdir)/pkgconfig | |
6446 | +pkgconfig_DATA = libmedia.pc | |
6447 | --- /dev/null | |
6448 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/media/libmedia.pc.in | |
6449 | @@ -0,0 +1,10 @@ | |
6450 | +prefix=@prefix@ | |
6451 | +exec_prefix=${prefix} | |
6452 | +libdir=@libdir@ | |
6453 | +includedir=@includedir@ | |
6454 | + | |
6455 | +Name: hybris-media | |
6456 | +Description: libhybris media library | |
6457 | +Version: @VERSION@ | |
6458 | +Libs: -L${libdir} -lhybris-common -lmedia | |
6459 | +Cflags: -I${includedir} | |
6460 | --- /dev/null | |
6461 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/media/media.c | |
6462 | @@ -0,0 +1,272 @@ | |
6463 | +/* | |
6464 | + * Copyright (C) 2013 Canonical Ltd | |
6465 | + * | |
6466 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6467 | + * you may not use this file except in compliance with the License. | |
6468 | + * You may obtain a copy of the License at | |
6469 | + * | |
6470 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
6471 | + * | |
6472 | + * Unless required by applicable law or agreed to in writing, software | |
6473 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
6474 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
6475 | + * See the License for the specific language governing permissions and | |
6476 | + * limitations under the License. | |
6477 | + * | |
6478 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
6479 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
6480 | + */ | |
6481 | + | |
6482 | +#include <assert.h> | |
6483 | +#include <dlfcn.h> | |
6484 | +#include <stddef.h> | |
6485 | +#include <stdbool.h> | |
6486 | + | |
6487 | +#include <hybris/internal/binding.h> | |
6488 | +#include <hybris/media/media_compatibility_layer.h> | |
6489 | +#include <hybris/media/recorder_compatibility_layer.h> | |
6490 | +#include <hybris/media/media_codec_layer.h> | |
6491 | +#include <hybris/media/media_codec_list.h> | |
6492 | +#include <hybris/media/media_format_layer.h> | |
6493 | +#include <hybris/media/surface_texture_client_hybris.h> | |
6494 | + | |
6495 | +#define COMPAT_LIBRARY_PATH "/system/lib/libmedia_compat_layer.so" | |
6496 | + | |
6497 | +#ifdef __ARM_PCS_VFP | |
6498 | +#define FP_ATTRIB __attribute__((pcs("aapcs"))) | |
6499 | +#else | |
6500 | +#define FP_ATTRIB | |
6501 | +#endif | |
6502 | + | |
6503 | +HYBRIS_LIBRARY_INITIALIZE(media, COMPAT_LIBRARY_PATH); | |
6504 | + | |
6505 | +int media_compat_check_availability() | |
6506 | +{ | |
6507 | + /* Both are defined via HYBRIS_LIBRARY_INITIALIZE */ | |
6508 | + hybris_media_initialize(); | |
6509 | + return media_handle ? 1 : 0; | |
6510 | +} | |
6511 | + | |
6512 | +HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaPlayerWrapper*, | |
6513 | + android_media_new_player); | |
6514 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, android_media_update_surface_texture, | |
6515 | + struct MediaPlayerWrapper*); | |
6516 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_play, | |
6517 | + struct MediaPlayerWrapper*); | |
6518 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_pause, | |
6519 | + struct MediaPlayerWrapper*); | |
6520 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_stop, | |
6521 | + struct MediaPlayerWrapper*); | |
6522 | +HYBRIS_IMPLEMENT_FUNCTION1(media, bool, android_media_is_playing, | |
6523 | + struct MediaPlayerWrapper*); | |
6524 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_seek_to, | |
6525 | + struct MediaPlayerWrapper*, int); | |
6526 | + | |
6527 | +// Setters | |
6528 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_data_source, | |
6529 | + struct MediaPlayerWrapper*, const char*); | |
6530 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_preview_texture, | |
6531 | + struct MediaPlayerWrapper*, int); | |
6532 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_volume, | |
6533 | + struct MediaPlayerWrapper*, int); | |
6534 | + | |
6535 | +// Getters | |
6536 | +HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, android_media_surface_texture_get_transformation_matrix, | |
6537 | + struct MediaPlayerWrapper*, float*); | |
6538 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_current_position, | |
6539 | + struct MediaPlayerWrapper*, int*); | |
6540 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_duration, | |
6541 | + struct MediaPlayerWrapper*, int*); | |
6542 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_volume, | |
6543 | + struct MediaPlayerWrapper*, int*); | |
6544 | + | |
6545 | +// Callbacks | |
6546 | +HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_video_size_cb, | |
6547 | + struct MediaPlayerWrapper*, on_msg_set_video_size, void*); | |
6548 | +HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_video_texture_needs_update_cb, | |
6549 | + struct MediaPlayerWrapper*, on_video_texture_needs_update, void*); | |
6550 | +HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_error_cb, | |
6551 | + struct MediaPlayerWrapper*, on_msg_error, void*); | |
6552 | +HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_playback_complete_cb, | |
6553 | + struct MediaPlayerWrapper*, on_playback_complete, void*); | |
6554 | +HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_media_prepared_cb, | |
6555 | + struct MediaPlayerWrapper*, on_media_prepared, void*); | |
6556 | + | |
6557 | +// Media Codecs | |
6558 | +HYBRIS_IMPLEMENT_FUNCTION1(media, MediaCodecDelegate, | |
6559 | + media_codec_create_by_codec_name, const char*); | |
6560 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_destroy, | |
6561 | + MediaCodecDelegate); | |
6562 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_ref, | |
6563 | + MediaCodecDelegate); | |
6564 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_unref, | |
6565 | + MediaCodecDelegate); | |
6566 | + | |
6567 | +#ifdef SIMPLE_PLAYER | |
6568 | +HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_configure, | |
6569 | + MediaCodecDelegate, MediaFormat, void*, uint32_t); | |
6570 | +#else | |
6571 | +HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_configure, | |
6572 | + MediaCodecDelegate, MediaFormat, SurfaceTextureClientHybris, uint32_t); | |
6573 | +#endif | |
6574 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_set_surface_texture_client, | |
6575 | + MediaCodecDelegate, SurfaceTextureClientHybris); | |
6576 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_queue_csd, | |
6577 | + MediaCodecDelegate, MediaFormat); | |
6578 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_start, | |
6579 | + MediaCodecDelegate); | |
6580 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_stop, | |
6581 | + MediaCodecDelegate); | |
6582 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_release, | |
6583 | + MediaCodecDelegate); | |
6584 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_flush, | |
6585 | + MediaCodecDelegate); | |
6586 | +HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_get_input_buffers_size, | |
6587 | + MediaCodecDelegate); | |
6588 | +HYBRIS_IMPLEMENT_FUNCTION2(media, uint8_t*, media_codec_get_nth_input_buffer, | |
6589 | + MediaCodecDelegate, size_t); | |
6590 | +HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_get_nth_input_buffer_capacity, | |
6591 | + MediaCodecDelegate, size_t); | |
6592 | +HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_get_output_buffers_size, | |
6593 | + MediaCodecDelegate); | |
6594 | +HYBRIS_IMPLEMENT_FUNCTION2(media, uint8_t*, media_codec_get_nth_output_buffer, | |
6595 | + MediaCodecDelegate, size_t); | |
6596 | +HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_get_nth_output_buffer_capacity, | |
6597 | + MediaCodecDelegate, size_t); | |
6598 | +HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_dequeue_output_buffer, | |
6599 | + MediaCodecDelegate, MediaCodecBufferInfo*, int64_t); | |
6600 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_queue_input_buffer, | |
6601 | + MediaCodecDelegate, const MediaCodecBufferInfo*); | |
6602 | +HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_dequeue_input_buffer, | |
6603 | + MediaCodecDelegate, size_t*, int64_t); | |
6604 | +HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_release_output_buffer, | |
6605 | + MediaCodecDelegate, size_t, uint8_t); | |
6606 | +HYBRIS_IMPLEMENT_FUNCTION1(media, MediaFormat, media_codec_get_output_format, | |
6607 | + MediaCodecDelegate); | |
6608 | + | |
6609 | +HYBRIS_IMPLEMENT_FUNCTION3(media, ssize_t, media_codec_list_find_codec_by_type, | |
6610 | + const char*, bool, size_t); | |
6611 | +HYBRIS_IMPLEMENT_FUNCTION1(media, ssize_t, media_codec_list_find_codec_by_name, | |
6612 | + const char *); | |
6613 | +HYBRIS_IMPLEMENT_FUNCTION0(media, size_t, media_codec_list_count_codecs); | |
6614 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_list_get_codec_info_at_id, | |
6615 | + size_t); | |
6616 | +HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_codec_list_get_codec_name, | |
6617 | + size_t); | |
6618 | +HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_list_is_encoder, | |
6619 | + size_t); | |
6620 | +HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_list_get_num_supported_types, | |
6621 | + size_t); | |
6622 | +HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_nth_supported_type_len, | |
6623 | + size_t, size_t); | |
6624 | +HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_list_get_nth_supported_type, | |
6625 | + size_t, char *, size_t); | |
6626 | +HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_num_profile_levels, | |
6627 | + size_t, const char*); | |
6628 | +HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_num_color_formats, | |
6629 | + size_t, const char*); | |
6630 | +HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_list_get_nth_codec_profile_level, | |
6631 | + size_t, const char*, profile_level*, size_t); | |
6632 | +HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_list_get_codec_color_formats, | |
6633 | + size_t, const char*, uint32_t*); | |
6634 | + | |
6635 | +HYBRIS_IMPLEMENT_FUNCTION5(media, MediaFormat, media_format_create_video_format, | |
6636 | + const char*, int32_t, int32_t, int64_t, int32_t); | |
6637 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_destroy, | |
6638 | + MediaFormat); | |
6639 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_ref, | |
6640 | + MediaFormat); | |
6641 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_unref, | |
6642 | + MediaFormat); | |
6643 | +HYBRIS_IMPLEMENT_VOID_FUNCTION4(media, media_format_set_byte_buffer, | |
6644 | + MediaFormat, const char*, uint8_t*, size_t); | |
6645 | +HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_format_get_mime, | |
6646 | + MediaFormat); | |
6647 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int64_t, media_format_get_duration_us, | |
6648 | + MediaFormat); | |
6649 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_width, | |
6650 | + MediaFormat); | |
6651 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_height, | |
6652 | + MediaFormat); | |
6653 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_max_input_size, | |
6654 | + MediaFormat); | |
6655 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_stride, | |
6656 | + MediaFormat); | |
6657 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_slice_height, | |
6658 | + MediaFormat); | |
6659 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_color_format, | |
6660 | + MediaFormat); | |
6661 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_left, | |
6662 | + MediaFormat); | |
6663 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_right, | |
6664 | + MediaFormat); | |
6665 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_top, | |
6666 | + MediaFormat); | |
6667 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_bottom, | |
6668 | + MediaFormat); | |
6669 | + | |
6670 | +// SurfaceTextureClientHybris | |
6671 | +HYBRIS_IMPLEMENT_FUNCTION1(media, SurfaceTextureClientHybris, | |
6672 | + surface_texture_client_create, EGLNativeWindowType); | |
6673 | +HYBRIS_IMPLEMENT_FUNCTION1(media, SurfaceTextureClientHybris, | |
6674 | + surface_texture_client_create_by_id, unsigned int); | |
6675 | +HYBRIS_IMPLEMENT_FUNCTION1(media, uint8_t, | |
6676 | + surface_texture_client_is_ready_for_rendering, SurfaceTextureClientHybris); | |
6677 | +HYBRIS_IMPLEMENT_FUNCTION1(media, uint8_t, | |
6678 | + surface_texture_client_hardware_rendering, SurfaceTextureClientHybris); | |
6679 | +HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_set_hardware_rendering, | |
6680 | + SurfaceTextureClientHybris, uint8_t); | |
6681 | +HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_get_transformation_matrix, | |
6682 | + SurfaceTextureClientHybris, GLfloat*); | |
6683 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_update_texture, | |
6684 | + SurfaceTextureClientHybris); | |
6685 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_destroy, | |
6686 | + SurfaceTextureClientHybris); | |
6687 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_ref, | |
6688 | + SurfaceTextureClientHybris); | |
6689 | +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_unref, | |
6690 | + SurfaceTextureClientHybris); | |
6691 | +HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_set_surface_texture, | |
6692 | + SurfaceTextureClientHybris, EGLNativeWindowType); | |
6693 | + | |
6694 | +// Recorder | |
6695 | +HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaRecorderWrapper*, | |
6696 | + android_media_new_recorder); | |
6697 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_initCheck, | |
6698 | + struct MediaRecorderWrapper*); | |
6699 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setCamera, | |
6700 | + struct MediaRecorderWrapper*, struct CameraControl*); | |
6701 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoSource, | |
6702 | + struct MediaRecorderWrapper*, VideoSource); | |
6703 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setAudioSource, | |
6704 | + struct MediaRecorderWrapper*, AudioSource); | |
6705 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setOutputFormat, | |
6706 | + struct MediaRecorderWrapper*, OutputFormat); | |
6707 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoEncoder, | |
6708 | + struct MediaRecorderWrapper*, VideoEncoder); | |
6709 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setAudioEncoder, | |
6710 | + struct MediaRecorderWrapper*, AudioEncoder); | |
6711 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setOutputFile, | |
6712 | + struct MediaRecorderWrapper*, int); | |
6713 | +HYBRIS_IMPLEMENT_FUNCTION3(media, int, android_recorder_setVideoSize, | |
6714 | + struct MediaRecorderWrapper*, int, int); | |
6715 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoFrameRate, | |
6716 | + struct MediaRecorderWrapper*, int); | |
6717 | +HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setParameters, | |
6718 | + struct MediaRecorderWrapper*, const char*); | |
6719 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_start, | |
6720 | + struct MediaRecorderWrapper*); | |
6721 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_stop, | |
6722 | + struct MediaRecorderWrapper*); | |
6723 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_prepare, | |
6724 | + struct MediaRecorderWrapper*); | |
6725 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_reset, | |
6726 | + struct MediaRecorderWrapper*); | |
6727 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_close, | |
6728 | + struct MediaRecorderWrapper*); | |
6729 | +HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_release, | |
6730 | + struct MediaRecorderWrapper*); | |
6731 | + | |
6732 | +// Recorder Callbacks | |
6733 | +HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_recorder_set_error_cb, | |
6734 | + struct MediaRecorderWrapper *, on_recorder_msg_error, void*); | |
6735 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/Makefile.am | |
6736 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/Makefile.am | |
6737 | @@ -7,6 +7,8 @@ bin_PROGRAMS = \ | |
6738 | test_sensors \ | |
6739 | test_input \ | |
6740 | test_camera \ | |
6741 | + test_media \ | |
6742 | + test_recorder \ | |
6743 | test_gps | |
6744 | ||
6745 | if HAS_ANDROID_4_2_0 | |
6746 | @@ -140,6 +142,28 @@ test_camera_LDADD = \ | |
6747 | $(top_builddir)/camera/libcamera.la \ | |
6748 | $(top_builddir)/input/libis.la | |
6749 | ||
6750 | +test_media_SOURCES = test_media.c | |
6751 | +test_media_CFLAGS = \ | |
6752 | + -I$(top_srcdir)/include | |
6753 | +test_media_LDADD = \ | |
6754 | + $(top_builddir)/common/libhybris-common.la \ | |
6755 | + $(top_builddir)/egl/libEGL.la \ | |
6756 | + $(top_builddir)/glesv2/libGLESv2.la \ | |
6757 | + $(top_builddir)/media/libmedia.la \ | |
6758 | + $(top_builddir)/sf/libsf.la | |
6759 | + | |
6760 | +test_recorder_SOURCES = test_recorder.c | |
6761 | +test_recorder_CFLAGS = \ | |
6762 | + -I$(top_srcdir)/include | |
6763 | +test_recorder_LDADD = \ | |
6764 | + $(top_builddir)/common/libhybris-common.la \ | |
6765 | + $(top_builddir)/egl/libEGL.la \ | |
6766 | + $(top_builddir)/glesv2/libGLESv2.la \ | |
6767 | + $(top_builddir)/media/libmedia.la \ | |
6768 | + $(top_builddir)/camera/libcamera.la \ | |
6769 | + $(top_builddir)/input/libis.la \ | |
6770 | + $(top_builddir)/sf/libsf.la | |
6771 | + | |
6772 | test_gps_SOURCES = test_gps.c | |
6773 | test_gps_CFLAGS = -pthread \ | |
6774 | -I$(top_srcdir)/include \ | |
6775 | --- /dev/null | |
6776 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_media.c | |
6777 | @@ -0,0 +1,373 @@ | |
6778 | +/* | |
6779 | + * Copyright (C) 2013 Canonical Ltd | |
6780 | + * | |
6781 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
6782 | + * you may not use this file except in compliance with the License. | |
6783 | + * You may obtain a copy of the License at | |
6784 | + * | |
6785 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
6786 | + * | |
6787 | + * Unless required by applicable law or agreed to in writing, software | |
6788 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
6789 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
6790 | + * See the License for the specific language governing permissions and | |
6791 | + * limitations under the License. | |
6792 | + * | |
6793 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
6794 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
6795 | + */ | |
6796 | + | |
6797 | +#include <hybris/media/media_compatibility_layer.h> | |
6798 | +#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h> | |
6799 | + | |
6800 | +#include <EGL/egl.h> | |
6801 | +#include <GLES2/gl2.h> | |
6802 | +#include <GLES2/gl2ext.h> | |
6803 | + | |
6804 | +#include <assert.h> | |
6805 | +#include <stdlib.h> | |
6806 | +#include <stdio.h> | |
6807 | +#include <string.h> | |
6808 | +#include <stdbool.h> | |
6809 | +#include <limits.h> | |
6810 | +#include <fcntl.h> | |
6811 | +#include <unistd.h> | |
6812 | +#include <sys/stat.h> | |
6813 | +#include <sys/types.h> | |
6814 | + | |
6815 | +enum { | |
6816 | + OK = 0, | |
6817 | + NO_ERROR = 0, | |
6818 | +}; | |
6819 | + | |
6820 | +static float DestWidth = 0.0, DestHeight = 0.0; | |
6821 | +// Actual video dimmensions | |
6822 | +static int Width = 0, Height = 0; | |
6823 | + | |
6824 | +static GLuint gProgram; | |
6825 | +static GLuint gaPositionHandle, gaTexHandle, gsTextureHandle, gmTexMatrix; | |
6826 | + | |
6827 | +static GLfloat positionCoordinates[8]; | |
6828 | + | |
6829 | +struct MediaPlayerWrapper *player = NULL; | |
6830 | + | |
6831 | +void calculate_position_coordinates() | |
6832 | +{ | |
6833 | + // Assuming cropping output for now | |
6834 | + float x = 1, y = 1; | |
6835 | + | |
6836 | + // Black borders | |
6837 | + x = (float) (Width / DestWidth); | |
6838 | + y = (float) (Height / DestHeight); | |
6839 | + | |
6840 | + // Make the larger side be 1 | |
6841 | + if (x > y) { | |
6842 | + y /= x; | |
6843 | + x = 1; | |
6844 | + } else { | |
6845 | + x /= y; | |
6846 | + y = 1; | |
6847 | + } | |
6848 | + | |
6849 | + positionCoordinates[0] = -x; | |
6850 | + positionCoordinates[1] = y; | |
6851 | + positionCoordinates[2] = -x; | |
6852 | + positionCoordinates[3] = -y; | |
6853 | + positionCoordinates[4] = x; | |
6854 | + positionCoordinates[5] = -y; | |
6855 | + positionCoordinates[6] = x; | |
6856 | + positionCoordinates[7] = y; | |
6857 | +} | |
6858 | + | |
6859 | +struct ClientWithSurface | |
6860 | +{ | |
6861 | + struct SfClient* client; | |
6862 | + struct SfSurface* surface; | |
6863 | +}; | |
6864 | + | |
6865 | +struct ClientWithSurface client_with_surface(bool setup_surface_with_egl) | |
6866 | +{ | |
6867 | + struct ClientWithSurface cs; | |
6868 | + | |
6869 | + cs.client = sf_client_create(); | |
6870 | + | |
6871 | + if (!cs.client) { | |
6872 | + printf("Problem creating client ... aborting now."); | |
6873 | + return cs; | |
6874 | + } | |
6875 | + | |
6876 | + static const size_t primary_display = 0; | |
6877 | + | |
6878 | + DestWidth = sf_get_display_width(primary_display); | |
6879 | + DestHeight = sf_get_display_height(primary_display); | |
6880 | + printf("Primary display width: %f, height: %f\n", DestWidth, DestHeight); | |
6881 | + | |
6882 | + SfSurfaceCreationParameters params = { | |
6883 | + 0, | |
6884 | + 0, | |
6885 | + DestWidth, | |
6886 | + DestHeight, | |
6887 | + -1, //PIXEL_FORMAT_RGBA_8888, | |
6888 | + 15000, | |
6889 | + 0.5f, | |
6890 | + setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL | |
6891 | + "MediaCompatLayerTestSurface" | |
6892 | + }; | |
6893 | + | |
6894 | + cs.surface = sf_surface_create(cs.client, ¶ms); | |
6895 | + | |
6896 | + if (!cs.surface) { | |
6897 | + printf("Problem creating surface ... aborting now."); | |
6898 | + return cs; | |
6899 | + } | |
6900 | + | |
6901 | + sf_surface_make_current(cs.surface); | |
6902 | + | |
6903 | + return cs; | |
6904 | +} | |
6905 | + | |
6906 | +static const char *vertex_shader() | |
6907 | +{ | |
6908 | + return | |
6909 | + "attribute vec4 a_position; \n" | |
6910 | + "attribute vec2 a_texCoord; \n" | |
6911 | + "uniform mat4 m_texMatrix; \n" | |
6912 | + "varying vec2 v_texCoord; \n" | |
6913 | + "varying float topDown; \n" | |
6914 | + "void main() \n" | |
6915 | + "{ \n" | |
6916 | + " gl_Position = a_position; \n" | |
6917 | + " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n" | |
6918 | + "} \n"; | |
6919 | +} | |
6920 | + | |
6921 | +static const char *fragment_shader() | |
6922 | +{ | |
6923 | + return | |
6924 | + "#extension GL_OES_EGL_image_external : require \n" | |
6925 | + "precision mediump float; \n" | |
6926 | + "varying vec2 v_texCoord; \n" | |
6927 | + "uniform samplerExternalOES s_texture; \n" | |
6928 | + "void main() \n" | |
6929 | + "{ \n" | |
6930 | + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" | |
6931 | + "} \n"; | |
6932 | +} | |
6933 | + | |
6934 | +static GLuint loadShader(GLenum shaderType, const char* pSource) | |
6935 | +{ | |
6936 | + GLuint shader = glCreateShader(shaderType); | |
6937 | + | |
6938 | + if (shader) { | |
6939 | + glShaderSource(shader, 1, &pSource, NULL); | |
6940 | + glCompileShader(shader); | |
6941 | + GLint compiled = 0; | |
6942 | + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); | |
6943 | + | |
6944 | + if (!compiled) { | |
6945 | + GLint infoLen = 0; | |
6946 | + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); | |
6947 | + if (infoLen) { | |
6948 | + char* buf = (char*) malloc(infoLen); | |
6949 | + if (buf) { | |
6950 | + glGetShaderInfoLog(shader, infoLen, NULL, buf); | |
6951 | + fprintf(stderr, "Could not compile shader %d:\n%s\n", | |
6952 | + shaderType, buf); | |
6953 | + free(buf); | |
6954 | + } | |
6955 | + glDeleteShader(shader); | |
6956 | + shader = 0; | |
6957 | + } | |
6958 | + } | |
6959 | + } else { | |
6960 | + printf("Error, during shader creation: %i\n", glGetError()); | |
6961 | + } | |
6962 | + | |
6963 | + return shader; | |
6964 | +} | |
6965 | + | |
6966 | +static GLuint create_program(const char* pVertexSource, const char* pFragmentSource) | |
6967 | +{ | |
6968 | + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); | |
6969 | + if (!vertexShader) { | |
6970 | + printf("vertex shader not compiled\n"); | |
6971 | + return 0; | |
6972 | + } | |
6973 | + | |
6974 | + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); | |
6975 | + if (!pixelShader) { | |
6976 | + printf("frag shader not compiled\n"); | |
6977 | + return 0; | |
6978 | + } | |
6979 | + | |
6980 | + GLuint program = glCreateProgram(); | |
6981 | + if (program) { | |
6982 | + glAttachShader(program, vertexShader); | |
6983 | + glAttachShader(program, pixelShader); | |
6984 | + glLinkProgram(program); | |
6985 | + GLint linkStatus = GL_FALSE; | |
6986 | + | |
6987 | + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); | |
6988 | + if (linkStatus != GL_TRUE) { | |
6989 | + GLint bufLength = 0; | |
6990 | + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); | |
6991 | + if (bufLength) { | |
6992 | + char* buf = (char*) malloc(bufLength); | |
6993 | + if (buf) { | |
6994 | + glGetProgramInfoLog(program, bufLength, NULL, buf); | |
6995 | + fprintf(stderr, "Could not link program:\n%s\n", buf); | |
6996 | + free(buf); | |
6997 | + } | |
6998 | + } | |
6999 | + glDeleteProgram(program); | |
7000 | + program = 0; | |
7001 | + } | |
7002 | + } | |
7003 | + | |
7004 | + return program; | |
7005 | +} | |
7006 | + | |
7007 | +static int setup_video_texture(struct ClientWithSurface *cs, GLuint *preview_texture_id) | |
7008 | +{ | |
7009 | + assert(cs != NULL); | |
7010 | + assert(preview_texture_id != NULL); | |
7011 | + | |
7012 | + sf_surface_make_current(cs->surface); | |
7013 | + | |
7014 | + glGenTextures(1, preview_texture_id); | |
7015 | + glClearColor(0, 0, 0, 0); | |
7016 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
7017 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
7018 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
7019 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
7020 | + | |
7021 | + android_media_set_preview_texture(player, *preview_texture_id); | |
7022 | + | |
7023 | + return 0; | |
7024 | +} | |
7025 | + | |
7026 | +void set_video_size_cb(int height, int width, void *context) | |
7027 | +{ | |
7028 | + printf("Video height: %d, width: %d\n", height, width); | |
7029 | + printf("Video dest height: %f, width: %f\n", DestHeight, DestWidth); | |
7030 | + | |
7031 | + Height = height; | |
7032 | + Width = width; | |
7033 | +} | |
7034 | + | |
7035 | +void media_prepared_cb(void *context) | |
7036 | +{ | |
7037 | + printf("Media is prepared for playback.\n"); | |
7038 | +} | |
7039 | + | |
7040 | +int main(int argc, char **argv) | |
7041 | +{ | |
7042 | + if (argc < 2) { | |
7043 | + printf("Usage: test_media <video_to_play>\n"); | |
7044 | + return EXIT_FAILURE; | |
7045 | + } | |
7046 | + | |
7047 | + player = android_media_new_player(); | |
7048 | + if (player == NULL) { | |
7049 | + printf("Problem creating new media player.\n"); | |
7050 | + return EXIT_FAILURE; | |
7051 | + } | |
7052 | + | |
7053 | + // Set player event cb for when the video size is known: | |
7054 | + android_media_set_video_size_cb(player, set_video_size_cb, NULL); | |
7055 | + android_media_set_media_prepared_cb(player, media_prepared_cb, NULL); | |
7056 | + | |
7057 | + printf("Setting data source to: %s.\n", argv[1]); | |
7058 | + | |
7059 | + if (android_media_set_data_source(player, argv[1]) != OK) { | |
7060 | + printf("Failed to set data source: %s\n", argv[1]); | |
7061 | + return EXIT_FAILURE; | |
7062 | + } | |
7063 | + | |
7064 | + printf("Creating EGL surface.\n"); | |
7065 | + struct ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */); | |
7066 | + if (!cs.surface) { | |
7067 | + printf("Problem acquiring surface for preview"); | |
7068 | + return EXIT_FAILURE; | |
7069 | + } | |
7070 | + | |
7071 | + printf("Creating GL texture.\n"); | |
7072 | + | |
7073 | + GLuint preview_texture_id; | |
7074 | + EGLDisplay disp = sf_client_get_egl_display(cs.client); | |
7075 | + EGLSurface surface = sf_surface_get_egl_surface(cs.surface); | |
7076 | + | |
7077 | + sf_surface_make_current(cs.surface); | |
7078 | + | |
7079 | + if (setup_video_texture(&cs, &preview_texture_id) != OK) { | |
7080 | + printf("Problem setting up GL texture for video surface.\n"); | |
7081 | + return EXIT_FAILURE; | |
7082 | + } | |
7083 | + | |
7084 | + printf("Starting video playback.\n"); | |
7085 | + android_media_play(player); | |
7086 | + | |
7087 | + while (android_media_is_playing(player)) { | |
7088 | + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; | |
7089 | + | |
7090 | + const GLfloat textureCoordinates[] = { | |
7091 | + 1.0f, 1.0f, | |
7092 | + 0.0f, 1.0f, | |
7093 | + 0.0f, 0.0f, | |
7094 | + 1.0f, 0.0f | |
7095 | + }; | |
7096 | + | |
7097 | + android_media_update_surface_texture(player); | |
7098 | + | |
7099 | + calculate_position_coordinates(); | |
7100 | + | |
7101 | + gProgram = create_program(vertex_shader(), fragment_shader()); | |
7102 | + gaPositionHandle = glGetAttribLocation(gProgram, "a_position"); | |
7103 | + gaTexHandle = glGetAttribLocation(gProgram, "a_texCoord"); | |
7104 | + gsTextureHandle = glGetUniformLocation(gProgram, "s_texture"); | |
7105 | + gmTexMatrix = glGetUniformLocation(gProgram, "m_texMatrix"); | |
7106 | + | |
7107 | + glClear(GL_COLOR_BUFFER_BIT); | |
7108 | + | |
7109 | + // Use the program object | |
7110 | + glUseProgram(gProgram); | |
7111 | + // Enable attributes | |
7112 | + glEnableVertexAttribArray(gaPositionHandle); | |
7113 | + glEnableVertexAttribArray(gaTexHandle); | |
7114 | + // Load the vertex position | |
7115 | + glVertexAttribPointer(gaPositionHandle, | |
7116 | + 2, | |
7117 | + GL_FLOAT, | |
7118 | + GL_FALSE, | |
7119 | + 0, | |
7120 | + positionCoordinates); | |
7121 | + // Load the texture coordinate | |
7122 | + glVertexAttribPointer(gaTexHandle, | |
7123 | + 2, | |
7124 | + GL_FLOAT, | |
7125 | + GL_FALSE, | |
7126 | + 0, | |
7127 | + textureCoordinates); | |
7128 | + | |
7129 | + GLfloat matrix[16]; | |
7130 | + android_media_surface_texture_get_transformation_matrix(player, matrix); | |
7131 | + | |
7132 | + glUniformMatrix4fv(gmTexMatrix, 1, GL_FALSE, matrix); | |
7133 | + | |
7134 | + glActiveTexture(GL_TEXTURE0); | |
7135 | + // Set the sampler texture unit to 0 | |
7136 | + glUniform1i(gsTextureHandle, 0); | |
7137 | + glUniform1i(gmTexMatrix, 0); | |
7138 | + android_media_update_surface_texture(player); | |
7139 | + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | |
7140 | + //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); | |
7141 | + glDisableVertexAttribArray(gaPositionHandle); | |
7142 | + glDisableVertexAttribArray(gaTexHandle); | |
7143 | + | |
7144 | + eglSwapBuffers(disp, surface); | |
7145 | + } | |
7146 | + | |
7147 | + android_media_stop(player); | |
7148 | + | |
7149 | + return EXIT_SUCCESS; | |
7150 | +} | |
7151 | --- /dev/null | |
7152 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_recorder.c | |
7153 | @@ -0,0 +1,490 @@ | |
7154 | +/* | |
7155 | + * Copyright (C) 2013 Canonical Ltd | |
7156 | + * | |
7157 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
7158 | + * you may not use this file except in compliance with the License. | |
7159 | + * You may obtain a copy of the License at | |
7160 | + * | |
7161 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
7162 | + * | |
7163 | + * Unless required by applicable law or agreed to in writing, software | |
7164 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
7165 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
7166 | + * See the License for the specific language governing permissions and | |
7167 | + * limitations under the License. | |
7168 | + * | |
7169 | + * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | |
7170 | + * Guenter Schwann <guenter.schwann@canonical.com> | |
7171 | + * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
7172 | + */ | |
7173 | + | |
7174 | +#include <hybris/camera/camera_compatibility_layer.h> | |
7175 | +#include <hybris/camera/camera_compatibility_layer_capabilities.h> | |
7176 | + | |
7177 | +#include <hybris/media/recorder_compatibility_layer.h> | |
7178 | + | |
7179 | +#include <hybris/input/input_stack_compatibility_layer.h> | |
7180 | +#include <hybris/input/input_stack_compatibility_layer_codes_key.h> | |
7181 | +#include <hybris/input/input_stack_compatibility_layer_flags_key.h> | |
7182 | + | |
7183 | +#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h> | |
7184 | + | |
7185 | +#include <EGL/egl.h> | |
7186 | +#include <GLES2/gl2.h> | |
7187 | +#include <GLES2/gl2ext.h> | |
7188 | + | |
7189 | +#include <assert.h> | |
7190 | +#include <stdlib.h> | |
7191 | +#include <stdio.h> | |
7192 | +#include <string.h> | |
7193 | +#include <stdbool.h> | |
7194 | +#include <limits.h> | |
7195 | +#include <fcntl.h> | |
7196 | +#include <unistd.h> | |
7197 | +#include <sys/stat.h> | |
7198 | +#include <sys/types.h> | |
7199 | + | |
7200 | +int shot_counter = 1; | |
7201 | +int32_t current_zoom_level = 1; | |
7202 | +bool new_camera_frame_available = true; | |
7203 | +struct MediaRecorderWrapper *mr = 0; | |
7204 | +GLuint preview_texture_id = 0; | |
7205 | + | |
7206 | +static GLuint gProgram; | |
7207 | +static GLuint gaPositionHandle, gaTexHandle, gsTextureHandle, gmTexMatrix; | |
7208 | + | |
7209 | +void error_msg_cb(void* context) | |
7210 | +{ | |
7211 | + printf("%s \n", __PRETTY_FUNCTION__); | |
7212 | +} | |
7213 | + | |
7214 | +void shutter_msg_cb(void* context) | |
7215 | +{ | |
7216 | + printf("%s \n", __PRETTY_FUNCTION__); | |
7217 | +} | |
7218 | + | |
7219 | +void zoom_msg_cb(void* context, int32_t new_zoom_level) | |
7220 | +{ | |
7221 | + printf("%s \n", __PRETTY_FUNCTION__); | |
7222 | + | |
7223 | + struct CameraControl* cc = (struct CameraControl*) context; | |
7224 | + static int zoom; | |
7225 | + current_zoom_level = new_zoom_level; | |
7226 | +} | |
7227 | + | |
7228 | +void autofocus_msg_cb(void* context) | |
7229 | +{ | |
7230 | + printf("%s \n", __PRETTY_FUNCTION__); | |
7231 | +} | |
7232 | + | |
7233 | +void raw_data_cb(void* data, uint32_t data_size, void* context) | |
7234 | +{ | |
7235 | + printf("%s: %d \n", __PRETTY_FUNCTION__, data_size); | |
7236 | +} | |
7237 | + | |
7238 | +void jpeg_data_cb(void* data, uint32_t data_size, void* context) | |
7239 | +{ | |
7240 | + printf("%s: %d \n", __PRETTY_FUNCTION__, data_size); | |
7241 | + struct CameraControl* cc = (struct CameraControl*) context; | |
7242 | + android_camera_start_preview(cc); | |
7243 | +} | |
7244 | + | |
7245 | +void size_cb(void* ctx, int width, int height) | |
7246 | +{ | |
7247 | + printf("Supported size: [%d,%d]\n", width, height); | |
7248 | +} | |
7249 | + | |
7250 | +void preview_texture_needs_update_cb(void* ctx) | |
7251 | +{ | |
7252 | + new_camera_frame_available = true; | |
7253 | +} | |
7254 | + | |
7255 | +void on_new_input_event(struct Event* event, void* context) | |
7256 | +{ | |
7257 | + assert(context); | |
7258 | + | |
7259 | + if (event->type == KEY_EVENT_TYPE && event->action == ISCL_KEY_EVENT_ACTION_UP) { | |
7260 | + printf("We have got a key event: %d \n", event->details.key.key_code); | |
7261 | + | |
7262 | + struct CameraControl* cc = (struct CameraControl*) context; | |
7263 | + | |
7264 | + int ret; | |
7265 | + switch (event->details.key.key_code) { | |
7266 | + case ISCL_KEYCODE_VOLUME_UP: | |
7267 | + printf("Starting video recording\n"); | |
7268 | + | |
7269 | + android_camera_unlock(cc); | |
7270 | + | |
7271 | + ret = android_recorder_setCamera(mr, cc); | |
7272 | + if (ret < 0) { | |
7273 | + printf("android_recorder_setCamera() failed\n"); | |
7274 | + return; | |
7275 | + } | |
7276 | + //state initial / idle | |
7277 | + ret = android_recorder_setAudioSource(mr, ANDROID_AUDIO_SOURCE_CAMCORDER); | |
7278 | + if (ret < 0) { | |
7279 | + printf("android_recorder_setAudioSource() failed\n"); | |
7280 | + return; | |
7281 | + } | |
7282 | + ret = android_recorder_setVideoSource(mr, ANDROID_VIDEO_SOURCE_CAMERA); | |
7283 | + if (ret < 0) { | |
7284 | + printf("android_recorder_setVideoSource() failed\n"); | |
7285 | + return; | |
7286 | + } | |
7287 | + //state initialized | |
7288 | + ret = android_recorder_setOutputFormat(mr, ANDROID_OUTPUT_FORMAT_MPEG_4); | |
7289 | + if (ret < 0) { | |
7290 | + printf("android_recorder_setOutputFormat() failed\n"); | |
7291 | + return; | |
7292 | + } | |
7293 | + //state DataSourceConfigured | |
7294 | + ret = android_recorder_setAudioEncoder(mr, ANDROID_AUDIO_ENCODER_AAC); | |
7295 | + if (ret < 0) { | |
7296 | + printf("android_recorder_setAudioEncoder() failed\n"); | |
7297 | + return; | |
7298 | + } | |
7299 | + ret = android_recorder_setVideoEncoder(mr, ANDROID_VIDEO_ENCODER_H264); | |
7300 | + if (ret < 0) { | |
7301 | + printf("android_recorder_setVideoEncoder() failed\n"); | |
7302 | + return; | |
7303 | + } | |
7304 | + | |
7305 | + int fd; | |
7306 | + fd = open("/tmp/test_video_recorder.avi", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | |
7307 | + if (fd < 0) { | |
7308 | + printf("Could not open file for video recording\n"); | |
7309 | + printf("FD: %i\n", fd); | |
7310 | + return; | |
7311 | + } | |
7312 | + ret = android_recorder_setOutputFile(mr, fd); | |
7313 | + if (ret < 0) { | |
7314 | + printf("android_recorder_setOutputFile() failed\n"); | |
7315 | + return; | |
7316 | + } | |
7317 | + | |
7318 | + ret = android_recorder_setVideoSize(mr, 1280, 720); | |
7319 | + if (ret < 0) { | |
7320 | + printf("android_recorder_setVideoSize() failed\n"); | |
7321 | + return; | |
7322 | + } | |
7323 | + ret = android_recorder_setVideoFrameRate(mr, 30); | |
7324 | + if (ret < 0) { | |
7325 | + printf("android_recorder_setVideoFrameRate() failed\n"); | |
7326 | + return; | |
7327 | + } | |
7328 | + | |
7329 | + ret = android_recorder_prepare(mr); | |
7330 | + if (ret < 0) { | |
7331 | + printf("android_recorder_prepare() failed\n"); | |
7332 | + return; | |
7333 | + } | |
7334 | + //state prepared | |
7335 | + ret = android_recorder_start(mr); | |
7336 | + if (ret < 0) { | |
7337 | + printf("android_recorder_start() failed\n"); | |
7338 | + return; | |
7339 | + } | |
7340 | + break; | |
7341 | + case ISCL_KEYCODE_VOLUME_DOWN: | |
7342 | + printf("Stoping video recording\n"); | |
7343 | + ret = android_recorder_stop(mr); | |
7344 | + | |
7345 | + printf("Stoping video recording returned\n"); | |
7346 | + if (ret < 0) { | |
7347 | + printf("android_recorder_stop() failed\n"); | |
7348 | + return; | |
7349 | + } | |
7350 | + printf("Stopped video recording\n"); | |
7351 | + ret = android_recorder_reset(mr); | |
7352 | + if (ret < 0) { | |
7353 | + printf("android_recorder_reset() failed\n"); | |
7354 | + return; | |
7355 | + } | |
7356 | + printf("Reset video recorder\n"); | |
7357 | + break; | |
7358 | + } | |
7359 | + } | |
7360 | +} | |
7361 | + | |
7362 | +struct ClientWithSurface | |
7363 | +{ | |
7364 | + struct SfClient* client; | |
7365 | + struct SfSurface* surface; | |
7366 | +}; | |
7367 | + | |
7368 | +struct ClientWithSurface client_with_surface(bool setup_surface_with_egl) | |
7369 | +{ | |
7370 | + struct ClientWithSurface cs; | |
7371 | + | |
7372 | + cs.client = sf_client_create(); | |
7373 | + | |
7374 | + if (!cs.client) { | |
7375 | + printf("Problem creating client ... aborting now."); | |
7376 | + return cs; | |
7377 | + } | |
7378 | + | |
7379 | + static const size_t primary_display = 0; | |
7380 | + | |
7381 | + SfSurfaceCreationParameters params = { | |
7382 | + 0, | |
7383 | + 0, | |
7384 | + sf_get_display_width(primary_display), | |
7385 | + sf_get_display_height(primary_display), | |
7386 | + -1, //PIXEL_FORMAT_RGBA_8888, | |
7387 | + 15000, | |
7388 | + 0.5f, | |
7389 | + setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL | |
7390 | + "CameraCompatLayerTestSurface" | |
7391 | + }; | |
7392 | + | |
7393 | + cs.surface = sf_surface_create(cs.client, ¶ms); | |
7394 | + | |
7395 | + if (!cs.surface) { | |
7396 | + printf("Problem creating surface ... aborting now."); | |
7397 | + return cs; | |
7398 | + } | |
7399 | + | |
7400 | + sf_surface_make_current(cs.surface); | |
7401 | + | |
7402 | + return cs; | |
7403 | +} | |
7404 | + | |
7405 | +static const char* vertex_shader() | |
7406 | +{ | |
7407 | + return | |
7408 | + "#extension GL_OES_EGL_image_external : require \n" | |
7409 | + "attribute vec4 a_position; \n" | |
7410 | + "attribute vec2 a_texCoord; \n" | |
7411 | + "uniform mat4 m_texMatrix; \n" | |
7412 | + "varying vec2 v_texCoord; \n" | |
7413 | + "varying float topDown; \n" | |
7414 | + "void main() \n" | |
7415 | + "{ \n" | |
7416 | + " gl_Position = a_position; \n" | |
7417 | + " v_texCoord = a_texCoord; \n" | |
7418 | + // " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n" | |
7419 | + //" topDown = v_texCoord.y; \n" | |
7420 | + "} \n"; | |
7421 | +} | |
7422 | + | |
7423 | +static const char* fragment_shader() | |
7424 | +{ | |
7425 | + return | |
7426 | + "#extension GL_OES_EGL_image_external : require \n" | |
7427 | + "precision mediump float; \n" | |
7428 | + "varying vec2 v_texCoord; \n" | |
7429 | + "uniform samplerExternalOES s_texture; \n" | |
7430 | + "void main() \n" | |
7431 | + "{ \n" | |
7432 | + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" | |
7433 | + "} \n"; | |
7434 | +} | |
7435 | + | |
7436 | +static GLuint loadShader(GLenum shaderType, const char* pSource) { | |
7437 | + GLuint shader = glCreateShader(shaderType); | |
7438 | + | |
7439 | + if (shader) { | |
7440 | + glShaderSource(shader, 1, &pSource, NULL); | |
7441 | + glCompileShader(shader); | |
7442 | + GLint compiled = 0; | |
7443 | + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); | |
7444 | + | |
7445 | + if (!compiled) { | |
7446 | + GLint infoLen = 0; | |
7447 | + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); | |
7448 | + if (infoLen) { | |
7449 | + char* buf = (char*) malloc(infoLen); | |
7450 | + if (buf) { | |
7451 | + glGetShaderInfoLog(shader, infoLen, NULL, buf); | |
7452 | + fprintf(stderr, "Could not compile shader %d:\n%s\n", | |
7453 | + shaderType, buf); | |
7454 | + free(buf); | |
7455 | + } | |
7456 | + glDeleteShader(shader); | |
7457 | + shader = 0; | |
7458 | + } | |
7459 | + } | |
7460 | + } else { | |
7461 | + printf("Error, during shader creation: %i\n", glGetError()); | |
7462 | + } | |
7463 | + | |
7464 | + return shader; | |
7465 | +} | |
7466 | + | |
7467 | +static GLuint create_program(const char* pVertexSource, const char* pFragmentSource) { | |
7468 | + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); | |
7469 | + if (!vertexShader) { | |
7470 | + printf("vertex shader not compiled\n"); | |
7471 | + return 0; | |
7472 | + } | |
7473 | + | |
7474 | + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); | |
7475 | + if (!pixelShader) { | |
7476 | + printf("frag shader not compiled\n"); | |
7477 | + return 0; | |
7478 | + } | |
7479 | + | |
7480 | + GLuint program = glCreateProgram(); | |
7481 | + if (program) { | |
7482 | + glAttachShader(program, vertexShader); | |
7483 | + glAttachShader(program, pixelShader); | |
7484 | + glLinkProgram(program); | |
7485 | + GLint linkStatus = GL_FALSE; | |
7486 | + | |
7487 | + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); | |
7488 | + if (linkStatus != GL_TRUE) { | |
7489 | + GLint bufLength = 0; | |
7490 | + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); | |
7491 | + if (bufLength) { | |
7492 | + char* buf = (char*) malloc(bufLength); | |
7493 | + if (buf) { | |
7494 | + glGetProgramInfoLog(program, bufLength, NULL, buf); | |
7495 | + fprintf(stderr, "Could not link program:\n%s\n", buf); | |
7496 | + free(buf); | |
7497 | + } | |
7498 | + } | |
7499 | + glDeleteProgram(program); | |
7500 | + program = 0; | |
7501 | + } | |
7502 | + } | |
7503 | + | |
7504 | + return program; | |
7505 | +} | |
7506 | + | |
7507 | +int main(int argc, char** argv) | |
7508 | +{ | |
7509 | + printf("Test application for video recording using the camera\n"); | |
7510 | + printf("Recording start with volume up button. And stops with volume down.\n"); | |
7511 | + printf("The result is stored to /root/test_video.avi\n\n"); | |
7512 | + | |
7513 | + struct CameraControlListener listener; | |
7514 | + memset(&listener, 0, sizeof(listener)); | |
7515 | + listener.on_msg_error_cb = error_msg_cb; | |
7516 | + listener.on_msg_shutter_cb = shutter_msg_cb; | |
7517 | + listener.on_msg_focus_cb = autofocus_msg_cb; | |
7518 | + listener.on_msg_zoom_cb = zoom_msg_cb; | |
7519 | + | |
7520 | + listener.on_data_raw_image_cb = raw_data_cb; | |
7521 | + listener.on_data_compressed_image_cb = jpeg_data_cb; | |
7522 | + listener.on_preview_texture_needs_update_cb = preview_texture_needs_update_cb; | |
7523 | + struct CameraControl* cc = android_camera_connect_to(BACK_FACING_CAMERA_TYPE, | |
7524 | + &listener); | |
7525 | + if (cc == NULL) { | |
7526 | + printf("Problem connecting to camera"); | |
7527 | + return 1; | |
7528 | + } | |
7529 | + | |
7530 | + listener.context = cc; | |
7531 | + | |
7532 | + mr = android_media_new_recorder(); | |
7533 | + | |
7534 | + struct AndroidEventListener event_listener; | |
7535 | + event_listener.on_new_event = on_new_input_event; | |
7536 | + event_listener.context = cc; | |
7537 | + | |
7538 | + struct InputStackConfiguration input_configuration = { false, 25000 }; | |
7539 | + | |
7540 | + android_input_stack_initialize(&event_listener, &input_configuration); | |
7541 | + android_input_stack_start(); | |
7542 | + | |
7543 | + android_camera_dump_parameters(cc); | |
7544 | + | |
7545 | + printf("Supported video sizes:\n"); | |
7546 | + android_camera_enumerate_supported_video_sizes(cc, size_cb, NULL); | |
7547 | + | |
7548 | + int min_fps, max_fps, current_fps; | |
7549 | + | |
7550 | + android_camera_set_preview_size(cc, 1280, 720); | |
7551 | + | |
7552 | + int width, height; | |
7553 | + android_camera_get_video_size(cc, &width, &height); | |
7554 | + printf("Current video size: [%d,%d]\n", width, height); | |
7555 | + | |
7556 | + struct ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */); | |
7557 | + | |
7558 | + if (!cs.surface) { | |
7559 | + printf("Problem acquiring surface for preview"); | |
7560 | + return 1; | |
7561 | + } | |
7562 | + | |
7563 | + EGLDisplay disp = sf_client_get_egl_display(cs.client); | |
7564 | + EGLSurface surface = sf_surface_get_egl_surface(cs.surface); | |
7565 | + | |
7566 | + sf_surface_make_current(cs.surface); | |
7567 | + | |
7568 | + gProgram = create_program(vertex_shader(), fragment_shader()); | |
7569 | + gaPositionHandle = glGetAttribLocation(gProgram, "a_position"); | |
7570 | + gaTexHandle = glGetAttribLocation(gProgram, "a_texCoord"); | |
7571 | + gsTextureHandle = glGetUniformLocation(gProgram, "s_texture"); | |
7572 | + gmTexMatrix = glGetUniformLocation(gProgram, "m_texMatrix"); | |
7573 | + | |
7574 | + glGenTextures(1, &preview_texture_id); | |
7575 | + glClearColor(1.0, 0., 0.5, 1.); | |
7576 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
7577 | + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
7578 | + glTexParameteri( | |
7579 | + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
7580 | + glTexParameteri( | |
7581 | + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
7582 | + android_camera_set_preview_texture(cc, preview_texture_id); | |
7583 | + android_camera_start_preview(cc); | |
7584 | + | |
7585 | + GLfloat transformation_matrix[16]; | |
7586 | + android_camera_get_preview_texture_transformation(cc, transformation_matrix); | |
7587 | + glUniformMatrix4fv(gmTexMatrix, 1, GL_FALSE, transformation_matrix); | |
7588 | + | |
7589 | + printf("Started camera preview.\n"); | |
7590 | + | |
7591 | + while (true) { | |
7592 | + /*if (new_camera_frame_available) | |
7593 | + { | |
7594 | + printf("Updating texture"); | |
7595 | + new_camera_frame_available = false; | |
7596 | + }*/ | |
7597 | + static GLfloat vVertices[] = { 0.0f, 0.0f, 0.0f, // Position 0 | |
7598 | + 0.0f, 0.0f, // TexCoord 0 | |
7599 | + 0.0f, 1.0f, 0.0f, // Position 1 | |
7600 | + 0.0f, 1.0f, // TexCoord 1 | |
7601 | + 1.0f, 1.0f, 0.0f, // Position 2 | |
7602 | + 1.0f, 1.0f, // TexCoord 2 | |
7603 | + 1.0f, 0.0f, 0.0f, // Position 3 | |
7604 | + 1.0f, 0.0f // TexCoord 3 | |
7605 | + }; | |
7606 | + | |
7607 | + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; | |
7608 | + | |
7609 | + // Set the viewport | |
7610 | + // Clear the color buffer | |
7611 | + glClear(GL_COLOR_BUFFER_BIT); | |
7612 | + // Use the program object | |
7613 | + glUseProgram(gProgram); | |
7614 | + // Enable attributes | |
7615 | + glEnableVertexAttribArray(gaPositionHandle); | |
7616 | + glEnableVertexAttribArray(gaTexHandle); | |
7617 | + // Load the vertex position | |
7618 | + glVertexAttribPointer(gaPositionHandle, | |
7619 | + 3, | |
7620 | + GL_FLOAT, | |
7621 | + GL_FALSE, | |
7622 | + 5 * sizeof(GLfloat), | |
7623 | + vVertices); | |
7624 | + // Load the texture coordinate | |
7625 | + glVertexAttribPointer(gaTexHandle, | |
7626 | + 2, | |
7627 | + GL_FLOAT, | |
7628 | + GL_FALSE, | |
7629 | + 5 * sizeof(GLfloat), | |
7630 | + vVertices+3); | |
7631 | + | |
7632 | + glActiveTexture(GL_TEXTURE0); | |
7633 | + // Set the sampler texture unit to 0 | |
7634 | + glUniform1i(gsTextureHandle, 0); | |
7635 | + glUniform1i(gmTexMatrix, 0); | |
7636 | + android_camera_update_preview_texture(cc); | |
7637 | + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); | |
7638 | + glDisableVertexAttribArray(gaPositionHandle); | |
7639 | + glDisableVertexAttribArray(gaTexHandle); | |
7640 | + | |
7641 | + eglSwapBuffers(disp, surface); | |
7642 | + } | |
7643 | +} | |
7644 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/test_ui.c | |
7645 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_ui.c | |
7646 | @@ -52,8 +52,10 @@ int main(int argc, char **argv) | |
7647 | graphic_buffer_lock(buffer, GRALLOC_USAGE_HW_RENDER, &vaddr); | |
7648 | graphic_buffer_unlock(buffer); | |
7649 | ||
7650 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
7651 | graphic_buffer_set_index(buffer, 11); | |
7652 | assert(graphic_buffer_get_index(buffer) == 11); | |
7653 | +#endif | |
7654 | ||
7655 | graphic_buffer_free(buffer); | |
7656 | ||
7657 | --- libhybris-0.1.0+git20131207+e452e83.orig/hybris/ui/ui.c | |
7658 | +++ libhybris-0.1.0+git20131207+e452e83/hybris/ui/ui.c | |
7659 | @@ -48,9 +48,11 @@ HYBRIS_IMPLEMENT_FUNCTION1(ui, uint32_t, | |
7660 | struct graphic_buffer*); | |
7661 | HYBRIS_IMPLEMENT_FUNCTION1(ui, void*, graphic_buffer_get_native_buffer, | |
7662 | struct graphic_buffer*); | |
7663 | +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 | |
7664 | HYBRIS_IMPLEMENT_VOID_FUNCTION2(ui, graphic_buffer_set_index, | |
7665 | struct graphic_buffer*, int); | |
7666 | HYBRIS_IMPLEMENT_FUNCTION1(ui, int, graphic_buffer_get_index, | |
7667 | struct graphic_buffer*); | |
7668 | +#endif | |
7669 | HYBRIS_IMPLEMENT_FUNCTION1(ui, int, graphic_buffer_init_check, | |
7670 | struct graphic_buffer*); |