--- /dev/null
+Subject: Collected Debian patches for libhybris
+Author: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
+
+The libhybris package is maintained in Git rather than maintaining
+patches as separate files, and separating the patches doesn't seem to
+be worth the effort. They are therefore all included in this single
+Debian patch.
+
+For full commit history and separated commits, see the packaging Git
+repository.
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/Android.common.mk
+@@ -0,0 +1,10 @@
++# define ANDROID_VERSION MAJOR, MINOR and PATCH
++
++ANDROID_VERSION_MAJOR := $(word 1, $(subst ., , $(PLATFORM_VERSION)))
++ANDROID_VERSION_MINOR := $(word 2, $(subst ., , $(PLATFORM_VERSION)))
++ANDROID_VERSION_PATCH := $(word 3, $(subst ., , $(PLATFORM_VERSION)))
++
++LOCAL_CFLAGS += \
++ -DANDROID_VERSION_MAJOR=$(ANDROID_VERSION_MAJOR) \
++ -DANDROID_VERSION_MINOR=$(ANDROID_VERSION_MINOR) \
++ -DANDROID_VERSION_PATCH=$(ANDROID_VERSION_PATCH)
+--- libhybris-0.1.0+git20131207+e452e83.orig/compat/camera/Android.mk
++++ libhybris-0.1.0+git20131207+e452e83/compat/camera/Android.mk
+@@ -1,5 +1,6 @@
+ LOCAL_PATH:= $(call my-dir)
+ include $(CLEAR_VARS)
++include $(LOCAL_PATH)/../Android.common.mk
+
+ HYBRIS_PATH := $(LOCAL_PATH)/../../hybris
+
+--- libhybris-0.1.0+git20131207+e452e83.orig/compat/camera/camera_compatibility_layer.cpp
++++ libhybris-0.1.0+git20131207+e452e83/compat/camera/camera_compatibility_layer.cpp
+@@ -27,17 +27,25 @@
+ #include <binder/ProcessState.h>
+ #include <camera/Camera.h>
+ #include <camera/CameraParameters.h>
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
+ #include <gui/SurfaceTexture.h>
++#else
++#include <gui/GLConsumer.h>
++#endif
+ #include <ui/GraphicBuffer.h>
+
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++
+ #undef LOG_TAG
+ #define LOG_TAG "CameraCompatibilityLayer"
+ #include <utils/KeyedVector.h>
+ #include <utils/Log.h>
++#include <utils/String16.h>
+
+ #define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__)
+
+-// From android::SurfaceTexture::FrameAvailableListener
++// From android::GLConsumer::FrameAvailableListener
+ void CameraControl::onFrameAvailable()
+ {
+ REPORT_FUNCTION();
+@@ -170,7 +178,11 @@ CameraControl* android_camera_connect_to
+
+ CameraControl* cc = new CameraControl();
+ cc->listener = listener;
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=3
++ cc->camera = android::Camera::connect(camera_id, android::String16("hybris"), android::Camera::USE_CALLING_UID);
++#else
+ cc->camera = android::Camera::connect(camera_id);
++#endif
+
+ if (cc->camera == NULL)
+ return NULL;
+@@ -511,30 +523,57 @@ void android_camera_set_preview_texture(
+ assert(control);
+
+ static const bool allow_synchronous_mode = false;
++ static const bool is_controlled_by_app = true;
+
+ android::sp<android::NativeBufferAlloc> native_alloc(
+ new android::NativeBufferAlloc()
+ );
+
+ android::sp<android::BufferQueue> buffer_queue(
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
+ new android::BufferQueue(false, NULL, native_alloc)
++#else
++ new android::BufferQueue(NULL, native_alloc)
++#endif
+ );
+
+ if (control->preview_texture == NULL) {
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
+ control->preview_texture = android::sp<android::SurfaceTexture>(
+ new android::SurfaceTexture(
++#else
++ control->preview_texture = android::sp<android::GLConsumer>(
++ new android::GLConsumer(
++#endif
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
+ texture_id,
+ allow_synchronous_mode,
+ GL_TEXTURE_EXTERNAL_OES,
+ true,
+ buffer_queue));
++#else
++ buffer_queue,
++ texture_id,
++ GL_TEXTURE_EXTERNAL_OES,
++ true,
++ is_controlled_by_app));
++#endif
+ }
+
+ control->preview_texture->setFrameAvailableListener(
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
+ android::sp<android::SurfaceTexture::FrameAvailableListener>(control));
++#else
++ android::sp<android::GLConsumer::FrameAvailableListener>(control));
++#endif
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
+ control->camera->setPreviewTexture(control->preview_texture->getBufferQueue());
++#else
++ control->camera->setPreviewTarget(buffer_queue);
++#endif
+ }
+
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
+ void android_camera_set_preview_surface(CameraControl* control, SfSurface* surface)
+ {
+ REPORT_FUNCTION();
+@@ -544,6 +583,7 @@ void android_camera_set_preview_surface(
+ android::Mutex::Autolock al(control->guard);
+ control->camera->setPreviewDisplay(surface->surface);
+ }
++#endif
+
+ void android_camera_start_preview(CameraControl* control)
+ {
+--- libhybris-0.1.0+git20131207+e452e83.orig/compat/input/Android.mk
++++ libhybris-0.1.0+git20131207+e452e83/compat/input/Android.mk
+@@ -18,6 +18,11 @@ LOCAL_SHARED_LIBRARIES := \
+ libgui \
+ libandroidfw
+
++HAS_LIBINPUTSERVICE := $(shell test $(ANDROID_VERSION_MAJOR) -eq 4 -a $(ANDROID_VERSION_MINOR) -gt 2 && echo true)
++ifeq ($(HAS_LIBINPUTSERVICE),true)
++LOCAL_SHARED_LIBRARIES += libinputservice
++endif
++
+ LOCAL_C_INCLUDES := \
+ $(HYBRIS_PATH)/include \
+ external/skia/include/core \
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/Android.mk
+@@ -0,0 +1,109 @@
++LOCAL_PATH:= $(call my-dir)
++include $(CLEAR_VARS)
++include $(LOCAL_PATH)/../Android.common.mk
++
++HYBRIS_PATH := $(LOCAL_PATH)/../../hybris
++
++LOCAL_CFLAGS += -std=gnu++0x
++
++LOCAL_SRC_FILES:= \
++ media_compatibility_layer.cpp \
++ media_codec_layer.cpp \
++ media_codec_list.cpp \
++ media_format_layer.cpp \
++ surface_texture_client_hybris.cpp \
++ recorder_compatibility_layer.cpp
++
++LOCAL_MODULE:= libmedia_compat_layer
++LOCAL_MODULE_TAGS := optional
++
++LOCAL_SHARED_LIBRARIES := \
++ libcutils \
++ libcamera_client \
++ libutils \
++ libbinder \
++ libhardware \
++ libui \
++ libgui \
++ libstagefright \
++ libstagefright_foundation \
++ libEGL \
++ libGLESv2 \
++ libmedia
++
++LOCAL_C_INCLUDES := \
++ $(HYBRIS_PATH)/include \
++ frameworks/base/media/libstagefright/include \
++ frameworks/base/include/media/stagefright \
++ frameworks/base/include/media
++
++include $(BUILD_SHARED_LIBRARY)
++
++include $(CLEAR_VARS)
++include $(LOCAL_PATH)/../Android.common.mk
++
++LOCAL_SRC_FILES:= \
++ direct_media_test.cpp
++
++LOCAL_MODULE:= direct_media_test
++LOCAL_MODULE_TAGS := optional
++
++LOCAL_C_INCLUDES := \
++ $(HYBRIS_PATH)/include \
++ bionic \
++ bionic/libstdc++/include \
++ external/gtest/include \
++ external/stlport/stlport \
++ external/skia/include/core \
++ frameworks/base/include
++
++LOCAL_SHARED_LIBRARIES := \
++ libis_compat_layer \
++ libsf_compat_layer \
++ libmedia_compat_layer \
++ libcutils \
++ libutils \
++ libbinder \
++ libhardware \
++ libui \
++ libgui \
++ libEGL \
++ libGLESv2
++
++include $(BUILD_EXECUTABLE)
++
++include $(CLEAR_VARS)
++include $(LOCAL_PATH)/../Android.common.mk
++
++LOCAL_CFLAGS += -Wno-multichar -D SIMPLE_PLAYER -std=gnu++0x
++
++LOCAL_SRC_FILES:= \
++ media_codec_layer.cpp \
++ media_codec_list.cpp \
++ media_format_layer.cpp \
++ codec.cpp \
++ SimplePlayer.cpp
++
++LOCAL_SHARED_LIBRARIES := \
++ libstagefright \
++ libstagefright_foundation \
++ liblog \
++ libutils \
++ libbinder \
++ libmedia \
++ libgui \
++ libcutils \
++ libui
++
++LOCAL_C_INCLUDES:= \
++ $(HYBRIS_PATH)/include \
++ frameworks/av/media/libstagefright \
++ frameworks/native/include/media/openmax \
++ frameworks/base/media/libstagefright/include \
++ frameworks/base/include/media/stagefright \
++ frameworks/base/include/media
++
++LOCAL_MODULE:= codec
++LOCAL_MODULE_TAGS := optional
++
++include $(BUILD_EXECUTABLE)
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/SimplePlayer.cpp
+@@ -0,0 +1,777 @@
++/*
++ * Copyright (C) 2012 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++//#define LOG_NDEBUG 0
++#define LOG_TAG "SimplePlayer"
++#include <utils/Log.h>
++
++#include "SimplePlayer.h"
++
++#include <gui/Surface.h>
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++#include <gui/SurfaceTextureClient.h>
++#endif
++#include <media/AudioTrack.h>
++#include <media/ICrypto.h>
++#include <media/stagefright/foundation/ABuffer.h>
++#include <media/stagefright/foundation/ADebug.h>
++#include <media/stagefright/foundation/AMessage.h>
++#include <media/stagefright/MediaCodec.h>
++#include <media/stagefright/MediaErrors.h>
++#include <media/stagefright/NativeWindowWrapper.h>
++#include <media/stagefright/NuMediaExtractor.h>
++
++#define USE_MEDIA_CODEC_LAYER
++
++namespace android {
++
++SimplePlayer::SimplePlayer()
++ : mState(UNINITIALIZED),
++ mDoMoreStuffGeneration(0),
++ mStartTimeRealUs(-1ll) {
++}
++
++SimplePlayer::~SimplePlayer() {
++}
++
++// static
++status_t PostAndAwaitResponse(
++ const sp<AMessage> &msg, sp<AMessage> *response) {
++ status_t err = msg->postAndAwaitResponse(response);
++ printf("%s\n", __PRETTY_FUNCTION__);
++
++ if (err != OK) {
++ return err;
++ }
++
++ if (!(*response)->findInt32("err", &err)) {
++ err = OK;
++ }
++
++ return err;
++}
++status_t SimplePlayer::setDataSource(const char *path) {
++ sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
++ msg->setString("path", path);
++ sp<AMessage> response;
++ return PostAndAwaitResponse(msg, &response);
++}
++
++status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) {
++ sp<AMessage> msg = new AMessage(kWhatSetSurface, id());
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ sp<SurfaceTextureClient> surfaceTextureClient;
++ if (surfaceTexture != NULL) {
++ surfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
++ }
++#else
++ sp<Surface> surfaceTextureClient;
++ if (surfaceTexture != NULL) {
++ surfaceTextureClient = new Surface(surfaceTexture);
++ }
++#endif
++
++ msg->setObject(
++ "native-window", new NativeWindowWrapper(surfaceTextureClient));
++
++ sp<AMessage> response;
++ return PostAndAwaitResponse(msg, &response);
++}
++
++status_t SimplePlayer::prepare() {
++ sp<AMessage> msg = new AMessage(kWhatPrepare, id());
++ sp<AMessage> response;
++ return PostAndAwaitResponse(msg, &response);
++}
++
++status_t SimplePlayer::start() {
++ printf("%s\n", __PRETTY_FUNCTION__);
++ sp<AMessage> msg = new AMessage(kWhatStart, id());
++ sp<AMessage> response;
++ return PostAndAwaitResponse(msg, &response);
++}
++
++status_t SimplePlayer::stop() {
++ sp<AMessage> msg = new AMessage(kWhatStop, id());
++ sp<AMessage> response;
++ return PostAndAwaitResponse(msg, &response);
++}
++
++status_t SimplePlayer::reset() {
++ sp<AMessage> msg = new AMessage(kWhatReset, id());
++ sp<AMessage> response;
++ return PostAndAwaitResponse(msg, &response);
++}
++
++void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) {
++ switch (msg->what()) {
++ case kWhatSetDataSource:
++ {
++ status_t err;
++ if (mState != UNINITIALIZED) {
++ err = INVALID_OPERATION;
++ } else {
++ CHECK(msg->findString("path", &mPath));
++ mState = UNPREPARED;
++ }
++
++ uint32_t replyID;
++ CHECK(msg->senderAwaitsResponse(&replyID));
++
++ sp<AMessage> response = new AMessage;
++ response->setInt32("err", err);
++ response->postReply(replyID);
++ break;
++ }
++
++ case kWhatSetSurface:
++ {
++ status_t err;
++ if (mState != UNPREPARED) {
++ err = INVALID_OPERATION;
++ } else {
++ sp<RefBase> obj;
++ CHECK(msg->findObject("native-window", &obj));
++
++ mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
++
++ err = OK;
++ }
++
++ uint32_t replyID;
++ CHECK(msg->senderAwaitsResponse(&replyID));
++
++ sp<AMessage> response = new AMessage;
++ response->setInt32("err", err);
++ response->postReply(replyID);
++ break;
++ }
++
++ case kWhatPrepare:
++ {
++ status_t err;
++ if (mState != UNPREPARED) {
++ err = INVALID_OPERATION;
++ } else {
++ err = onPrepare();
++
++ if (err == OK) {
++ mState = STOPPED;
++ }
++ }
++
++ uint32_t replyID;
++ CHECK(msg->senderAwaitsResponse(&replyID));
++
++ sp<AMessage> response = new AMessage;
++ response->setInt32("err", err);
++ response->postReply(replyID);
++ break;
++ }
++
++ case kWhatStart:
++ {
++ status_t err = OK;
++
++ if (mState == UNPREPARED) {
++ err = onPrepare();
++
++ if (err == OK) {
++ mState = STOPPED;
++ }
++ }
++
++ if (err == OK) {
++ if (mState != STOPPED) {
++ err = INVALID_OPERATION;
++ } else {
++ err = onStart();
++
++ if (err == OK) {
++ mState = STARTED;
++ }
++ }
++ }
++
++ uint32_t replyID;
++ CHECK(msg->senderAwaitsResponse(&replyID));
++
++ sp<AMessage> response = new AMessage;
++ response->setInt32("err", err);
++ response->postReply(replyID);
++ break;
++ }
++
++ case kWhatStop:
++ {
++ status_t err;
++
++ if (mState != STARTED) {
++ err = INVALID_OPERATION;
++ } else {
++ err = onStop();
++
++ if (err == OK) {
++ mState = STOPPED;
++ }
++ }
++
++ uint32_t replyID;
++ CHECK(msg->senderAwaitsResponse(&replyID));
++
++ sp<AMessage> response = new AMessage;
++ response->setInt32("err", err);
++ response->postReply(replyID);
++ break;
++ }
++
++ case kWhatReset:
++ {
++ status_t err = OK;
++
++ if (mState == STARTED) {
++ CHECK_EQ(onStop(), (status_t)OK);
++ mState = STOPPED;
++ }
++
++ if (mState == STOPPED) {
++ err = onReset();
++ mState = UNINITIALIZED;
++ }
++
++ uint32_t replyID;
++ CHECK(msg->senderAwaitsResponse(&replyID));
++
++ sp<AMessage> response = new AMessage;
++ response->setInt32("err", err);
++ response->postReply(replyID);
++ break;
++ }
++
++ case kWhatDoMoreStuff:
++ {
++ int32_t generation;
++ CHECK(msg->findInt32("generation", &generation));
++
++ if (generation != mDoMoreStuffGeneration) {
++ break;
++ }
++
++ status_t err = onDoMoreStuff();
++
++ if (err == OK) {
++ msg->post(10000ll);
++ }
++ break;
++ }
++
++ default:
++ TRESPASS();
++ }
++}
++
++status_t SimplePlayer::onPrepare() {
++ CHECK_EQ(mState, UNPREPARED);
++ printf("%s\n", __PRETTY_FUNCTION__);
++
++ mExtractor = new NuMediaExtractor;
++
++ status_t err = mExtractor->setDataSource(mPath.c_str());
++
++ if (err != OK) {
++ mExtractor.clear();
++ return err;
++ }
++
++ if (mCodecLooper == NULL) {
++ mCodecLooper = new ALooper;
++ mCodecLooper->start();
++ }
++
++ bool haveAudio = false;
++ bool haveVideo = false;
++ for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
++ sp<AMessage> format;
++ status_t err = mExtractor->getTrackFormat(i, &format);
++ CHECK_EQ(err, (status_t)OK);
++
++ AString mime;
++ int32_t width = 0, height = 0, maxInputSize = 0;
++ int64_t durationUs = 0;
++ sp<ABuffer> csd0, csd1;
++#ifdef USE_MEDIA_CODEC_LAYER
++ MediaFormat mformat;
++#endif
++ CHECK(format->findString("mime", &mime));
++
++ if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) {
++ //haveAudio = true;
++ printf("*** Have audio but skipping it!\n");
++ continue;
++ } else if (!haveVideo && !strncasecmp(mime.c_str(), "video/", 6)) {
++ haveVideo = true;
++ CHECK(format->findInt32("width", &width));
++ CHECK(format->findInt32("height", &height));
++ CHECK(format->findInt64("durationUs", &durationUs));
++ CHECK(format->findInt32("max-input-size", &maxInputSize));
++ CHECK(format->findBuffer("csd-0", &csd0));
++ CHECK(format->findBuffer("csd-1", &csd1));
++#ifdef USE_MEDIA_CODEC_LAYER
++ mformat = media_format_create_video_format(mime.c_str(), width, height, durationUs, maxInputSize);
++ media_format_set_byte_buffer(mformat, "csd-0", csd0->data(), csd0->size());
++ media_format_set_byte_buffer(mformat, "csd-1", csd1->data(), csd1->size());
++#endif
++ } else {
++ continue;
++ }
++
++ err = mExtractor->selectTrack(i);
++ CHECK_EQ(err, (status_t)OK);
++
++ CodecState *state =
++ &mStateByTrackIndex.editValueAt(
++ mStateByTrackIndex.add(i, CodecState()));
++
++ state->mNumFramesWritten = 0;
++#ifdef USE_MEDIA_CODEC_LAYER
++ state->mCodecDelegate = media_codec_create_by_codec_type(mime.c_str());
++ state->mCodec = media_codec_get(state->mCodecDelegate);
++ CHECK(state->mCodecDelegate != NULL);
++#else
++ state->mCodec = MediaCodec::CreateByType(
++ mCodecLooper, mime.c_str(), false /* encoder */);
++#endif
++
++ CHECK(state->mCodec != NULL);
++
++#ifdef USE_MEDIA_CODEC_LAYER
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ err = media_codec_configure(state->mCodecDelegate, mformat, mNativeWindow->getSurfaceTextureClient().get(), 0);
++#else
++ err = media_codec_configure(state->mCodecDelegate, mformat, mNativeWindow->getSurface().get(), 0);
++#endif
++#else
++ err = state->mCodec->configure(
++ format,
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ mNativeWindow->getSurfaceTextureClient(),
++#else
++ mNativeWindow->getSurface(),
++#endif
++ NULL /* crypto */,
++ 0 /* flags */);
++#endif
++
++ CHECK_EQ(err, (status_t)OK);
++
++ size_t j = 0;
++ sp<ABuffer> buffer;
++ // Place the CSD data into the source buffer
++ while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) {
++ state->mCSD.push_back(buffer);
++
++ ++j;
++ }
++ }
++
++ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
++ CodecState *state = &mStateByTrackIndex.editValueAt(i);
++
++#ifdef USE_MEDIA_CODEC_LAYER
++ status_t err = media_codec_start(state->mCodecDelegate);
++#else
++ status_t err = state->mCodec->start();
++#endif
++ CHECK_EQ(err, (status_t)OK);
++
++#ifdef USE_MEDIA_CODEC_LAYER
++ size_t nInputBuffers = media_codec_get_input_buffers_size(state->mCodecDelegate);
++ ALOGD("nInputBuffers: %u", nInputBuffers);
++ for (size_t i=0; i<nInputBuffers; i++)
++ {
++ uint8_t *data = media_codec_get_nth_input_buffer(state->mCodecDelegate, i);
++ CHECK(data != NULL);
++ size_t size = media_codec_get_nth_input_buffer_capacity(state->mCodecDelegate, i);
++ ALOGD("input buffer[%d] size: %d", i, size);
++ sp<ABuffer> buf = new ABuffer(data, size);
++ state->mBuffers[0].insertAt(new ABuffer(data, size), i);
++ }
++#else
++ err = state->mCodec->getInputBuffers(&state->mBuffers[0]);
++ CHECK_EQ(err, (status_t)OK);
++#endif
++
++ err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
++ CHECK_EQ(err, (status_t)OK);
++
++ for (size_t j = 0; j < state->mCSD.size(); ++j) {
++ const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j);
++
++ size_t index;
++#ifdef USE_MEDIA_CODEC_LAYER
++ err = media_codec_dequeue_input_buffer(state->mCodecDelegate, &index, -1ll);
++#else
++ err = state->mCodec->dequeueInputBuffer(&index, -1ll);
++#endif
++ CHECK_EQ(err, (status_t)OK);
++
++ const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
++
++ CHECK_LE(srcBuffer->size(), dstBuffer->capacity());
++ dstBuffer->setRange(0, srcBuffer->size());
++ memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size());
++
++#ifdef USE_MEDIA_CODEC_LAYER
++ MediaCodecBufferInfo bufInfo;
++ bufInfo.index = index;
++ bufInfo.offset = 0;
++ bufInfo.size = dstBuffer->size();
++ bufInfo.presentation_time_us = 0ll;
++ bufInfo.flags = MediaCodec::BUFFER_FLAG_CODECCONFIG;
++
++ err = media_codec_queue_input_buffer(
++ state->mCodecDelegate,
++ &bufInfo);
++
++#else
++ err = state->mCodec->queueInputBuffer(
++ index,
++ 0,
++ dstBuffer->size(),
++ 0ll,
++ MediaCodec::BUFFER_FLAG_CODECCONFIG);
++#endif
++ CHECK_EQ(err, (status_t)OK);
++ }
++ }
++
++ return OK;
++}
++
++status_t SimplePlayer::onStart() {
++ CHECK_EQ(mState, STOPPED);
++
++ mStartTimeRealUs = -1ll;
++
++ sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id());
++ msg->setInt32("generation", ++mDoMoreStuffGeneration);
++ msg->post();
++
++ return OK;
++}
++
++status_t SimplePlayer::onStop() {
++ CHECK_EQ(mState, STARTED);
++
++ ++mDoMoreStuffGeneration;
++
++ return OK;
++}
++
++status_t SimplePlayer::onReset() {
++ CHECK_EQ(mState, STOPPED);
++
++ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
++ CodecState *state = &mStateByTrackIndex.editValueAt(i);
++
++ CHECK_EQ(state->mCodec->release(), (status_t)OK);
++ }
++
++ mStartTimeRealUs = -1ll;
++
++ mStateByTrackIndex.clear();
++ mCodecLooper.clear();
++ mExtractor.clear();
++ mNativeWindow.clear();
++ mPath.clear();
++
++ return OK;
++}
++
++status_t SimplePlayer::onDoMoreStuff() {
++ ALOGV("onDoMoreStuff");
++ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
++ CodecState *state = &mStateByTrackIndex.editValueAt(i);
++
++ status_t err;
++ do {
++ size_t index;
++#ifdef USE_MEDIA_CODEC_LAYER
++ err = media_codec_dequeue_input_buffer(state->mCodecDelegate, &index, 0ll);
++#else
++ err = state->mCodec->dequeueInputBuffer(&index);
++#endif
++
++ if (err == OK) {
++ ALOGD("dequeued input buffer on track %d",
++ mStateByTrackIndex.keyAt(i));
++
++ state->mAvailInputBufferIndices.push_back(index);
++ } else {
++ ALOGD("dequeueInputBuffer on track %d returned %d",
++ mStateByTrackIndex.keyAt(i), err);
++ }
++ } while (err == OK);
++
++ do {
++#ifdef USE_MEDIA_CODEC_LAYER
++ BufferInfo info;
++ MediaCodecBufferInfo bufInfo;
++ err = media_codec_dequeue_output_buffer(
++ state->mCodecDelegate,
++ &bufInfo,
++ 0ll);
++
++ info.mIndex = bufInfo.index;
++ info.mOffset = bufInfo.offset;
++ info.mSize = bufInfo.size;
++ info.mPresentationTimeUs = bufInfo.presentation_time_us;
++ info.mFlags = bufInfo.flags;
++
++#else
++ BufferInfo info;
++ err = state->mCodec->dequeueOutputBuffer(
++ &info.mIndex,
++ &info.mOffset,
++ &info.mSize,
++ &info.mPresentationTimeUs,
++ &info.mFlags);
++#endif
++
++ if (err == OK) {
++ ALOGV("dequeued output buffer on track %d",
++ mStateByTrackIndex.keyAt(i));
++
++ state->mAvailOutputBufferInfos.push_back(info);
++ } else if (err == INFO_FORMAT_CHANGED) {
++ err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state);
++ CHECK_EQ(err, (status_t)OK);
++ } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
++ err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
++ CHECK_EQ(err, (status_t)OK);
++ } else {
++ ALOGV("dequeueOutputBuffer on track %d returned %d",
++ mStateByTrackIndex.keyAt(i), err);
++ }
++ } while (err == OK
++ || err == INFO_FORMAT_CHANGED
++ || err == INFO_OUTPUT_BUFFERS_CHANGED);
++ }
++
++ for (;;) {
++ size_t trackIndex;
++ status_t err = mExtractor->getSampleTrackIndex(&trackIndex);
++
++ if (err != OK) {
++ ALOGI("encountered input EOS.");
++ break;
++ } else {
++ CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex);
++
++ if (state->mAvailInputBufferIndices.empty()) {
++ break;
++ }
++
++ size_t index = *state->mAvailInputBufferIndices.begin();
++ state->mAvailInputBufferIndices.erase(
++ state->mAvailInputBufferIndices.begin());
++
++ const sp<ABuffer> &dstBuffer =
++ state->mBuffers[0].itemAt(index);
++
++ err = mExtractor->readSampleData(dstBuffer);
++ CHECK_EQ(err, (status_t)OK);
++
++ int64_t timeUs;
++ CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK);
++
++#ifdef USE_MEDIA_CODEC_LAYER
++ MediaCodecBufferInfo bufInfo;
++ bufInfo.index = index;
++ bufInfo.offset = dstBuffer->offset();
++ bufInfo.size = dstBuffer->size();
++ bufInfo.presentation_time_us = timeUs;
++ bufInfo.flags = 0;
++
++ err = media_codec_queue_input_buffer(
++ state->mCodecDelegate,
++ &bufInfo);
++
++#else
++ err = state->mCodec->queueInputBuffer(
++ index,
++ dstBuffer->offset(),
++ dstBuffer->size(),
++ timeUs,
++ 0);
++#endif
++ CHECK_EQ(err, (status_t)OK);
++
++ ALOGV("enqueued input data on track %d", trackIndex);
++
++ err = mExtractor->advance();
++ CHECK_EQ(err, (status_t)OK);
++ }
++ }
++
++ int64_t nowUs = ALooper::GetNowUs();
++
++ if (mStartTimeRealUs < 0ll) {
++ mStartTimeRealUs = nowUs + 1000000ll;
++ }
++
++ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
++ CodecState *state = &mStateByTrackIndex.editValueAt(i);
++
++ while (!state->mAvailOutputBufferInfos.empty()) {
++ BufferInfo *info = &*state->mAvailOutputBufferInfos.begin();
++
++ int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs;
++ int64_t lateByUs = nowUs - whenRealUs;
++
++ if (lateByUs > -10000ll) {
++ bool release = true;
++
++ if (lateByUs > 30000ll) {
++ ALOGI("track %d buffer late by %lld us, dropping.",
++ mStateByTrackIndex.keyAt(i), lateByUs);
++ state->mCodec->releaseOutputBuffer(info->mIndex);
++ } else {
++ if (state->mAudioTrack != NULL) {
++ const sp<ABuffer> &srcBuffer =
++ state->mBuffers[1].itemAt(info->mIndex);
++
++ renderAudio(state, info, srcBuffer);
++
++ if (info->mSize > 0) {
++ release = false;
++ }
++ }
++
++ if (release) {
++#ifdef USE_MEDIA_CODEC_LAYER
++ ALOGD("Rendering output buffer index %d and releasing", info->mIndex);
++ state->mCodec->renderOutputBufferAndRelease(
++ info->mIndex);
++#else
++ ALOGD("Releasing output buffer index %d", info->mIndex);
++ state->mCodec->releaseOutputBuffer(info->mIndex);
++#endif
++ }
++ }
++
++ if (release) {
++ state->mAvailOutputBufferInfos.erase(
++ state->mAvailOutputBufferInfos.begin());
++
++ info = NULL;
++ } else {
++ break;
++ }
++ } else {
++ ALOGV("track %d buffer early by %lld us.",
++ mStateByTrackIndex.keyAt(i), -lateByUs);
++ break;
++ }
++ }
++ }
++
++ return OK;
++}
++
++status_t SimplePlayer::onOutputFormatChanged(
++ size_t trackIndex, CodecState *state) {
++ sp<AMessage> format;
++ status_t err = state->mCodec->getOutputFormat(&format);
++
++ if (err != OK) {
++ return err;
++ }
++
++ AString mime;
++ CHECK(format->findString("mime", &mime));
++
++ if (!strncasecmp(mime.c_str(), "audio/", 6)) {
++ int32_t channelCount;
++ int32_t sampleRate;
++ CHECK(format->findInt32("channel-count", &channelCount));
++ CHECK(format->findInt32("sample-rate", &sampleRate));
++
++ state->mAudioTrack = new AudioTrack(
++ AUDIO_STREAM_MUSIC,
++ sampleRate,
++ AUDIO_FORMAT_PCM_16_BIT,
++ audio_channel_out_mask_from_count(channelCount),
++ 0);
++
++ state->mNumFramesWritten = 0;
++ }
++
++ return OK;
++}
++
++void SimplePlayer::renderAudio(
++ CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) {
++ CHECK(state->mAudioTrack != NULL);
++
++ if (state->mAudioTrack->stopped()) {
++ state->mAudioTrack->start();
++ }
++
++ uint32_t numFramesPlayed;
++ CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK);
++
++ uint32_t numFramesAvailableToWrite =
++ state->mAudioTrack->frameCount()
++ - (state->mNumFramesWritten - numFramesPlayed);
++
++ size_t numBytesAvailableToWrite =
++ numFramesAvailableToWrite * state->mAudioTrack->frameSize();
++
++ size_t copy = info->mSize;
++ if (copy > numBytesAvailableToWrite) {
++ copy = numBytesAvailableToWrite;
++ }
++
++ if (copy == 0) {
++ return;
++ }
++
++ int64_t startTimeUs = ALooper::GetNowUs();
++
++ ssize_t nbytes = state->mAudioTrack->write(
++ buffer->base() + info->mOffset, copy);
++
++ CHECK_EQ(nbytes, (ssize_t)copy);
++
++ int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
++
++ uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize();
++
++ if (delayUs > 2000ll) {
++ ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, "
++ "numFramesWritten=%u",
++ delayUs, numFramesAvailableToWrite, numFramesWritten);
++ }
++
++ info->mOffset += nbytes;
++ info->mSize -= nbytes;
++
++ state->mNumFramesWritten += numFramesWritten;
++}
++
++} // namespace android
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/SimplePlayer.h
+@@ -0,0 +1,120 @@
++/*
++ * Copyright (C) 2012 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#include <media/stagefright/foundation/AHandler.h>
++#include <media/stagefright/foundation/AString.h>
++#include <utils/KeyedVector.h>
++
++#include <hybris/media/media_codec_layer.h>
++
++namespace android {
++
++struct ABuffer;
++struct ALooper;
++struct AudioTrack;
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++struct ISurfaceTexture;
++#else
++struct IGraphicBufferProducer;
++#endif
++struct MediaCodec;
++struct NativeWindowWrapper;
++struct NuMediaExtractor;
++
++struct SimplePlayer : public AHandler {
++ SimplePlayer();
++
++ status_t setDataSource(const char *path);
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ status_t setSurface(const sp<ISurfaceTexture> &surfaceTexture);
++#else
++ status_t setSurface(const sp<IGraphicBufferProducer> &surfaceTexture);
++#endif
++ status_t prepare();
++ status_t start();
++ status_t stop();
++ status_t reset();
++
++protected:
++ virtual ~SimplePlayer();
++
++ virtual void onMessageReceived(const sp<AMessage> &msg);
++
++private:
++ enum State {
++ UNINITIALIZED,
++ UNPREPARED,
++ STOPPED,
++ STARTED
++ };
++
++ enum {
++ kWhatSetDataSource,
++ kWhatSetSurface,
++ kWhatPrepare,
++ kWhatStart,
++ kWhatStop,
++ kWhatReset,
++ kWhatDoMoreStuff,
++ };
++
++ struct BufferInfo {
++ size_t mIndex;
++ size_t mOffset;
++ size_t mSize;
++ int64_t mPresentationTimeUs;
++ uint32_t mFlags;
++ };
++
++ struct CodecState
++ {
++ sp<MediaCodec> mCodec;
++ MediaCodecDelegate mCodecDelegate;
++ Vector<sp<ABuffer> > mCSD;
++ Vector<sp<ABuffer> > mBuffers[2];
++
++ List<size_t> mAvailInputBufferIndices;
++ List<BufferInfo> mAvailOutputBufferInfos;
++
++ sp<AudioTrack> mAudioTrack;
++ uint32_t mNumFramesWritten;
++ };
++
++ State mState;
++ AString mPath;
++ sp<NativeWindowWrapper> mNativeWindow;
++
++ sp<NuMediaExtractor> mExtractor;
++ sp<ALooper> mCodecLooper;
++ KeyedVector<size_t, CodecState> mStateByTrackIndex;
++ int32_t mDoMoreStuffGeneration;
++
++ int64_t mStartTimeRealUs;
++
++ status_t onPrepare();
++ status_t onStart();
++ status_t onStop();
++ status_t onReset();
++ status_t onDoMoreStuff();
++ status_t onOutputFormatChanged(size_t trackIndex, CodecState *state);
++
++ void renderAudio(
++ CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer);
++
++ DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer);
++};
++
++} // namespace android
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/codec.cpp
+@@ -0,0 +1,433 @@
++/*
++ * Copyright (C) 2012 The Android Open Source Project
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#define LOG_NDEBUG 0
++#define LOG_TAG "codec"
++#include <utils/Log.h>
++
++#include "SimplePlayer.h"
++
++#include <binder/IServiceManager.h>
++#include <binder/ProcessState.h>
++#include <media/ICrypto.h>
++#include <media/IMediaPlayerService.h>
++#include <media/stagefright/foundation/ABuffer.h>
++#include <media/stagefright/foundation/ADebug.h>
++#include <media/stagefright/foundation/ALooper.h>
++#include <media/stagefright/foundation/AMessage.h>
++#include <media/stagefright/foundation/AString.h>
++#include <media/stagefright/DataSource.h>
++#include <media/stagefright/MediaCodec.h>
++#include <media/stagefright/MediaCodecList.h>
++#include <media/stagefright/MediaDefs.h>
++#include <media/stagefright/NuMediaExtractor.h>
++#include <gui/ISurfaceComposer.h>
++#include <gui/SurfaceComposerClient.h>
++#include <ui/DisplayInfo.h>
++
++static void usage(const char *me) {
++ fprintf(stderr, "usage: %s [-a] use audio\n"
++ "\t\t[-v] use video\n"
++ "\t\t[-p] playback\n"
++ "\t\t[-S] allocate buffers from a surface\n",
++ me);
++
++ exit(1);
++}
++
++namespace android {
++
++struct CodecState {
++ sp<MediaCodec> mCodec;
++ Vector<sp<ABuffer> > mInBuffers;
++ Vector<sp<ABuffer> > mOutBuffers;
++ bool mSignalledInputEOS;
++ bool mSawOutputEOS;
++ int64_t mNumBuffersDecoded;
++ int64_t mNumBytesDecoded;
++ bool mIsAudio;
++};
++
++} // namespace android
++
++static int decode(
++ const android::sp<android::ALooper> &looper,
++ const char *path,
++ bool useAudio,
++ bool useVideo,
++ const android::sp<android::Surface> &surface) {
++ using namespace android;
++
++ static int64_t kTimeout = 500ll;
++
++ sp<NuMediaExtractor> extractor = new NuMediaExtractor;
++ if (extractor->setDataSource(path) != OK) {
++ fprintf(stderr, "unable to instantiate extractor.\n");
++ return 1;
++ }
++
++ KeyedVector<size_t, CodecState> stateByTrack;
++
++ bool haveAudio = false;
++ bool haveVideo = false;
++ for (size_t i = 0; i < extractor->countTracks(); ++i) {
++ sp<AMessage> format;
++ status_t err = extractor->getTrackFormat(i, &format);
++ CHECK_EQ(err, (status_t)OK);
++
++ AString mime;
++ CHECK(format->findString("mime", &mime));
++
++ bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6);
++ bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
++
++ if (useAudio && !haveAudio && isAudio) {
++ haveAudio = true;
++ } else if (useVideo && !haveVideo && isVideo) {
++ haveVideo = true;
++ } else {
++ continue;
++ }
++
++ ALOGV("selecting track %d", i);
++
++ err = extractor->selectTrack(i);
++ CHECK_EQ(err, (status_t)OK);
++
++ CodecState *state =
++ &stateByTrack.editValueAt(stateByTrack.add(i, CodecState()));
++
++ state->mNumBytesDecoded = 0;
++ state->mNumBuffersDecoded = 0;
++ state->mIsAudio = isAudio;
++
++ state->mCodec = MediaCodec::CreateByType(
++ looper, mime.c_str(), false /* encoder */);
++
++ CHECK(state->mCodec != NULL);
++
++ err = state->mCodec->configure(
++ format, isVideo ? surface : NULL,
++ NULL /* crypto */,
++ 0 /* flags */);
++
++ CHECK_EQ(err, (status_t)OK);
++
++ state->mSignalledInputEOS = false;
++ state->mSawOutputEOS = false;
++ }
++
++ CHECK(!stateByTrack.isEmpty());
++
++ int64_t startTimeUs = ALooper::GetNowUs();
++
++ for (size_t i = 0; i < stateByTrack.size(); ++i) {
++ CodecState *state = &stateByTrack.editValueAt(i);
++
++ sp<MediaCodec> codec = state->mCodec;
++
++ CHECK_EQ((status_t)OK, codec->start());
++
++ CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers));
++ CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers));
++
++ ALOGV("got %d input and %d output buffers",
++ state->mInBuffers.size(), state->mOutBuffers.size());
++ }
++
++ bool sawInputEOS = false;
++
++ for (;;) {
++ if (!sawInputEOS) {
++ size_t trackIndex;
++ status_t err = extractor->getSampleTrackIndex(&trackIndex);
++
++ if (err != OK) {
++ ALOGV("saw input eos");
++ sawInputEOS = true;
++ } else {
++ CodecState *state = &stateByTrack.editValueFor(trackIndex);
++
++ size_t index;
++ err = state->mCodec->dequeueInputBuffer(&index, kTimeout);
++
++ if (err == OK) {
++ ALOGV("filling input buffer %d", index);
++
++ const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index);
++
++ err = extractor->readSampleData(buffer);
++ CHECK_EQ(err, (status_t)OK);
++
++ int64_t timeUs;
++ err = extractor->getSampleTime(&timeUs);
++ CHECK_EQ(err, (status_t)OK);
++
++ uint32_t bufferFlags = 0;
++
++ err = state->mCodec->queueInputBuffer(
++ index,
++ 0 /* offset */,
++ buffer->size(),
++ timeUs,
++ bufferFlags);
++
++ CHECK_EQ(err, (status_t)OK);
++
++ extractor->advance();
++ } else {
++ CHECK_EQ(err, -EAGAIN);
++ }
++ }
++ } else {
++ for (size_t i = 0; i < stateByTrack.size(); ++i) {
++ CodecState *state = &stateByTrack.editValueAt(i);
++
++ if (!state->mSignalledInputEOS) {
++ size_t index;
++ status_t err =
++ state->mCodec->dequeueInputBuffer(&index, kTimeout);
++
++ if (err == OK) {
++ ALOGV("signalling input EOS on track %d", i);
++
++ err = state->mCodec->queueInputBuffer(
++ index,
++ 0 /* offset */,
++ 0 /* size */,
++ 0ll /* timeUs */,
++ MediaCodec::BUFFER_FLAG_EOS);
++
++ CHECK_EQ(err, (status_t)OK);
++
++ state->mSignalledInputEOS = true;
++ } else {
++ CHECK_EQ(err, -EAGAIN);
++ }
++ }
++ }
++ }
++
++ bool sawOutputEOSOnAllTracks = true;
++ for (size_t i = 0; i < stateByTrack.size(); ++i) {
++ CodecState *state = &stateByTrack.editValueAt(i);
++ if (!state->mSawOutputEOS) {
++ sawOutputEOSOnAllTracks = false;
++ break;
++ }
++ }
++
++ if (sawOutputEOSOnAllTracks) {
++ break;
++ }
++
++ for (size_t i = 0; i < stateByTrack.size(); ++i) {
++ CodecState *state = &stateByTrack.editValueAt(i);
++
++ if (state->mSawOutputEOS) {
++ continue;
++ }
++
++ size_t index;
++ size_t offset;
++ size_t size;
++ int64_t presentationTimeUs;
++ uint32_t flags;
++ status_t err = state->mCodec->dequeueOutputBuffer(
++ &index, &offset, &size, &presentationTimeUs, &flags,
++ kTimeout);
++
++ if (err == OK) {
++ ALOGV("draining output buffer %d, time = %lld us",
++ index, presentationTimeUs);
++
++ ++state->mNumBuffersDecoded;
++ state->mNumBytesDecoded += size;
++
++ err = state->mCodec->releaseOutputBuffer(index);
++ CHECK_EQ(err, (status_t)OK);
++
++ if (flags & MediaCodec::BUFFER_FLAG_EOS) {
++ ALOGV("reached EOS on output.");
++
++ state->mSawOutputEOS = true;
++ }
++ } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
++ ALOGV("INFO_OUTPUT_BUFFERS_CHANGED");
++ CHECK_EQ((status_t)OK,
++ state->mCodec->getOutputBuffers(&state->mOutBuffers));
++
++ ALOGV("got %d output buffers", state->mOutBuffers.size());
++ } else if (err == INFO_FORMAT_CHANGED) {
++ sp<AMessage> format;
++ CHECK_EQ((status_t)OK, state->mCodec->getOutputFormat(&format));
++
++ ALOGV("INFO_FORMAT_CHANGED: %s", format->debugString().c_str());
++ } else {
++ CHECK_EQ(err, -EAGAIN);
++ }
++ }
++ }
++
++ int64_t elapsedTimeUs = ALooper::GetNowUs() - startTimeUs;
++
++ for (size_t i = 0; i < stateByTrack.size(); ++i) {
++ CodecState *state = &stateByTrack.editValueAt(i);
++
++ CHECK_EQ((status_t)OK, state->mCodec->release());
++
++ if (state->mIsAudio) {
++ ALOGD("track %d: %lld bytes received. %.2f KB/sec\n",
++ i,
++ state->mNumBytesDecoded,
++ state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
++ } else {
++ ALOGD("track %d: %lld frames decoded, %.2f fps. %lld bytes "
++ "received. %.2f KB/sec\n",
++ i,
++ state->mNumBuffersDecoded,
++ state->mNumBuffersDecoded * 1E6 / elapsedTimeUs,
++ state->mNumBytesDecoded,
++ state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
++ }
++ }
++
++ return 0;
++}
++
++int main(int argc, char **argv) {
++ using namespace android;
++
++ const char *me = argv[0];
++
++ bool useAudio = false;
++ bool useVideo = false;
++ bool playback = false;
++ bool useSurface = false;
++
++ int res;
++ while ((res = getopt(argc, argv, "havpSD")) >= 0) {
++ switch (res) {
++ case 'a':
++ {
++ useAudio = true;
++ break;
++ }
++
++ case 'v':
++ {
++ useVideo = true;
++ break;
++ }
++
++ case 'p':
++ {
++ playback = true;
++ break;
++ }
++
++ case 'S':
++ {
++ useSurface = true;
++ break;
++ }
++
++ case '?':
++ case 'h':
++ default:
++ {
++ usage(me);
++ }
++ }
++ }
++
++ argc -= optind;
++ argv += optind;
++
++ if (argc != 1) {
++ usage(me);
++ }
++
++ if (!useAudio && !useVideo) {
++ useAudio = useVideo = true;
++ }
++
++ ProcessState::self()->startThreadPool();
++
++ DataSource::RegisterDefaultSniffers();
++
++ sp<ALooper> looper = new ALooper;
++ looper->start();
++
++ sp<SurfaceComposerClient> composerClient;
++ sp<SurfaceControl> control;
++ sp<Surface> surface;
++
++ if (playback || (useSurface && useVideo)) {
++ composerClient = new SurfaceComposerClient;
++ CHECK_EQ(composerClient->initCheck(), (status_t)OK);
++
++ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
++ ISurfaceComposer::eDisplayIdMain));
++ DisplayInfo info;
++ SurfaceComposerClient::getDisplayInfo(display, &info);
++ ssize_t displayWidth = info.w;
++ ssize_t displayHeight = info.h;
++
++ ALOGV("display is %ld x %ld\n", displayWidth, displayHeight);
++
++ control = composerClient->createSurface(
++ String8("A Surface"),
++ displayWidth,
++ displayHeight,
++ PIXEL_FORMAT_RGB_565,
++ 0);
++
++ CHECK(control != NULL);
++ CHECK(control->isValid());
++
++ SurfaceComposerClient::openGlobalTransaction();
++ CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
++ CHECK_EQ(control->show(), (status_t)OK);
++ SurfaceComposerClient::closeGlobalTransaction();
++
++ surface = control->getSurface();
++ CHECK(surface != NULL);
++ }
++
++ if (playback) {
++ sp<SimplePlayer> player = new SimplePlayer;
++ looper->registerHandler(player);
++
++ player->setDataSource(argv[0]);
++ player->setSurface(surface->getSurfaceTexture());
++ player->start();
++ ALOGD("Playing for 60 seconds\n");
++ sleep(60);
++ player->stop();
++ player->reset();
++ } else {
++ decode(looper, argv[0], useAudio, useVideo, surface);
++ }
++
++ if (playback || (useSurface && useVideo)) {
++ composerClient->dispose();
++ }
++
++ looper->stop();
++
++ return 0;
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/direct_media_test.cpp
+@@ -0,0 +1,417 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
++ */
++
++#include <hybris/media/media_compatibility_layer.h>
++#include "direct_media_test.h"
++
++#include <utils/Errors.h>
++
++#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h>
++
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <fcntl.h>
++#include <unistd.h>
++
++#include <cassert>
++#include <cstdio>
++#include <cstdlib>
++#include <cstring>
++
++using namespace android;
++
++static float DestWidth = 0.0, DestHeight = 0.0;
++// Actual video dimmensions
++static int Width = 0, Height = 0;
++
++static GLfloat positionCoordinates[8];
++
++MediaPlayerWrapper *player = NULL;
++
++void calculate_position_coordinates()
++{
++ // Assuming cropping output for now
++ float x = 1, y = 1;
++
++ // Black borders
++ x = float(Width / DestWidth);
++ y = float(Height / DestHeight);
++
++ // Make the larger side be 1
++ if (x > y) {
++ y /= x;
++ x = 1;
++ } else {
++ x /= y;
++ y = 1;
++ }
++
++ positionCoordinates[0] = -x;
++ positionCoordinates[1] = y;
++ positionCoordinates[2] = -x;
++ positionCoordinates[3] = -y;
++ positionCoordinates[4] = x;
++ positionCoordinates[5] = -y;
++ positionCoordinates[6] = x;
++ positionCoordinates[7] = y;
++}
++
++WindowRenderer::WindowRenderer(int width, int height)
++ : mThreadCmd(CMD_IDLE)
++{
++ createThread(threadStart, this);
++}
++
++WindowRenderer::~WindowRenderer()
++{
++}
++
++int WindowRenderer::threadStart(void* self)
++{
++ ((WindowRenderer *)self)->glThread();
++ return 0;
++}
++
++void WindowRenderer::glThread()
++{
++ printf("%s\n", __PRETTY_FUNCTION__);
++
++ Mutex::Autolock autoLock(mLock);
++}
++
++struct ClientWithSurface
++{
++ SfClient* client;
++ SfSurface* surface;
++};
++
++ClientWithSurface client_with_surface(bool setup_surface_with_egl)
++{
++ ClientWithSurface cs = ClientWithSurface();
++
++ cs.client = sf_client_create();
++
++ if (!cs.client) {
++ printf("Problem creating client ... aborting now.");
++ return cs;
++ }
++
++ static const size_t primary_display = 0;
++
++ DestWidth = sf_get_display_width(primary_display);
++ DestHeight = sf_get_display_height(primary_display);
++ printf("Primary display width: %f, height: %f\n", DestWidth, DestHeight);
++
++ SfSurfaceCreationParameters params = {
++ 0,
++ 0,
++ (int) DestWidth,
++ (int) DestHeight,
++ -1, //PIXEL_FORMAT_RGBA_8888,
++ 15000,
++ 0.5f,
++ setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL
++ "MediaCompatLayerTestSurface"
++ };
++
++ cs.surface = sf_surface_create(cs.client, ¶ms);
++
++ if (!cs.surface) {
++ printf("Problem creating surface ... aborting now.");
++ return cs;
++ }
++
++ sf_surface_make_current(cs.surface);
++
++ return cs;
++}
++
++struct RenderData
++{
++ static const char *vertex_shader()
++ {
++ return
++ "attribute vec4 a_position; \n"
++ "attribute vec2 a_texCoord; \n"
++ "uniform mat4 m_texMatrix; \n"
++ "varying vec2 v_texCoord; \n"
++ "varying float topDown; \n"
++ "void main() \n"
++ "{ \n"
++ " gl_Position = a_position; \n"
++ " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n"
++ "} \n";
++ }
++
++ static const char *fragment_shader()
++ {
++ return
++ "#extension GL_OES_EGL_image_external : require \n"
++ "precision mediump float; \n"
++ "varying vec2 v_texCoord; \n"
++ "uniform samplerExternalOES s_texture; \n"
++ "void main() \n"
++ "{ \n"
++ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
++ "} \n";
++ }
++
++ static GLuint loadShader(GLenum shaderType, const char* pSource)
++ {
++ GLuint shader = glCreateShader(shaderType);
++
++ if (shader) {
++ glShaderSource(shader, 1, &pSource, NULL);
++ glCompileShader(shader);
++ GLint compiled = 0;
++ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
++
++ if (!compiled) {
++ GLint infoLen = 0;
++ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
++ if (infoLen) {
++ char* buf = (char*) malloc(infoLen);
++ if (buf) {
++ glGetShaderInfoLog(shader, infoLen, NULL, buf);
++ fprintf(stderr, "Could not compile shader %d:\n%s\n",
++ shaderType, buf);
++ free(buf);
++ }
++ glDeleteShader(shader);
++ shader = 0;
++ }
++ }
++ } else {
++ printf("Error, during shader creation: %i\n", glGetError());
++ }
++
++ return shader;
++ }
++
++ static GLuint create_program(const char* pVertexSource, const char* pFragmentSource)
++ {
++ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
++ if (!vertexShader) {
++ printf("vertex shader not compiled\n");
++ return 0;
++ }
++
++ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
++ if (!pixelShader) {
++ printf("frag shader not compiled\n");
++ return 0;
++ }
++
++ GLuint program = glCreateProgram();
++ if (program) {
++ glAttachShader(program, vertexShader);
++ glAttachShader(program, pixelShader);
++ glLinkProgram(program);
++ GLint linkStatus = GL_FALSE;
++ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
++
++ if (linkStatus != GL_TRUE) {
++ GLint bufLength = 0;
++ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
++ if (bufLength) {
++ char* buf = (char*) malloc(bufLength);
++ if (buf) {
++ glGetProgramInfoLog(program, bufLength, NULL, buf);
++ fprintf(stderr, "Could not link program:\n%s\n", buf);
++ free(buf);
++ }
++ }
++ glDeleteProgram(program);
++ program = 0;
++ }
++ }
++
++ return program;
++ }
++
++ RenderData() : program_object(create_program(vertex_shader(), fragment_shader()))
++ {
++ position_loc = glGetAttribLocation(program_object, "a_position");
++ tex_coord_loc = glGetAttribLocation(program_object, "a_texCoord");
++ sampler_loc = glGetUniformLocation(program_object, "s_texture");
++ matrix_loc = glGetUniformLocation(program_object, "m_texMatrix");
++ }
++
++ // Handle to a program object
++ GLuint program_object;
++ // Attribute locations
++ GLint position_loc;
++ GLint tex_coord_loc;
++ // Sampler location
++ GLint sampler_loc;
++ // Matrix location
++ GLint matrix_loc;
++};
++
++static int setup_video_texture(ClientWithSurface *cs, GLuint *preview_texture_id)
++{
++ assert(cs != NULL);
++ assert(preview_texture_id != NULL);
++
++ sf_surface_make_current(cs->surface);
++
++ glGenTextures(1, preview_texture_id);
++ glClearColor(0, 0, 0, 0);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++
++ android_media_set_preview_texture(player, *preview_texture_id);
++
++ return 0;
++}
++
++static void print_gl_error(unsigned int line)
++{
++ GLint error = glGetError();
++ printf("GL error: %#04x (line: %d)\n", error, line);
++}
++
++static int update_gl_buffer(RenderData *render_data, EGLDisplay *disp, EGLSurface *surface)
++{
++ assert(disp != NULL);
++ assert(surface != NULL);
++
++ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
++
++ const GLfloat textureCoordinates[] = {
++ 1.0f, 1.0f,
++ 0.0f, 1.0f,
++ 0.0f, 0.0f,
++ 1.0f, 0.0f
++ };
++
++ calculate_position_coordinates();
++
++ glClear(GL_COLOR_BUFFER_BIT);
++ // Use the program object
++ glUseProgram(render_data->program_object);
++ // Enable attributes
++ glEnableVertexAttribArray(render_data->position_loc);
++ glEnableVertexAttribArray(render_data->tex_coord_loc);
++ // Load the vertex position
++ glVertexAttribPointer(render_data->position_loc,
++ 2,
++ GL_FLOAT,
++ GL_FALSE,
++ 0,
++ positionCoordinates);
++ // Load the texture coordinate
++ glVertexAttribPointer(render_data->tex_coord_loc,
++ 2,
++ GL_FLOAT,
++ GL_FALSE,
++ 0,
++ textureCoordinates);
++
++ GLfloat matrix[16];
++ android_media_surface_texture_get_transformation_matrix(player, matrix);
++
++ glUniformMatrix4fv(render_data->matrix_loc, 1, GL_FALSE, matrix);
++
++ glActiveTexture(GL_TEXTURE0);
++ // Set the sampler texture unit to 0
++ glUniform1i(render_data->sampler_loc, 0);
++ glUniform1i(render_data->matrix_loc, 0);
++ android_media_update_surface_texture(player);
++ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
++ //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
++ glDisableVertexAttribArray(render_data->position_loc);
++ glDisableVertexAttribArray(render_data->tex_coord_loc);
++
++ eglSwapBuffers(*disp, *surface);
++
++ return 0;
++}
++
++void set_video_size_cb(int height, int width, void *context)
++{
++ printf("Video height: %d, width: %d\n", height, width);
++ printf("Video dest height: %f, width: %f\n", DestHeight, DestWidth);
++
++ Height = height;
++ Width = width;
++}
++
++int main(int argc, char **argv)
++{
++ if (argc < 2) {
++ printf("Usage: direct_media_test <video_to_play>\n");
++ return EXIT_FAILURE;
++ }
++
++ player = android_media_new_player();
++ if (player == NULL) {
++ printf("Problem creating new media player.\n");
++ return EXIT_FAILURE;
++ }
++
++ // Set player event cb for when the video size is known:
++ android_media_set_video_size_cb(player, set_video_size_cb, NULL);
++
++ printf("Setting data source to: %s.\n", argv[1]);
++
++ if (android_media_set_data_source(player, argv[1]) != OK) {
++ printf("Failed to set data source: %s\n", argv[1]);
++ return EXIT_FAILURE;
++ }
++
++ WindowRenderer renderer(DestWidth, DestHeight);
++
++ printf("Creating EGL surface.\n");
++ ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */);
++ if (!cs.surface) {
++ printf("Problem acquiring surface for preview");
++ return EXIT_FAILURE;
++ }
++
++ printf("Creating GL texture.\n");
++ GLuint preview_texture_id;
++ EGLDisplay disp = sf_client_get_egl_display(cs.client);
++ EGLSurface surface = sf_surface_get_egl_surface(cs.surface);
++
++ sf_surface_make_current(cs.surface);
++ if (setup_video_texture(&cs, &preview_texture_id) != OK) {
++ printf("Problem setting up GL texture for video surface.\n");
++ return EXIT_FAILURE;
++ }
++
++ RenderData render_data;
++
++ printf("Starting video playback.\n");
++ android_media_play(player);
++
++ printf("Updating gl buffer continuously...\n");
++ while (android_media_is_playing(player)) {
++ update_gl_buffer(&render_data, &disp, &surface);
++ }
++
++ android_media_stop(player);
++
++ return EXIT_SUCCESS;
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/direct_media_test.h
+@@ -0,0 +1,58 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#ifndef DIRECT_MEDIA_TEST_H_
++#define DIRECT_MEDIA_TEST_H_
++
++#include <EGL/egl.h>
++#include <GLES2/gl2.h>
++#include <utils/threads.h>
++
++namespace android {
++
++class RenderInput;
++
++class WindowRenderer
++{
++public:
++ WindowRenderer(int width, int height);
++ ~WindowRenderer();
++
++private:
++ // The GL thread functions
++ static int threadStart(void* self);
++ void glThread();
++
++ // These variables are used to communicate between the GL thread and
++ // other threads.
++ Mutex mLock;
++ Condition mCond;
++ enum {
++ CMD_IDLE,
++ CMD_RENDER_INPUT,
++ CMD_RESERVE_TEXTURE,
++ CMD_DELETE_TEXTURE,
++ CMD_QUIT,
++ };
++ int mThreadCmd;
++ RenderInput* mThreadRenderInput;
++ GLuint mThreadTextureId;
++};
++} // android
++
++#endif
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_codec_layer.cpp
+@@ -0,0 +1,763 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++// Uncomment to enable verbose debug output
++#define LOG_NDEBUG 0
++
++#undef LOG_TAG
++#define LOG_TAG "MediaCodecLayer"
++
++#include <hybris/media/media_codec_layer.h>
++#include <hybris/media/media_compatibility_layer.h>
++#include <hybris/media/media_format_layer.h>
++
++#include "media_format_layer_priv.h"
++#include "surface_texture_client_hybris_priv.h"
++
++#include <fcntl.h>
++#include <sys/stat.h>
++
++#include <binder/ProcessState.h>
++
++#include <media/stagefright/foundation/AHandler.h>
++#include <media/stagefright/foundation/AString.h>
++#include <media/ICrypto.h>
++#include <media/stagefright/foundation/ABuffer.h>
++#include <media/stagefright/foundation/ADebug.h>
++#include <media/stagefright/foundation/AMessage.h>
++#include <media/stagefright/MediaCodec.h>
++#include <media/stagefright/MediaErrors.h>
++#include <media/stagefright/NativeWindowWrapper.h>
++
++#include <utils/Vector.h>
++#include <utils/Log.h>
++#include <utils/RefBase.h>
++
++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__);
++
++using namespace android;
++
++struct _MediaCodecDelegate : public AHandler
++{
++public:
++ typedef sp<_MediaCodecDelegate> Ptr;
++
++ explicit _MediaCodecDelegate(void *context);
++ virtual ~_MediaCodecDelegate();
++
++protected:
++ virtual void onMessageReceived(const sp<AMessage> &msg) { }
++
++public:
++ sp<MediaCodec> media_codec;
++ sp<ALooper> looper;
++
++ Vector<sp<ABuffer> > input_buffers;
++ Vector<sp<ABuffer> > output_buffers;
++ List<MediaCodecBufferInfo> available_output_buffer_infos;
++ List<size_t> available_input_buffer_indices;
++ bool output_format_changed;
++ bool hardware_rendering;
++
++ void *context;
++ unsigned int refcount;
++};
++
++_MediaCodecDelegate::_MediaCodecDelegate(void *context)
++ : output_format_changed(false),
++ hardware_rendering(false),
++ context(context),
++ refcount(1)
++{
++ REPORT_FUNCTION()
++}
++
++_MediaCodecDelegate::~_MediaCodecDelegate()
++{
++ REPORT_FUNCTION()
++}
++
++static inline _MediaCodecDelegate *get_internal_delegate(MediaCodecDelegate delegate)
++{
++ if (delegate == NULL)
++ {
++ ALOGE("delegate must not be NULL");
++ return NULL;
++ }
++
++ _MediaCodecDelegate *d = static_cast<_MediaCodecDelegate*>(delegate);
++ // Some simple sanity checks that must be true for a valid MediaCodecDelegate instance
++ if (d->media_codec == NULL || d->refcount < 1)
++ return NULL;
++
++ return d;
++}
++
++MediaCodecDelegate media_codec_create_by_codec_name(const char *name)
++{
++ REPORT_FUNCTION()
++
++ if (name == NULL)
++ {
++ ALOGE("name must not be NULL");
++ return NULL;
++ }
++
++ ALOGD("Creating codec '%s'", name);
++
++ ProcessState::self()->startThreadPool();
++
++ _MediaCodecDelegate *d(new _MediaCodecDelegate(NULL));
++ d->looper = new ALooper;
++ d->looper->start();
++
++ d->media_codec = android::MediaCodec::CreateByComponentName(d->looper, name);
++
++ return d;
++}
++
++#ifdef SIMPLE_PLAYER
++MediaCodec* media_codec_get(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return NULL;
++
++ return d->media_codec.get();
++}
++#endif
++
++MediaCodecDelegate media_codec_create_by_codec_type(const char *type)
++{
++ REPORT_FUNCTION()
++
++ if (type == NULL)
++ {
++ ALOGE("type must not be NULL");
++ return NULL;
++ }
++
++ ALOGD("Creating codec by type '%s'", type);
++
++ ProcessState::self()->startThreadPool();
++
++ _MediaCodecDelegate *d(new _MediaCodecDelegate(NULL));
++ d->looper = new ALooper;
++ d->looper->start();
++
++ d->media_codec = android::MediaCodec::CreateByType(d->looper, type, false);
++
++ return d;
++}
++
++void media_codec_delegate_destroy(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ {
++ ALOGE("d == NULL, cannot destroy MediaCodecDelegate instance");
++ return;
++ }
++
++ ALOGI("Releasing media_codec");
++ d->media_codec->release();
++ ALOGI("Stopping looper");
++ d->looper->stop();
++
++ ALOGI("Setting refcount = 0");
++ d->refcount = 0;
++
++ ALOGI("Deleting the MediaCodecDelegate instance");
++ delete d;
++}
++
++void media_codec_delegate_ref(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return;
++
++ d->refcount++;
++}
++
++void media_codec_delegate_unref(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ {
++ ALOGE("d == NULL, cannot unref MediaCodecDelegate instance");
++ return;
++ }
++
++ if (d->refcount > 1)
++ d->refcount--;
++ else
++ media_codec_delegate_destroy (delegate);
++}
++
++#ifdef SIMPLE_PLAYER
++int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, void *nativeWindow, uint32_t flags)
++#else
++int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, SurfaceTextureClientHybris stc, uint32_t flags)
++#endif
++{
++ REPORT_FUNCTION()
++
++ if (format == NULL)
++ {
++ ALOGE("format must not be NULL");
++ return BAD_VALUE;
++ }
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ _MediaFormat *format_priv = static_cast<_MediaFormat*>(format);
++#ifndef SIMPLE_PLAYER
++ _SurfaceTextureClientHybris *stch = static_cast<_SurfaceTextureClientHybris*>(stc);
++#endif
++
++ sp<AMessage> aformat = new AMessage;
++ aformat->setString("mime", format_priv->mime.c_str());
++ if (format_priv->duration_us > 0)
++ aformat->setInt64("durationUs", format_priv->duration_us);
++ aformat->setInt32("width", format_priv->width);
++ aformat->setInt32("height", format_priv->height);
++ if (format_priv->max_input_size > 0)
++ aformat->setInt32("max-input-size", format_priv->max_input_size);
++
++ ALOGD("Format: %s", aformat->debugString().c_str());
++
++#ifdef SIMPLE_PLAYER
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ sp<SurfaceTextureClient> surfaceTextureClient = static_cast<SurfaceTextureClient*>(nativeWindow);
++#else
++ sp<Surface> surfaceTextureClient = static_cast<Surface*>(nativeWindow);
++#endif
++ // TODO: Don't just pass NULL for the security when DRM is needed
++ d->media_codec->configure(aformat, surfaceTextureClient, NULL, flags);
++#else
++ ALOGD("SurfaceTextureClientHybris: %p", stch);
++
++ // Make sure we're ready to configure the codec and the Surface/SurfaceTextureClient together
++ if (stch != NULL && stch->hardwareRendering() && stch->isReady())
++ {
++ ALOGD("Doing hardware decoding with hardware rendering");
++ // TODO: Don't just pass NULL for the security when DRM is needed
++ d->media_codec->configure(aformat, stch, NULL, flags);
++ }
++ else
++ {
++ ALOGD("Doing hardware decoding path with software rendering");
++ // This scenario is for hardware video decoding, but software rendering, therefore there's
++ // no need to pass a valid Surface/SurfaceTextureClient instance to configure()
++ d->media_codec->configure(aformat, NULL, NULL, flags);
++ }
++
++#endif
++
++ return OK;
++}
++
++int media_codec_set_surface_texture_client(MediaCodecDelegate delegate, SurfaceTextureClientHybris stc)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++ if (stc == NULL)
++ {
++ ALOGE("stc must not be NULL");
++ return BAD_VALUE;
++ }
++
++ _SurfaceTextureClientHybris *stcu = static_cast<_SurfaceTextureClientHybris*>(stc);
++ status_t err = native_window_api_connect(stcu, NATIVE_WINDOW_API_MEDIA);
++ if (err != OK)
++ {
++ ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
++ return err;
++ }
++
++ return OK;
++}
++
++int media_codec_queue_csd(MediaCodecDelegate delegate, MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ if (format == NULL)
++ {
++ ALOGE("format must not be NULL");
++ return BAD_VALUE;
++ }
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ _MediaFormat *format_priv = static_cast<_MediaFormat*>(format);
++ assert(format_priv->csd != NULL);
++
++ status_t err = OK;
++
++ Vector<sp<ABuffer> > input_bufs[1];
++ err = d->media_codec->getInputBuffers(&input_bufs[0]);
++ CHECK_EQ(err, static_cast<status_t>(OK));
++
++ for (size_t i=0; i<2; ++i)
++ {
++ const sp<ABuffer> &srcBuffer = format_priv->csd;
++
++ size_t index = 0;
++ err = d->media_codec->dequeueInputBuffer(&index, -1ll);
++ CHECK_EQ(err, static_cast<status_t>(OK));
++
++ const sp<ABuffer> &dstBuffer = input_bufs[0].itemAt(index);
++
++ CHECK_LE(srcBuffer->size(), dstBuffer->capacity());
++ dstBuffer->setRange(0, srcBuffer->size());
++ memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size());
++
++ AString err_msg;
++ err = d->media_codec->queueInputBuffer(
++ index,
++ 0,
++ dstBuffer->size(),
++ 0ll,
++ MediaCodec::BUFFER_FLAG_CODECCONFIG);
++ CHECK_EQ(err, static_cast<status_t>(OK));
++ }
++
++ return err;
++}
++
++int media_codec_start(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ return d->media_codec->start();
++}
++
++int media_codec_stop(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ return d->media_codec->stop();
++}
++
++int media_codec_release(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ return d->media_codec->release();
++}
++
++int media_codec_flush(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ d->available_output_buffer_infos.clear();
++
++ return d->media_codec->flush();
++}
++
++size_t media_codec_get_input_buffers_size(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ status_t ret = d->media_codec->getInputBuffers(&d->input_buffers);
++ if (ret != OK)
++ {
++ ALOGE("Failed to get input buffers size");
++ return 0;
++ }
++ ALOGD("Got %d input buffers", d->input_buffers.size());
++
++ return d->input_buffers.size();
++}
++
++uint8_t *media_codec_get_nth_input_buffer(MediaCodecDelegate delegate, size_t n)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return NULL;
++
++ if (d->input_buffers.size() == 0)
++ {
++ status_t ret = d->media_codec->getInputBuffers(&d->input_buffers);
++ if (ret != OK)
++ {
++ ALOGE("Failed to get input buffers");
++ return NULL;
++ }
++ }
++
++ if (n > d->input_buffers.size())
++ {
++ ALOGE("Failed to get %uth input buffer, n > total buffer size", n);
++ return NULL;
++ }
++
++ return d->input_buffers.itemAt(n).get()->data();
++}
++
++size_t media_codec_get_nth_input_buffer_capacity(MediaCodecDelegate delegate, size_t n)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ Vector<sp<ABuffer> > input_buffers;
++ status_t ret = d->media_codec->getInputBuffers(&input_buffers);
++ if (ret != OK)
++ {
++ ALOGE("Failed to get input buffers");
++ return 0;
++ }
++
++ if (n > input_buffers.size())
++ {
++ ALOGE("Failed to get %uth input buffer capacity, n > total buffer size", n);
++ return 0;
++ }
++
++ return input_buffers[n].get()->capacity();
++}
++
++size_t media_codec_get_output_buffers_size(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ status_t ret = d->media_codec->getOutputBuffers(&d->output_buffers);
++ if (ret != OK)
++ {
++ ALOGE("Failed to get output buffers size");
++ return 0;
++ }
++ ALOGD("Got %d output buffers", d->output_buffers.size());
++
++ return d->output_buffers.size();
++}
++
++uint8_t *media_codec_get_nth_output_buffer(MediaCodecDelegate delegate, size_t n)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return NULL;
++
++ status_t ret = d->media_codec->getOutputBuffers(&d->output_buffers);
++ if (ret != OK)
++ {
++ ALOGE("Failed to get output buffers");
++ return NULL;
++ }
++
++ if (n > d->output_buffers.size())
++ {
++ ALOGE("Failed to get %uth output buffer, n > total buffer size", n);
++ return NULL;
++ }
++
++ return d->output_buffers.itemAt(n).get()->data();
++}
++
++size_t media_codec_get_nth_output_buffer_capacity(MediaCodecDelegate delegate, size_t n)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ status_t ret = d->media_codec->getOutputBuffers(&d->output_buffers);
++ if (ret != OK)
++ {
++ ALOGE("Failed to get output buffers");
++ return 0;
++ }
++
++ if (n > d->output_buffers.size())
++ {
++ ALOGE("Failed to get %uth output buffer capacity, n > total buffer size", n);
++ return 0;
++ }
++
++ return d->output_buffers[n].get()->capacity();
++}
++
++#define INFO_TRY_AGAIN_LATER -1
++#define INFO_OUTPUT_FORMAT_CHANGED -2
++#define INFO_OUTPUT_BUFFERS_CHANGED -4
++
++int media_codec_dequeue_output_buffer(MediaCodecDelegate delegate, MediaCodecBufferInfo *info, int64_t timeout_us)
++{
++ REPORT_FUNCTION()
++
++ if (info == NULL)
++ {
++ ALOGE("info must not be NULL");
++ return BAD_VALUE;
++ }
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ int ret = d->media_codec->dequeueOutputBuffer(&info->index, &info->offset, &info->size, &info->presentation_time_us, &info->flags, timeout_us);
++ ALOGD("dequeueOutputBuffer() ret: %d", ret);
++ info->render_retries = 0;
++
++ if (ret == -EAGAIN)
++ {
++ ALOGD("dequeueOutputBuffer returned %d", ret);
++ return INFO_TRY_AGAIN_LATER;
++ }
++ else if (ret & ~INFO_OUTPUT_BUFFERS_CHANGED)
++ {
++ ALOGD("Output buffers changed (ret: %d)", ret);
++ return INFO_OUTPUT_BUFFERS_CHANGED + 1;
++ }
++ // FIXME: Get rid of the hardcoded -10 and replace with more elegant solution
++ else if (ret & ~(INFO_FORMAT_CHANGED - 10))
++ {
++ ALOGD("Output buffer format changed (ret: %d)", ret);
++ d->output_format_changed = true;
++ return -2;
++ }
++
++ ALOGD("Dequeued output buffer:\n-----------------------");
++ ALOGD("index: %u", info->index);
++ ALOGD("offset: %d", info->offset);
++ ALOGD("size: %d", info->size);
++ ALOGD("presentation_time_us: %lld", info->presentation_time_us);
++ ALOGD("flags: %d", info->flags);
++
++ // Keep track of the used output buffer info
++ d->available_output_buffer_infos.push_back(*info);
++
++ return OK;
++}
++
++int media_codec_queue_input_buffer(MediaCodecDelegate delegate, const MediaCodecBufferInfo *info)
++{
++ REPORT_FUNCTION()
++
++ if (info == NULL)
++ {
++ ALOGE("info must not be NULL");
++ return BAD_VALUE;
++ }
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ // Make sure that there is at least one dequeued input buffer available
++ if (d->available_input_buffer_indices.empty())
++ {
++ ALOGE("Input buffer index %d has not been dequeued, cannot queue input buffer", info->index);
++ return BAD_VALUE;
++ }
++
++ const size_t index = *d->available_input_buffer_indices.begin();
++ d->available_input_buffer_indices.erase(d->available_input_buffer_indices.begin());
++
++ ALOGD("info->index: %d", index);
++ ALOGD("info->offset: %d", info->offset);
++ ALOGD("info->size: %d", info->size);
++ ALOGD("info->presentation_time_us: %lld", info->presentation_time_us);
++ ALOGD("info->flags: %d", info->flags);
++
++ AString err_msg;
++ status_t ret = d->media_codec->queueInputBuffer(index, info->offset, info->size,
++ info->presentation_time_us, info->flags, &err_msg);
++ if (ret != OK)
++ {
++ ALOGE("Failed to queue input buffer (err: %d, index: %d)", ret, index);
++ ALOGE("Detailed error message: %s", err_msg.c_str());
++ }
++
++ return ret;
++}
++
++int media_codec_dequeue_input_buffer(MediaCodecDelegate delegate, size_t *index, int64_t timeout_us)
++{
++ REPORT_FUNCTION()
++
++ if (index == NULL)
++ {
++ ALOGE("index must not be NULL");
++ return BAD_VALUE;
++ }
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ status_t ret = d->media_codec->dequeueInputBuffer(index, timeout_us);
++ if (ret == -EAGAIN)
++ {
++ ALOGD("dequeueInputBuffer returned %d, tried timeout: %d", ret, timeout_us);
++ return INFO_TRY_AGAIN_LATER;
++ }
++ else if (ret == OK)
++ {
++ ALOGD("Dequeued input buffer (index: %d)", *index);
++ d->available_input_buffer_indices.push_back(*index);
++ }
++ else
++ ALOGE("Failed to dequeue input buffer (err: %d, index: %d)", ret, *index);
++
++ return ret;
++}
++
++int media_codec_release_output_buffer(MediaCodecDelegate delegate, size_t index, uint8_t render)
++{
++ REPORT_FUNCTION()
++ ALOGV("Requesting to release output buffer index: %d, render: %d", index, render);
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return BAD_VALUE;
++
++ status_t ret = OK;
++
++ auto it = d->available_output_buffer_infos.begin();
++ while (it != d->available_output_buffer_infos.end())
++ {
++ MediaCodecBufferInfo *info = &*it;
++ ALOGD("info index: %d", info->index);
++ ALOGD("info render_retries: %u", info->render_retries);
++ if (info->render_retries == 1)
++ {
++ ALOGV("Rendering and releasing output buffer %d from the available indices list", info->index);
++ ret = d->media_codec->renderOutputBufferAndRelease(info->index);
++ if (ret != OK)
++ {
++ ALOGE("Failed to release output buffer (ret: %d, index: %d)", ret, info->index);
++ ++info->render_retries;
++ }
++ else
++ {
++ ALOGV("Successfully rendered output buffer %d on a second try.", info->index);
++ d->available_output_buffer_infos.erase(it);
++ }
++ }
++ else if (info->render_retries > 1)
++ {
++ ALOGV("Tried to render output buffer %d twice, dropping.", info->index);
++ ret = d->media_codec->releaseOutputBuffer(info->index);
++ d->available_output_buffer_infos.erase(d->available_output_buffer_infos.begin());
++ }
++
++ ++it;
++ }
++
++ MediaCodecBufferInfo *info = &*d->available_output_buffer_infos.begin();
++ // Either render and release the output buffer, or just release.
++ if (render)
++ {
++ ALOGV("Rendering and releasing output buffer %d from the available indices list", info->index);
++ ret = d->media_codec->renderOutputBufferAndRelease(info->index);
++ }
++ else
++ {
++ ALOGV("Releasing output buffer %d from the available indices list", info->index);
++ ret = d->media_codec->releaseOutputBuffer(info->index);
++ }
++ if (ret != OK)
++ {
++ ALOGE("Failed to release output buffer (ret: %d, index: %d)", ret, info->index);
++ ++info->render_retries;
++ } else {
++ ALOGV("Released output buffer %d from the available buffer infos list", info->index);
++ d->available_output_buffer_infos.erase(d->available_output_buffer_infos.begin());
++ }
++
++ return ret;
++}
++
++MediaFormat media_codec_get_output_format(MediaCodecDelegate delegate)
++{
++ REPORT_FUNCTION()
++
++ _MediaCodecDelegate *d = get_internal_delegate(delegate);
++ if (d == NULL)
++ return NULL;
++
++ _MediaFormat *f = new _MediaFormat();
++
++ sp<AMessage> msg_format;
++ status_t ret = d->media_codec->getOutputFormat(&msg_format);
++ if (ret != OK)
++ {
++ ALOGE("Failed to get the output format");
++ return NULL;
++ }
++
++ ALOGD("Output format: %s", msg_format->debugString().c_str());
++
++ CHECK(msg_format->findString("mime", &f->mime));
++ CHECK(msg_format->findInt32("width", &f->width));
++ CHECK(msg_format->findInt32("height", &f->height));
++ CHECK(msg_format->findInt32("stride", &f->stride));
++ CHECK(msg_format->findInt32("slice-height", &f->slice_height));
++ CHECK(msg_format->findInt32("color-format", &f->color_format));
++ Rect crop;
++ CHECK(msg_format->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom));
++
++ return f;
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_codec_list.cpp
+@@ -0,0 +1,228 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++// Uncomment to enable verbose debug output
++#define LOG_NDEBUG 0
++
++#undef LOG_TAG
++#define LOG_TAG "MediaCodecList"
++
++#include <hybris/media/media_codec_list.h>
++
++#include <media/stagefright/foundation/AString.h>
++#include <media/stagefright/MediaCodecList.h>
++
++#include <utils/Log.h>
++#include <utils/Vector.h>
++
++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__);
++
++using namespace android;
++
++ssize_t media_codec_list_find_codec_by_type(const char *type, bool encoder, size_t startIndex)
++{
++ REPORT_FUNCTION()
++ return MediaCodecList::getInstance()->findCodecByType(type, encoder, startIndex);
++}
++
++ssize_t media_codec_list_find_codec_by_name(const char *name)
++{
++ REPORT_FUNCTION()
++ return MediaCodecList::getInstance()->findCodecByName(name);
++}
++
++size_t media_codec_list_count_codecs()
++{
++ REPORT_FUNCTION()
++ return MediaCodecList::getInstance()->countCodecs();
++}
++
++void media_codec_list_get_codec_info_at_id(size_t index)
++{
++ REPORT_FUNCTION()
++}
++
++const char *media_codec_list_get_codec_name(size_t index)
++{
++ REPORT_FUNCTION()
++ return MediaCodecList::getInstance()->getCodecName(index);
++}
++
++bool media_codec_list_is_encoder(size_t index)
++{
++ REPORT_FUNCTION()
++ return MediaCodecList::getInstance()->isEncoder(index);
++}
++
++size_t media_codec_list_get_num_supported_types(size_t index)
++{
++ REPORT_FUNCTION()
++
++ Vector<AString> types;
++ status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types);
++ if (err != OK)
++ {
++ ALOGE("Failed to get the number of supported codec types (err: %d)", err);
++ return 0;
++ }
++ ALOGD("Number of supported codec types: %d", types.size());
++
++ return types.size();
++}
++
++size_t media_codec_list_get_nth_supported_type_len(size_t index, size_t n)
++{
++ REPORT_FUNCTION()
++
++ Vector<AString> types;
++ status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types);
++
++ return types[n].size();
++}
++
++int media_codec_list_get_nth_supported_type(size_t index, char *type, size_t n)
++{
++ REPORT_FUNCTION()
++
++ if (type == NULL)
++ {
++ ALOGE("types must not be NULL");
++ return BAD_VALUE;
++ }
++
++ Vector<AString> types;
++ status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types);
++ for (size_t i=0; i<types[n].size(); ++i)
++ type[i] = types.itemAt(n).c_str()[i];
++
++ return err;
++}
++
++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)
++{
++ REPORT_FUNCTION()
++
++ Vector<MediaCodecList::ProfileLevel> profile_levels;
++ Vector<uint32_t> color_formats;
++ ALOGD("index: %d, type: '%s'", index, type);
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
++ status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &color_formats);
++#else
++ uint32_t flags;
++ status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &color_formats, &flags);
++#endif
++ if (err != OK)
++ {
++ ALOGE("Failed to get the number of supported codec capabilities (err: %d)", err);
++ return;
++ }
++
++ if (num_profile_levels != NULL)
++ {
++ ALOGD("Number of codec profile levels: %d", profile_levels.size());
++ *num_profile_levels = profile_levels.size();
++ }
++ if (num_color_formats != NULL)
++ {
++ ALOGD("Number of codec color formats: %d", color_formats.size());
++ *num_color_formats = color_formats.size();
++ }
++}
++
++size_t media_codec_list_get_num_profile_levels(size_t index, const char *type)
++{
++ REPORT_FUNCTION()
++
++ size_t num = 0;
++ media_codec_list_get_num_codec_capabilities(index, type, &num, NULL);
++
++ return num;
++}
++
++size_t media_codec_list_get_num_color_formats(size_t index, const char *type)
++{
++ REPORT_FUNCTION()
++
++ size_t num = 0;
++ media_codec_list_get_num_codec_capabilities(index, type, NULL, &num);
++
++ return num;
++}
++
++int media_codec_list_get_nth_codec_profile_level(size_t index, const char *type, profile_level *pro_level, size_t n)
++{
++ REPORT_FUNCTION()
++
++ if (type == NULL)
++ {
++ ALOGE("types must not be NULL");
++ return BAD_VALUE;
++ }
++
++ if (pro_level == NULL)
++ {
++ ALOGE("pro_level must not be NULL");
++ return BAD_VALUE;
++ }
++
++ Vector<MediaCodecList::ProfileLevel> profile_levels;
++ Vector<uint32_t> formats;
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
++ status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats);
++#else
++ uint32_t flags;
++ status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats, &flags);
++#endif
++ if (err != OK)
++ {
++ ALOGE("Failed to get the nth codec profile level (err: %d)", err);
++ return 0;
++ }
++
++ pro_level->profile = profile_levels[n].mProfile;
++ pro_level->level = profile_levels[n].mLevel;
++
++ return err;
++}
++
++int media_codec_list_get_codec_color_formats(size_t index, const char *type, uint32_t *color_formats)
++{
++ REPORT_FUNCTION()
++
++ Vector<MediaCodecList::ProfileLevel> profile_levels;
++ Vector<uint32_t> formats;
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
++ status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats);
++#else
++ uint32_t flags;
++ status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats, &flags);
++#endif
++ if (err != OK)
++ {
++ ALOGE("Failed to get the number of supported codec types (err: %d)", err);
++ return 0;
++ }
++
++ for (size_t i=0; i<formats.size(); ++i)
++ {
++ color_formats[i] = formats[i];
++ ALOGD("Color format [%d]: %d", i, formats[i]);
++ }
++
++ return OK;
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_compatibility_layer.cpp
+@@ -0,0 +1,660 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
++ */
++
++// Uncomment to enable verbose debug output
++#define LOG_NDEBUG 0
++
++#undef LOG_TAG
++#define LOG_TAG "MediaCompatibilityLayer"
++
++#include <hybris/media/media_compatibility_layer.h>
++
++#include <fcntl.h>
++#include <sys/stat.h>
++
++#include <media/mediaplayer.h>
++
++#include <binder/ProcessState.h>
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++#include <gui/SurfaceTexture.h>
++#else
++#include <gui/GLConsumer.h>
++#endif
++
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++
++#include <ui/GraphicBuffer.h>
++
++#include <utils/Log.h>
++
++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__)
++
++namespace android
++{
++NativeBufferAlloc::NativeBufferAlloc() {
++}
++
++NativeBufferAlloc::~NativeBufferAlloc() {
++}
++
++sp<GraphicBuffer> NativeBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
++ PixelFormat format, uint32_t usage, status_t* error) {
++ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
++ status_t err = graphicBuffer->initCheck();
++ *error = err;
++ if (err != 0 || graphicBuffer->handle == 0) {
++ if (err == NO_MEMORY) {
++ GraphicBuffer::dumpAllocationsToSystemLog();
++ }
++ ALOGI("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
++ "failed (%s), handle=%p",
++ w, h, strerror(-err), graphicBuffer->handle);
++ return 0;
++ }
++ return graphicBuffer;
++}
++}
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++struct FrameAvailableListener : public android::SurfaceTexture::FrameAvailableListener
++#else
++struct FrameAvailableListener : public android::GLConsumer::FrameAvailableListener
++#endif
++{
++ public:
++ FrameAvailableListener()
++ : set_video_texture_needs_update_cb(NULL),
++ video_texture_needs_update_context(NULL)
++ {
++ }
++
++ // From android::GLConsumer/SurfaceTexture::FrameAvailableListener
++ void onFrameAvailable()
++ {
++ if (set_video_texture_needs_update_cb != NULL)
++ set_video_texture_needs_update_cb(video_texture_needs_update_context);
++ }
++
++ void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context)
++ {
++ set_video_texture_needs_update_cb = cb;
++ video_texture_needs_update_context = context;
++ }
++
++ private:
++ on_video_texture_needs_update set_video_texture_needs_update_cb;
++ void *video_texture_needs_update_context;
++};
++
++class MediaPlayerListenerWrapper : public android::MediaPlayerListener
++{
++ public:
++ MediaPlayerListenerWrapper()
++ : set_video_size_cb(NULL),
++ video_size_context(NULL),
++ error_cb(NULL),
++ error_context(NULL),
++ playback_complete_cb(NULL),
++ playback_complete_context(NULL),
++ media_prepared_cb(NULL),
++ media_prepared_context(NULL)
++ {
++ }
++
++ void notify(int msg, int ext1, int ext2, const android::Parcel *obj)
++ {
++ ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2);
++
++ switch (msg) {
++ case android::MEDIA_PREPARED:
++ ALOGV("\tMEDIA_PREPARED msg\n");
++ if (media_prepared_cb != NULL)
++ media_prepared_cb(media_prepared_context);
++ else
++ ALOGW("Failed to signal media prepared, callback not set.");
++ break;
++ case android::MEDIA_PLAYBACK_COMPLETE:
++ ALOGV("\tMEDIA_PLAYBACK_COMPLETE msg\n");
++ if (playback_complete_cb != NULL)
++ playback_complete_cb(playback_complete_context);
++ else
++ ALOGW("Failed to signal end of playback, callback not set.");
++ break;
++ case android::MEDIA_BUFFERING_UPDATE:
++ ALOGV("\tMEDIA_BUFFERING_UPDATE msg\n");
++ break;
++ case android::MEDIA_SEEK_COMPLETE:
++ ALOGV("\tMEDIA_SEEK_COMPLETE msg\n");
++ break;
++ case android::MEDIA_SET_VIDEO_SIZE:
++ ALOGV("\tMEDIA_SET_VIDEO_SIZE msg\n");
++ if (set_video_size_cb != NULL)
++ set_video_size_cb(ext2, ext1, video_size_context);
++ else
++ ALOGE("Failed to set video size. set_video_size_cb is NULL.");
++ break;
++ case android::MEDIA_TIMED_TEXT:
++ ALOGV("\tMEDIA_TIMED_TEXT msg\n");
++ break;
++ case android::MEDIA_ERROR:
++ ALOGV("\tMEDIA_ERROR msg\n");
++ // TODO: Extend this cb to include the error message
++ if (error_cb != NULL)
++ error_cb(error_context);
++ else
++ ALOGE("Failed to signal error to app layer, callback not set.");
++ break;
++ case android::MEDIA_INFO:
++ ALOGV("\tMEDIA_INFO msg\n");
++ break;
++ default:
++ ALOGV("\tUnknown media msg\n");
++ }
++ }
++
++ void setVideoSizeCb(on_msg_set_video_size cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ set_video_size_cb = cb;
++ video_size_context = context;
++ }
++
++ void setErrorCb(on_msg_error cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ error_cb = cb;
++ error_context = context;
++ }
++
++ void setPlaybackCompleteCb(on_playback_complete cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ playback_complete_cb = cb;
++ playback_complete_context = context;
++ }
++
++ void setMediaPreparedCb(on_media_prepared cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ media_prepared_cb = cb;
++ media_prepared_context = context;
++ }
++
++ private:
++ on_msg_set_video_size set_video_size_cb;
++ void *video_size_context;
++ on_msg_error error_cb;
++ void *error_context;
++ on_playback_complete playback_complete_cb;
++ void *playback_complete_context;
++ on_media_prepared media_prepared_cb;
++ void *media_prepared_context;
++};
++
++// ----- MediaPlayer Wrapper ----- //
++
++struct MediaPlayerWrapper : public android::MediaPlayer
++{
++ public:
++ MediaPlayerWrapper()
++ : MediaPlayer(),
++ texture(NULL),
++ media_player_listener(new MediaPlayerListenerWrapper()),
++ frame_listener(new FrameAvailableListener),
++ left_volume(1), // Set vol to 100% for this track by default
++ right_volume(1),
++ source_fd(-1)
++ {
++ setListener(media_player_listener);
++ // Update the live volume with the cached values
++ MediaPlayer::setVolume(left_volume, right_volume);
++ }
++
++ ~MediaPlayerWrapper()
++ {
++ reset();
++ source_fd = -1;
++ }
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ android::status_t setVideoSurfaceTexture(const android::sp<android::SurfaceTexture> &surfaceTexture)
++#else
++ android::status_t setVideoSurfaceTexture(android::sp<android::BufferQueue> bq, const android::sp<android::GLConsumer> &surfaceTexture)
++#endif
++ {
++ REPORT_FUNCTION();
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ surfaceTexture->getBufferQueue()->setBufferCount(5);
++#else
++ bq->setBufferCount(5);
++#endif
++ texture = surfaceTexture;
++ texture->setFrameAvailableListener(frame_listener);
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ return MediaPlayer::setVideoSurfaceTexture(surfaceTexture->getBufferQueue());
++#else
++ return MediaPlayer::setVideoSurfaceTexture(bq);
++#endif
++ }
++
++ void updateGLConsumer()
++ {
++ assert(texture != NULL);
++ texture->updateTexImage();
++ }
++
++ void get_transformation_matrix_for_surface_texture(GLfloat* matrix)
++ {
++ assert(texture != NULL);
++ texture->getTransformMatrix(matrix);
++ }
++
++ void setVideoSizeCb(on_msg_set_video_size cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ assert(media_player_listener != NULL);
++ media_player_listener->setVideoSizeCb(cb, context);
++ }
++
++ void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ assert(frame_listener != NULL);
++ frame_listener->setVideoTextureNeedsUpdateCb(cb, context);
++ }
++
++ void setErrorCb(on_msg_error cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ assert(media_player_listener != NULL);
++ media_player_listener->setErrorCb(cb, context);
++ }
++
++ void setPlaybackCompleteCb(on_playback_complete cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ assert(media_player_listener != NULL);
++ media_player_listener->setPlaybackCompleteCb(cb, context);
++ }
++
++ void setMediaPreparedCb(on_media_prepared cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ assert(media_player_listener != NULL);
++ media_player_listener->setMediaPreparedCb(cb, context);
++ }
++
++ void getVolume(float *leftVolume, float *rightVolume)
++ {
++ *leftVolume = left_volume;
++ *rightVolume = right_volume;
++ }
++
++ android::status_t setVolume(float leftVolume, float rightVolume)
++ {
++ REPORT_FUNCTION();
++
++ left_volume = leftVolume;
++ right_volume = rightVolume;
++ return MediaPlayer::setVolume(leftVolume, rightVolume);
++ }
++
++ int getSourceFd() const { return source_fd; }
++ void setSourceFd(int fd) { source_fd = fd; }
++
++ private:
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ android::sp<android::SurfaceTexture> texture;
++#else
++ android::sp<android::GLConsumer> texture;
++#endif
++ android::sp<MediaPlayerListenerWrapper> media_player_listener;
++ android::sp<FrameAvailableListener> frame_listener;
++ float left_volume;
++ float right_volume;
++ int source_fd;
++}; // MediaPlayerWrapper
++
++using namespace android;
++
++// ----- Media Player C API Implementation ----- //
++
++void android_media_set_video_size_cb(MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return;
++ }
++
++ mp->setVideoSizeCb(cb, context);
++}
++
++void android_media_set_video_texture_needs_update_cb(MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return;
++ }
++
++ mp->setVideoTextureNeedsUpdateCb(cb, context);
++}
++
++void android_media_set_error_cb(MediaPlayerWrapper *mp, on_msg_error cb, void *context)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return;
++ }
++
++ mp->setErrorCb(cb, context);
++}
++
++void android_media_set_playback_complete_cb(MediaPlayerWrapper *mp, on_playback_complete cb, void *context)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return;
++ }
++
++ mp->setPlaybackCompleteCb(cb, context);
++}
++
++void android_media_set_media_prepared_cb(MediaPlayerWrapper *mp, on_media_prepared cb, void *context)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return;
++ }
++
++ mp->setMediaPreparedCb(cb, context);
++}
++
++MediaPlayerWrapper *android_media_new_player()
++{
++ REPORT_FUNCTION();
++
++ MediaPlayerWrapper *mp = new MediaPlayerWrapper();
++ if (mp == NULL) {
++ ALOGE("Failed to create new MediaPlayerWrapper instance.");
++ return NULL;
++ }
++
++ // Required for internal player state processing. Without this, prepare() and start() hang.
++ ProcessState::self()->startThreadPool();
++
++ return mp;
++}
++
++int android_media_set_data_source(MediaPlayerWrapper *mp, const char* url)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ if (url == NULL) {
++ ALOGE("url must not be NULL");
++ return BAD_VALUE;
++ }
++
++ ALOGD("url: %s", url);
++
++ String16 src(url);
++ if (src.startsWith(String16("http://")) == true) {
++ ALOGD("HTTP source URL detected");
++ mp->setDataSource(url, NULL);
++ } else {
++ ALOGD("File source URL detected");
++ int fd = open(url, O_RDONLY);
++ if (fd < 0)
++ {
++ ALOGE("Failed to open source data at: %s\n", url);
++ return BAD_VALUE;
++ }
++
++ mp->setSourceFd(fd);
++
++ struct stat st;
++ stat(url, &st);
++
++ ALOGD("source file length: %lld\n", st.st_size);
++
++ mp->setDataSource(fd, 0, st.st_size);
++ }
++ mp->prepare();
++
++ return OK;
++}
++
++int android_media_set_preview_texture(MediaPlayerWrapper *mp, int texture_id)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ android::sp<android::NativeBufferAlloc> native_alloc(
++ new android::NativeBufferAlloc()
++ );
++
++ android::sp<android::BufferQueue> buffer_queue(
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
++ new android::BufferQueue(false, NULL, native_alloc)
++#else
++ new android::BufferQueue(NULL, native_alloc)
++#endif
++ );
++
++ static const bool allow_synchronous_mode = true;
++ // Create a new GLConsumer/SurfaceTexture from the texture_id in synchronous mode (don't wait on all data in the buffer)
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ mp->setVideoSurfaceTexture(android::sp<android::SurfaceTexture>(
++ new android::SurfaceTexture(
++#else
++ mp->setVideoSurfaceTexture(buffer_queue, android::sp<android::GLConsumer>(
++ new android::GLConsumer(
++#endif
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
++ texture_id,
++ allow_synchronous_mode,
++ GL_TEXTURE_EXTERNAL_OES,
++ true,
++ buffer_queue)));
++#else
++ buffer_queue,
++ texture_id,
++ GL_TEXTURE_EXTERNAL_OES,
++ true,
++ false)));
++#endif
++
++ return OK;
++}
++
++void android_media_update_surface_texture(MediaPlayerWrapper *mp)
++{
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return;
++ }
++
++ mp->updateGLConsumer();
++}
++
++void android_media_surface_texture_get_transformation_matrix(MediaPlayerWrapper *mp, GLfloat* matrix)
++{
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return;
++ }
++
++ mp->get_transformation_matrix_for_surface_texture(matrix);
++}
++
++int android_media_play(MediaPlayerWrapper *mp)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ mp->start();
++ const char *tmp = mp->isPlaying() ? "yes" : "no";
++ ALOGV("Is playing?: %s\n", tmp);
++
++ return OK;
++}
++
++int android_media_pause(MediaPlayerWrapper *mp)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ mp->pause();
++
++ return OK;
++}
++
++int android_media_stop(MediaPlayerWrapper *mp)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ mp->stop();
++
++ int fd = mp->getSourceFd();
++ if (fd > -1)
++ close(fd);
++
++ return OK;
++}
++
++bool android_media_is_playing(MediaPlayerWrapper *mp)
++{
++ if (mp != NULL) {
++ if (mp->isPlaying())
++ return true;
++ }
++
++ return false;
++}
++
++int android_media_seek_to(MediaPlayerWrapper *mp, int msec)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mp->seekTo(msec);
++}
++
++int android_media_get_current_position(MediaPlayerWrapper *mp, int *msec)
++{
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mp->getCurrentPosition(msec);
++}
++
++int android_media_get_duration(MediaPlayerWrapper *mp, int *msec)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mp->getDuration(msec);
++}
++
++int android_media_get_volume(MediaPlayerWrapper *mp, int *volume)
++{
++ REPORT_FUNCTION();
++
++ if (volume == NULL) {
++ ALOGE("volume must not be NULL");
++ return BAD_VALUE;
++ }
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ float left_volume = 0, right_volume = 0;
++ mp->getVolume(&left_volume, &right_volume);
++ *volume = left_volume * 100;
++
++ return OK;
++}
++
++int android_media_set_volume(MediaPlayerWrapper *mp, int volume)
++{
++ REPORT_FUNCTION();
++
++ if (mp == NULL) {
++ ALOGE("mp must not be NULL");
++ return BAD_VALUE;
++ }
++
++ float left_volume = float(volume / 100);
++ float right_volume = float(volume / 100);
++ return mp->setVolume(left_volume, right_volume);
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer.cpp
+@@ -0,0 +1,245 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++// Uncomment to enable verbose debug output
++#define LOG_NDEBUG 0
++
++#undef LOG_TAG
++#define LOG_TAG "MediaFormatLayer"
++
++#include <hybris/media/media_format_layer.h>
++#include "media_format_layer_priv.h"
++
++#include <assert.h>
++
++#include <utils/Log.h>
++
++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__);
++
++using namespace android;
++
++static inline _MediaFormat *get_internal_format(MediaFormat format)
++{
++ if (format == NULL)
++ {
++ ALOGE("format must not be NULL");
++ return NULL;
++ }
++
++ _MediaFormat *mf = static_cast<_MediaFormat*>(format);
++ assert(mf->refcount >= 1);
++
++ return mf;
++}
++
++MediaFormat media_format_create_video_format(const char *mime, int32_t width, int32_t height, int64_t duration_us, int32_t max_input_size)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *format = new _MediaFormat();
++ format->mime = AString(mime);
++ format->width = width;
++ format->height = height;
++ format->duration_us = duration_us;
++ format->max_input_size = max_input_size;
++
++ return format;
++}
++
++void media_format_destroy(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return;
++
++ if (mf->refcount)
++ return;
++
++ delete mf;
++}
++
++void media_format_ref(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return;
++
++ mf->refcount++;
++}
++
++void media_format_unref(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return;
++
++ if (mf->refcount)
++ mf->refcount--;
++}
++
++void media_format_set_byte_buffer(MediaFormat format, const char *key, uint8_t *data, size_t size)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return;
++ if (key == NULL || data == NULL || size == 0)
++ return;
++
++ mf->csd_key_name = AString(key);
++ mf->csd = sp<ABuffer>(new ABuffer(data, size));
++}
++
++const char* media_format_get_mime(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return NULL;
++
++ return mf->mime.c_str();
++}
++
++int64_t media_format_get_duration_us(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->duration_us;
++}
++
++int32_t media_format_get_width(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->width;
++}
++
++int32_t media_format_get_height(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->height;
++}
++
++int32_t media_format_get_max_input_size(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->max_input_size;
++}
++
++int32_t media_format_get_stride(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->stride;
++}
++
++int32_t media_format_get_slice_height(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->height;
++}
++
++int32_t media_format_get_color_format(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->color_format;
++}
++
++int32_t media_format_get_crop_left(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->crop_left;
++}
++
++int32_t media_format_get_crop_right(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->crop_right;
++}
++
++int32_t media_format_get_crop_top(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->crop_top;
++}
++
++int32_t media_format_get_crop_bottom(MediaFormat format)
++{
++ REPORT_FUNCTION()
++
++ _MediaFormat *mf = get_internal_format(format);
++ if (mf == NULL)
++ return 0;
++
++ return mf->crop_bottom;
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer_priv.cpp
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#include <stddef.h>
++#include <unistd.h>
++
++#include <media/stagefright/foundation/AString.h>
++
++#include <utils/RefBase.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct _MediaFormat : public RefBase
++{
++ _MediaFormat()
++ : refcount(1)
++ {
++ }
++
++ AString mime;
++ int64_t duration_us;
++ int32_t width;
++ int32_t height;
++ int32_t max_input_size;
++
++ unsigned int refcount;
++};
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer_priv.h
+@@ -0,0 +1,68 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#ifndef MEDIA_FORMAT_LAYER_PRIV_H_
++#define MEDIA_FORMAT_LAYER_PRIV_H_
++
++#include <stddef.h>
++#include <unistd.h>
++
++#include <media/stagefright/foundation/AString.h>
++#include <media/stagefright/foundation/ABuffer.h>
++
++#include <utils/RefBase.h>
++
++struct _MediaFormat : public android::RefBase
++{
++ _MediaFormat()
++ : duration_us(0),
++ width(0),
++ height(0),
++ max_input_size(0),
++ csd(NULL),
++ stride(0),
++ slice_height(0),
++ color_format(0),
++ crop_left(0),
++ crop_right(0),
++ crop_top(0),
++ crop_bottom(0),
++ refcount(1)
++ {
++ }
++
++ android::AString mime;
++ int64_t duration_us;
++ int32_t width;
++ int32_t height;
++ int32_t max_input_size;
++ android::AString csd_key_name;
++ android::sp<android::ABuffer> csd;
++
++ int32_t stride;
++ int32_t slice_height;
++ int32_t color_format;
++ int32_t crop_left;
++ int32_t crop_right;
++ int32_t crop_top;
++ int32_t crop_bottom;
++
++ unsigned int refcount;
++};
++
++#endif // MEDIA_FORMAT_LAYER_PRIV_H_
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/recorder_compatibility_layer.cpp
+@@ -0,0 +1,457 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ * Guenter Schwann <guenter.schwann@canonical.com>
++ * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
++ */
++
++#include <hybris/internal/camera_control.h>
++#include <hybris/media/recorder_compatibility_layer.h>
++
++#include <camera/Camera.h>
++#include <camera/ICamera.h>
++#include <media/mediarecorder.h>
++
++//#define LOG_NDEBUG 0
++#undef LOG_TAG
++#define LOG_TAG "MediaRecorderCompatibilityLayer"
++#include <utils/KeyedVector.h>
++#include <utils/Log.h>
++
++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__)
++
++/*!
++ * \brief The MediaRecorderListenerWrapper class is used to listen to events
++ * from the MediaRecorder
++ */
++class MediaRecorderListenerWrapper : public android::MediaRecorderListener
++{
++ public:
++ MediaRecorderListenerWrapper()
++ : error_cb(NULL),
++ error_context(NULL)
++ {
++ }
++
++ void notify(int msg, int ext1, int ext2)
++ {
++ ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2);
++
++ switch (msg) {
++ case android::MEDIA_RECORDER_EVENT_ERROR:
++ ALOGV("\tMEDIA_RECORDER_EVENT_ERROR msg\n");
++ // TODO: Extend this cb to include the error message
++ if (error_cb != NULL)
++ error_cb(error_context);
++ else
++ ALOGE("Failed to signal error to app layer, callback not set.");
++ break;
++ default:
++ ALOGV("\tUnknown notification\n");
++ }
++ }
++
++ void setErrorCb(on_recorder_msg_error cb, void *context)
++ {
++ REPORT_FUNCTION();
++ error_cb = cb;
++ error_context = context;
++ }
++
++ private:
++ on_recorder_msg_error error_cb;
++ void *error_context;
++};
++
++/*!
++ * \brief The MediaRecorderWrapper struct wraps the MediaRecorder class
++ */
++struct MediaRecorderWrapper : public android::MediaRecorder
++{
++ public:
++ MediaRecorderWrapper()
++ : MediaRecorder(),
++ media_recorder_listener(new MediaRecorderListenerWrapper())
++ {
++ setListener(media_recorder_listener);
++ }
++
++ ~MediaRecorderWrapper()
++ {
++ reset();
++ }
++
++ void setErrorCb(on_recorder_msg_error cb, void *context)
++ {
++ REPORT_FUNCTION();
++
++ assert(media_recorder_listener != NULL);
++ media_recorder_listener->setErrorCb(cb, context);
++ }
++
++ private:
++ android::sp<MediaRecorderListenerWrapper> media_recorder_listener;
++};
++
++
++using namespace android;
++
++/*!
++ * \brief android_recorder_set_error_cb
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param cb The callback function to be called when a recording error occurs
++ * \param context
++ */
++void android_recorder_set_error_cb(MediaRecorderWrapper *mr, on_recorder_msg_error cb,
++ void *context)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return;
++ }
++
++ mr->setErrorCb(cb, context);
++}
++
++/*!
++ * \brief android_media_new_recorder creates a new MediaRecorder
++ * \return New MediaRecorder object, or NULL if the object could not be created.
++ */
++MediaRecorderWrapper *android_media_new_recorder()
++{
++ REPORT_FUNCTION();
++
++ MediaRecorderWrapper *mr = new MediaRecorderWrapper;
++ if (mr == NULL) {
++ ALOGE("Failed to create new MediaRecorderWrapper instance.");
++ return NULL;
++ }
++
++ return mr;
++}
++
++/*!
++ * \brief android_recorder_initCheck
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \return negative value if an error occured
++ */
++int android_recorder_initCheck(MediaRecorderWrapper *mr)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->initCheck();
++}
++
++/*!
++ * \brief android_recorder_setCamera sets the camera object for recording videos
++ * from the camera
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param control Wrapper for the camera (see camera in hybris)
++ * \return negative value if an error occured
++ */
++int android_recorder_setCamera(MediaRecorderWrapper *mr, CameraControl* control)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++ if (control == NULL) {
++ ALOGE("control must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setCamera(control->camera->remote(), control->camera->getRecordingProxy());
++}
++
++/*!
++ * \brief android_recorder_setVideoSource sets the video source.
++ * If no video source is set, only audio is recorded.
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param vs The video source. It's either the camera of gralloc buffer
++ * \return negative value if an error occured
++ */
++int android_recorder_setVideoSource(MediaRecorderWrapper *mr, VideoSource vs)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setVideoSource(static_cast<int>(vs));
++}
++
++/*!
++ * \brief android_recorder_setAudioSource
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param as The audio source.
++ * \return negative value if an error occured
++ */
++int android_recorder_setAudioSource(MediaRecorderWrapper *mr, AudioSource as)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setAudioSource(static_cast<int>(as));
++}
++
++/*!
++ * \brief android_recorder_setOutputFormat
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param of The output file format
++ * \return negative value if an error occured
++ */
++int android_recorder_setOutputFormat(MediaRecorderWrapper *mr, OutputFormat of)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setOutputFormat(static_cast<int>(of));
++}
++
++/*!
++ * \brief android_recorder_setVideoEncoder
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param ve The video encoder sets the codec for the video
++ * \return negative value if an error occured
++ */
++int android_recorder_setVideoEncoder(MediaRecorderWrapper *mr, VideoEncoder ve)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setVideoEncoder(static_cast<int>(ve));
++}
++
++/*!
++ * \brief android_recorder_setAudioEncoder
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param ae The audio encoder sets the codec for the audio
++ * \return negative value if an error occured
++ */
++int android_recorder_setAudioEncoder(MediaRecorderWrapper *mr, AudioEncoder ae)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setAudioEncoder(static_cast<int>(ae));
++}
++
++/*!
++ * \brief android_recorder_setOutputFile sets the output file to the given file descriptor
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param fd File descriptor of an open file, that the stream can be written to
++ * \return negative value if an error occured
++ */
++int android_recorder_setOutputFile(MediaRecorderWrapper *mr, int fd)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setOutputFile(fd, 0, 0);
++}
++
++/*!
++ * \brief android_recorder_setVideoSize
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param width width for the video to record
++ * \param height height for the video to record
++ * \return negative value if an error occured
++ */
++int android_recorder_setVideoSize(MediaRecorderWrapper *mr, int width, int height)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setVideoSize(width, height);
++}
++
++/*!
++ * \brief android_recorder_setVideoFrameRate
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param frames_per_second Frames per second has typical values for a movie clip in 720p is 30
++ * \return negative value if an error occured
++ */
++int android_recorder_setVideoFrameRate(MediaRecorderWrapper *mr, int frames_per_second)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->setVideoFrameRate(frames_per_second);
++}
++
++/*!
++ * \brief android_recorder_setParameters sets a parameter. Even those without
++ * explicit function.
++ * For possible parameters look for example in StagefrightRecorder::setParameter()
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \param parameters list of parameters. format is "parameter1=value;parameter2=value"
++ * \return negative value if an error occured
++ */
++int android_recorder_setParameters(MediaRecorderWrapper *mr, const char* parameters)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ String8 params(parameters);
++ return mr->setParameters(params);
++}
++
++/*!
++ * \brief android_recorder_start starts the recording.
++ * The MediaRecorder has to be in state "prepared"
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \return negative value if an error occured
++ */
++int android_recorder_start(MediaRecorderWrapper *mr)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->start();
++}
++
++/*!
++ * \brief android_recorder_stop Stops a running recording.
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \return negative value if an error occured
++ */
++int android_recorder_stop(MediaRecorderWrapper *mr)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->stop();
++}
++
++/*!
++ * \brief android_recorder_prepare put the MediaRecorder into state "prepare"
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \return negative value if an error occured
++ */
++int android_recorder_prepare(MediaRecorderWrapper *mr)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->prepare();
++}
++
++/*!
++ * \brief android_recorder_reset resets the MediaRecorder
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \return negative value if an error occured
++ */
++int android_recorder_reset(MediaRecorderWrapper *mr)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->reset();
++}
++
++/*!
++ * \brief android_recorder_close closes the MediaRecorder
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \return negative value if an error occured
++ */
++int android_recorder_close(MediaRecorderWrapper *mr)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->close();
++}
++
++/*!
++ * \brief android_recorder_release releases the MediaRecorder resources
++ * This deletes the object. So don't use it after calling this function.
++ * \param mr A MediaRecorderWrapper instance, created by calling android_media_new_recorder()
++ * \return negative value if an error occured
++ */
++int android_recorder_release(MediaRecorderWrapper *mr)
++{
++ REPORT_FUNCTION();
++
++ if (mr == NULL) {
++ ALOGE("mr must not be NULL");
++ return BAD_VALUE;
++ }
++
++ return mr->release();
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/surface_texture_client_hybris.cpp
+@@ -0,0 +1,333 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++// Uncomment to enable verbose debug output
++#define LOG_NDEBUG 0
++
++#undef LOG_TAG
++#define LOG_TAG "SurfaceTextureClientHybris"
++
++#include <hybris/media/surface_texture_client_hybris.h>
++#include "surface_texture_client_hybris_priv.h"
++
++#include <ui/GraphicBuffer.h>
++#include <utils/Log.h>
++#include <ui/Region.h>
++#include <gui/Surface.h>
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++#include <gui/SurfaceTextureClient.h>
++#endif
++
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++
++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__);
++
++using namespace android;
++
++// ----- Begin _SurfaceTextureClientHybris API ----- //
++
++static inline _SurfaceTextureClientHybris *get_internal_stch(SurfaceTextureClientHybris stc, const char * func)
++{
++ if (stc == NULL)
++ {
++ ALOGE("stc must not be NULL (%s)", func);
++ return NULL;
++ }
++
++ _SurfaceTextureClientHybris *s = static_cast<_SurfaceTextureClientHybris*>(stc);
++ assert(s->refcount >= 1);
++
++ return s;
++}
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris()
++ : refcount(1),
++ ready(false)
++{
++ REPORT_FUNCTION()
++}
++#endif
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=4
++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp<BufferQueue> &bq)
++ : Surface::Surface(bq, true),
++ refcount(1),
++ ready(false)
++{
++ REPORT_FUNCTION()
++}
++#endif
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch)
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ : SurfaceTextureClient::SurfaceTextureClient(),
++#else
++ : Surface::Surface(new BufferQueue(), true),
++#endif
++ refcount(stch.refcount),
++ ready(false)
++{
++ REPORT_FUNCTION()
++}
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp<ISurfaceTexture> &st)
++ : SurfaceTextureClient::SurfaceTextureClient(st),
++#else
++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp<IGraphicBufferProducer> &st)
++ : Surface::Surface(st, true),
++#endif
++ refcount(1),
++ ready(false)
++{
++ REPORT_FUNCTION()
++}
++#endif
++
++_SurfaceTextureClientHybris::~_SurfaceTextureClientHybris()
++{
++ REPORT_FUNCTION()
++
++ ready = false;
++}
++
++bool _SurfaceTextureClientHybris::isReady() const
++{
++ return ready;
++}
++
++int _SurfaceTextureClientHybris::dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd)
++{
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ return SurfaceTextureClient::dequeueBuffer(buffer, fenceFd);
++#else
++ return Surface::dequeueBuffer(buffer, fenceFd);
++#endif
++}
++
++int _SurfaceTextureClientHybris::queueBuffer(ANativeWindowBuffer* buffer, int fenceFd)
++{
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ return SurfaceTextureClient::queueBuffer(buffer, fenceFd);
++#else
++ return Surface::queueBuffer(buffer, fenceFd);
++#endif
++}
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++void _SurfaceTextureClientHybris::setISurfaceTexture(const sp<ISurfaceTexture>& surface_texture)
++{
++ SurfaceTextureClient::setISurfaceTexture(surface_texture);
++#else
++void _SurfaceTextureClientHybris::setISurfaceTexture(const sp<IGraphicBufferProducer>& surface_texture)
++{
++ // We don't need to set up the IGraphicBufferProducer as stc needs it when created
++#endif
++
++ // Ready for rendering
++ ready = true;
++}
++
++void _SurfaceTextureClientHybris::setHardwareRendering(bool do_hardware_rendering)
++{
++ hardware_rendering = do_hardware_rendering;
++}
++
++bool _SurfaceTextureClientHybris::hardwareRendering()
++{
++ return hardware_rendering;
++}
++
++// ----- End _SurfaceTextureClientHybris API ----- //
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp<SurfaceTexture> &surface_texture)
++#else
++static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp<GLConsumer> &surface_texture)
++#endif
++{
++ REPORT_FUNCTION()
++
++ if (stch == NULL)
++ return;
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ stch->setISurfaceTexture(surface_texture->getBufferQueue());
++#else
++ stch->setISurfaceTexture(stch->getIGraphicBufferProducer());
++#endif
++}
++
++SurfaceTextureClientHybris surface_texture_client_create_by_id(unsigned int texture_id)
++{
++ REPORT_FUNCTION()
++
++ if (texture_id == 0)
++ {
++ ALOGE("Cannot create new SurfaceTextureClientHybris, texture id must be > 0.");
++ return NULL;
++ }
++
++ // Use a new native buffer allocator vs the default one, which means it'll use the proper one
++ // that will allow rendering to work with Mir
++ sp<NativeBufferAlloc> native_alloc(new NativeBufferAlloc());
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
++ sp<BufferQueue> buffer_queue(new BufferQueue(false, NULL, native_alloc));
++ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris);
++#else
++ sp<BufferQueue> buffer_queue(new BufferQueue(NULL, native_alloc));
++ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris(buffer_queue));
++#endif
++
++ ALOGD("stch: %p (%s)", stch, __PRETTY_FUNCTION__);
++
++ if (stch->surface_texture != NULL)
++ stch->surface_texture.clear();
++
++ const bool allow_synchronous_mode = true;
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ stch->surface_texture = new SurfaceTexture(texture_id, allow_synchronous_mode, GL_TEXTURE_EXTERNAL_OES, true, buffer_queue);
++ set_surface(stch, stch->surface_texture);
++#else
++ stch->surface_texture = new GLConsumer(buffer_queue, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true);
++#endif
++ set_surface(stch, stch->surface_texture);
++
++ return stch;
++}
++
++uint8_t surface_texture_client_is_ready_for_rendering(SurfaceTextureClientHybris stc)
++{
++ REPORT_FUNCTION()
++
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ return false;
++
++ return static_cast<uint8_t>(s->isReady());
++}
++
++uint8_t surface_texture_client_hardware_rendering(SurfaceTextureClientHybris stc)
++{
++ REPORT_FUNCTION()
++
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ return false;
++
++ return s->hardwareRendering();
++}
++
++void surface_texture_client_set_hardware_rendering(SurfaceTextureClientHybris stc, uint8_t hardware_rendering)
++{
++ REPORT_FUNCTION()
++
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ return;
++
++ s->setHardwareRendering(static_cast<bool>(hardware_rendering));
++}
++
++void surface_texture_client_get_transformation_matrix(SurfaceTextureClientHybris stc, float *matrix)
++{
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ return;
++
++ s->surface_texture->getTransformMatrix(static_cast<GLfloat*>(matrix));
++}
++
++void surface_texture_client_update_texture(SurfaceTextureClientHybris stc)
++{
++ REPORT_FUNCTION()
++
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ return;
++
++ s->surface_texture->updateTexImage();
++}
++
++void surface_texture_client_destroy(SurfaceTextureClientHybris stc)
++{
++ REPORT_FUNCTION()
++
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ {
++ ALOGE("s == NULL, cannot destroy SurfaceTextureClientHybris instance");
++ return;
++ }
++
++ s->refcount = 0;
++
++ delete s;
++}
++
++void surface_texture_client_ref(SurfaceTextureClientHybris stc)
++{
++ REPORT_FUNCTION()
++
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ return;
++
++ s->refcount++;
++}
++
++void surface_texture_client_unref(SurfaceTextureClientHybris stc)
++{
++ REPORT_FUNCTION()
++
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ {
++ ALOGE("s == NULL, cannot unref SurfaceTextureClientHybris instance");
++ return;
++ }
++
++ if (s->refcount > 1)
++ s->refcount--;
++ else
++ surface_texture_client_destroy (stc);
++}
++
++void surface_texture_client_set_surface_texture(SurfaceTextureClientHybris stc, EGLNativeWindowType native_window)
++{
++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__);
++ if (s == NULL)
++ return;
++
++ if (native_window == NULL)
++ {
++ ALOGE("native_window must not be NULL");
++ return;
++ }
++
++ sp<Surface> surface = static_cast<Surface*>(native_window);
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ s->setISurfaceTexture(surface->getSurfaceTexture());
++#else
++ s->setISurfaceTexture(surface->getIGraphicBufferProducer());
++#endif
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/compat/media/surface_texture_client_hybris_priv.h
+@@ -0,0 +1,68 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#include <gui/Surface.h>
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++#include <gui/SurfaceTextureClient.h>
++#else
++#include <gui/GLConsumer.h>
++#endif
++
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++struct _SurfaceTextureClientHybris : public android::SurfaceTextureClient
++#else
++struct _SurfaceTextureClientHybris : public android::Surface
++#endif
++{
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ _SurfaceTextureClientHybris();
++#endif
++ _SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch);
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ _SurfaceTextureClientHybris(const android::sp<android::ISurfaceTexture> &st);
++#else
++ _SurfaceTextureClientHybris(const android::sp<android::BufferQueue> &bq);
++#endif
++ ~_SurfaceTextureClientHybris();
++
++ /** Has a texture id or EGLNativeWindowType been passed in, meaning rendering will function? **/
++ bool isReady() const;
++
++public:
++ int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
++ int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd);
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ void setISurfaceTexture(const android::sp<android::ISurfaceTexture>& surface_texture);
++#else
++ void setISurfaceTexture(const android::sp<android::IGraphicBufferProducer>& surface_texture);
++#endif
++ void setHardwareRendering(bool do_hardware_rendering);
++ bool hardwareRendering();
++
++ unsigned int refcount;
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
++ android::sp<android::SurfaceTexture> surface_texture;
++#else
++ android::sp<android::GLConsumer> surface_texture;
++#endif
++
++private:
++ bool ready;
++ bool hardware_rendering;
++};
++
+--- libhybris-0.1.0+git20131207+e452e83.orig/compat/ui/Android.mk
++++ libhybris-0.1.0+git20131207+e452e83/compat/ui/Android.mk
+@@ -1,5 +1,6 @@
+ LOCAL_PATH:= $(call my-dir)
+ include $(CLEAR_VARS)
++include $(LOCAL_PATH)/../Android.common.mk
+
+ HYBRIS_PATH := $(LOCAL_PATH)/../../hybris
+
+--- libhybris-0.1.0+git20131207+e452e83.orig/compat/ui/ui_compatibility_layer.cpp
++++ libhybris-0.1.0+git20131207+e452e83/compat/ui/ui_compatibility_layer.cpp
+@@ -126,6 +126,7 @@ void* graphic_buffer_get_native_buffer(s
+ return buffer->self->getNativeBuffer();
+ }
+
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
+ void graphic_buffer_set_index(struct graphic_buffer *buffer, int index)
+ {
+ return buffer->self->setIndex(index);
+@@ -135,6 +136,7 @@ int graphic_buffer_get_index(struct grap
+ {
+ return buffer->self->getIndex();
+ }
++#endif
+
+ int graphic_buffer_init_check(struct graphic_buffer *buffer)
+ {
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/Makefile.am
++++ libhybris-0.1.0+git20131207+e452e83/hybris/Makefile.am
+@@ -4,7 +4,7 @@ if HAS_ANDROID_4_2_0
+ SUBDIRS += libsync
+ endif
+
+-SUBDIRS += egl glesv1 glesv2 ui sf input camera
++SUBDIRS += egl glesv1 glesv2 ui sf input camera media
+ if HAS_LIBNFC_NXP_HEADERS
+ SUBDIRS += libnfc_nxp libnfc_ndef_nxp
+ endif
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks.c
+@@ -27,6 +27,7 @@
+ #include <stdio_ext.h>
+ #include <stddef.h>
+ #include <stdlib.h>
++#include <limits.h>
+ #include <malloc.h>
+ #include <string.h>
+ #include <strings.h>
+@@ -42,6 +43,10 @@
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+
++#include <linux/futex.h>
++#include <sys/syscall.h>
++#include <sys/time.h>
++
+ #include <netdb.h>
+ #include <unistd.h>
+ #include <syslog.h>
+@@ -64,8 +69,12 @@ static int locale_inited = 0;
+
+ #define ANDROID_MUTEX_SHARED_MASK 0x2000
+ #define ANDROID_COND_SHARED_MASK 0x0001
++#define ANDROID_COND_COUNTER_INCREMENT 0x0002
++#define ANDROID_COND_COUNTER_MASK (~ANDROID_COND_SHARED_MASK)
+ #define ANDROID_RWLOCKATTR_SHARED_MASK 0x0010
+
++#define ANDROID_COND_IS_SHARED(c) (((c)->value & ANDROID_COND_SHARED_MASK) != 0)
++
+ /* For the static initializer types */
+ #define ANDROID_PTHREAD_MUTEX_INITIALIZER 0
+ #define ANDROID_PTHREAD_RECURSIVE_MUTEX_INITIALIZER 0x4000
+@@ -87,6 +96,11 @@ struct _hook {
+ void *func;
+ };
+
++/* pthread cond struct as done in Android */
++typedef struct {
++ int volatile value;
++} android_cond_t;
++
+ /* Helpers */
+ static int hybris_check_android_shared_mutex(unsigned int mutex_addr)
+ {
+@@ -109,9 +123,59 @@ static int hybris_check_android_shared_c
+ (cond_addr & ANDROID_COND_SHARED_MASK))
+ return 1;
+
++ /* In case android is setting up cond_addr with a negative value,
++ * used for error control */
++ if (cond_addr > HYBRIS_SHM_MASK_TOP)
++ return 1;
++
++ return 0;
++}
++
++/* Based on Android's Bionic pthread implementation.
++ * This is just needed when we have a shared cond with Android */
++static int __android_pthread_cond_pulse(android_cond_t *cond, int counter)
++{
++ long flags;
++ int fret;
++
++ if (cond == NULL)
++ return EINVAL;
++
++ flags = (cond->value & ~ANDROID_COND_COUNTER_MASK);
++ for (;;) {
++ long oldval = cond->value;
++ long newval = 0;
++ /* In our case all we need to do is make sure the negative value
++ * is under our range, which is the last 0xF from SHM_MASK */
++ if (oldval < -12)
++ newval = ((oldval + ANDROID_COND_COUNTER_INCREMENT) &
++ ANDROID_COND_COUNTER_MASK) | flags;
++ else
++ newval = ((oldval - ANDROID_COND_COUNTER_INCREMENT) &
++ ANDROID_COND_COUNTER_MASK) | flags;
++ if (__sync_bool_compare_and_swap(&cond->value, oldval, newval))
++ break;
++ }
++
++ int pshared = cond->value & ANDROID_COND_SHARED_MASK;
++ fret = syscall(SYS_futex , &cond->value,
++ pshared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, counter,
++ NULL, NULL, NULL);
++ LOGD("futex based pthread_cond_*, value %d, counter %d, ret %d",
++ cond->value, counter, fret);
+ return 0;
+ }
+
++int android_pthread_cond_broadcast(android_cond_t *cond)
++{
++ return __android_pthread_cond_pulse(cond, INT_MAX);
++}
++
++int android_pthread_cond_signal(android_cond_t *cond)
++{
++ return __android_pthread_cond_pulse(cond, 1);
++}
++
+ static void hybris_set_mutex_attr(unsigned int android_value, pthread_mutexattr_t *attr)
+ {
+ /* Init already sets as PTHREAD_MUTEX_NORMAL */
+@@ -577,8 +641,8 @@ static int my_pthread_cond_broadcast(pth
+ {
+ unsigned int value = (*(unsigned int *) cond);
+ if (hybris_check_android_shared_cond(value)) {
+- LOGD("shared condition with Android, not broadcasting.");
+- return 0;
++ LOGD("Shared condition with Android, broadcasting with futex.");
++ return android_pthread_cond_broadcast((android_cond_t *) cond);
+ }
+
+ pthread_cond_t *realcond = (pthread_cond_t *) value;
+@@ -598,8 +662,8 @@ static int my_pthread_cond_signal(pthrea
+ unsigned int value = (*(unsigned int *) cond);
+
+ if (hybris_check_android_shared_cond(value)) {
+- LOGD("Shared condition with Android, not signaling.");
+- return 0;
++ LOGD("Shared condition with Android, broadcasting with futex.");
++ return android_pthread_cond_signal((android_cond_t *) cond);
+ }
+
+ pthread_cond_t *realcond = (pthread_cond_t *) value;
+@@ -1217,6 +1281,56 @@ FP_ATTRIB static double my_strtod(const
+ return strtod_l(nptr, endptr, hybris_locale);
+ }
+
++static int __my_system_property_read(const void *pi, char *name, char *value)
++{
++ return property_get(name, value, NULL);
++}
++
++static int __my_system_property_get(const char *name, char *value)
++{
++ return property_get(name, value, NULL);
++}
++
++static int __my_system_property_foreach(void (*propfn)(const void *pi, void *cookie), void *cookie)
++{
++ return 0;
++}
++
++static const void *__my_system_property_find(const char *name)
++{
++ return NULL;
++}
++
++static unsigned int __my_system_property_serial(const void *pi)
++{
++ return 0;
++}
++
++static int __my_system_property_wait(const void *pi)
++{
++ return 0;
++}
++
++static int __my_system_property_update(void *pi, const char *value, unsigned int len)
++{
++ return 0;
++}
++
++static int __my_system_property_add(const char *name, unsigned int namelen, const char *value, unsigned int valuelen)
++{
++ return 0;
++}
++
++static unsigned int __my_system_property_wait_any(unsigned int serial)
++{
++ return 0;
++}
++
++static const void *__my_system_property_find_nth(unsigned n)
++{
++ return NULL;
++}
++
+ extern int __cxa_atexit(void (*)(void*), void*, void*);
+
+ static struct _hook hooks[] = {
+@@ -1449,6 +1563,17 @@ static struct _hook hooks[] = {
+ /* grp.h */
+ {"getgrgid", getgrgid},
+ {"__cxa_atexit", __cxa_atexit},
++ {"__system_property_read", __my_system_property_read},
++ {"__system_property_get", __my_system_property_get},
++ {"__system_property_set", property_set},
++ {"__system_property_foreach", __my_system_property_foreach},
++ {"__system_property_find", __my_system_property_find},
++ {"__system_property_serial", __my_system_property_serial},
++ {"__system_property_wait", __my_system_property_wait},
++ {"__system_property_update", __my_system_property_update},
++ {"__system_property_add", __my_system_property_add},
++ {"__system_property_wait_any", __my_system_property_wait_any},
++ {"__system_property_find_nth", __my_system_property_find_nth},
+ {NULL, NULL},
+ };
+
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks_shm.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks_shm.c
+@@ -123,7 +123,9 @@ static void _hybris_shm_init()
+ else {
+ LOGD("Creating a new shared memory segment.");
+
+- _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0660);
++ mode_t pumask = umask(0);
++ _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0666);
++ umask(pumask);
+ if (_hybris_shm_fd >= 0) {
+ ftruncate( _hybris_shm_fd, size_to_map );
+ /* Map the memory object */
+@@ -171,11 +173,12 @@ static void _hybris_shm_extend_region()
+
+ /*
+ * Determine if the pointer that has been extracted by hybris is
+- * pointing to an address in the shared memory
++ * pointing to an address in the shared memory.
+ */
+ int hybris_is_pointer_in_shm(void *ptr)
+ {
+- if ((unsigned int)ptr >= HYBRIS_SHM_MASK)
++ if (((unsigned int) ptr >= HYBRIS_SHM_MASK) &&
++ ((unsigned int) ptr <= HYBRIS_SHM_MASK_TOP))
+ return 1;
+
+ return 0;
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks_shm.h
++++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks_shm.h
+@@ -20,6 +20,9 @@
+
+ #include <stddef.h>
+
++/* Leave space to workaround the issue that Android might pass negative int values */
++#define HYBRIS_SHM_MASK_TOP 0xFFFFFFF0UL
++
+ typedef unsigned int hybris_shm_pointer_t;
+
+ /*
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/dlfcn.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/dlfcn.c
+@@ -78,7 +78,7 @@ const char *android_dlerror(void)
+ void *android_dlsym(void *handle, const char *symbol)
+ {
+ soinfo *found;
+- Elf32_Sym *sym;
++ Elf_Sym *sym;
+ unsigned bind;
+
+ pthread_mutex_lock(&dl_lock);
+@@ -142,7 +142,7 @@ int android_dladdr(const void *addr, Dl_
+ info->dli_fbase = (void*)si->base;
+
+ /* Determine if any symbol in the library contains the specified address */
+- Elf32_Sym *sym = find_containing_symbol(addr, si);
++ Elf_Sym *sym = find_containing_symbol(addr, si);
+
+ if(sym != NULL) {
+ info->dli_sname = si->strtab + sym->st_name;
+@@ -192,7 +192,7 @@ int android_dl_iterate_phdr(int (*cb)(st
+ #endif
+
+
+-static Elf32_Sym libdl_symtab[] = {
++static Elf_Sym libdl_symtab[] = {
+ // total length of libdl_info.strtab, including trailing 0
+ // This is actually the the STH_UNDEF entry. Technically, it's
+ // supposed to have st_name == 0, but instead, it points to an index
+@@ -200,45 +200,45 @@ static Elf32_Sym libdl_symtab[] = {
+ { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1,
+ },
+ { st_name: 0, // starting index of the name in libdl_info.strtab
+- st_value: (Elf32_Addr) &android_dlopen,
++ st_value: (Elf_Addr) &android_dlopen,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+ { st_name: 7,
+- st_value: (Elf32_Addr) &android_dlclose,
++ st_value: (Elf_Addr) &android_dlclose,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+ { st_name: 15,
+- st_value: (Elf32_Addr) &android_dlsym,
++ st_value: (Elf_Addr) &android_dlsym,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+ { st_name: 21,
+- st_value: (Elf32_Addr) &android_dlerror,
++ st_value: (Elf_Addr) &android_dlerror,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+ { st_name: 29,
+- st_value: (Elf32_Addr) &android_dladdr,
++ st_value: (Elf_Addr) &android_dladdr,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+ #ifdef ANDROID_ARM_LINKER
+ { st_name: 36,
+- st_value: (Elf32_Addr) &android_dl_unwind_find_exidx,
++ st_value: (Elf_Addr) &android_dl_unwind_find_exidx,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+ #elif defined(ANDROID_X86_LINKER)
+ { st_name: 36,
+- st_value: (Elf32_Addr) &android_dl_iterate_phdr,
++ st_value: (Elf_Addr) &android_dl_iterate_phdr,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+ #elif defined(ANDROID_SH_LINKER)
+ { st_name: 36,
+- st_value: (Elf32_Addr) &android_dl_iterate_phdr,
++ st_value: (Elf_Addr) &android_dl_iterate_phdr,
+ st_info: STB_GLOBAL << 4,
+ st_shndx: 1,
+ },
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.c
+@@ -381,10 +381,10 @@ android_dl_iterate_phdr(int (*cb)(struct
+ }
+ #endif
+
+-static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name)
++static Elf_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name)
+ {
+- Elf32_Sym *s;
+- Elf32_Sym *symtab = si->symtab;
++ Elf_Sym *s;
++ Elf_Sym *symtab = si->symtab;
+ const char *strtab = si->strtab;
+ unsigned n;
+
+@@ -426,11 +426,11 @@ static unsigned elfhash(const char *_nam
+ return h;
+ }
+
+-static Elf32_Sym *
++static Elf_Sym *
+ _do_lookup(soinfo *si, const char *name, unsigned *base)
+ {
+ unsigned elf_hash = elfhash(name);
+- Elf32_Sym *s;
++ Elf_Sym *s;
+ unsigned *d;
+ soinfo *lsi = si;
+ int i;
+@@ -502,17 +502,17 @@ done:
+ /* This is used by dl_sym(). It performs symbol lookup only within the
+ specified soinfo object and not in any of its dependencies.
+ */
+-Elf32_Sym *lookup_in_library(soinfo *si, const char *name)
++Elf_Sym *lookup_in_library(soinfo *si, const char *name)
+ {
+ return _elf_lookup(si, elfhash(name), name);
+ }
+
+ /* This is used by dl_sym(). It performs a global symbol lookup.
+ */
+-Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start)
++Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start)
+ {
+ unsigned elf_hash = elfhash(name);
+- Elf32_Sym *s = NULL;
++ Elf_Sym *s = NULL;
+ soinfo *si;
+
+ if(start == NULL) {
+@@ -553,7 +553,7 @@ soinfo *find_containing_library(const vo
+ return NULL;
+ }
+
+-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si)
++Elf_Sym *find_containing_symbol(const void *addr, soinfo *si)
+ {
+ unsigned int i;
+ unsigned soaddr = (unsigned)addr - si->base;
+@@ -561,7 +561,7 @@ Elf32_Sym *find_containing_symbol(const
+ /* Search the library's symbol table for any defined symbol which
+ * contains this address */
+ for(i=0; i<si->nchain; i++) {
+- Elf32_Sym *sym = &si->symtab[i];
++ Elf_Sym *sym = &si->symtab[i];
+
+ if(sym->st_shndx != SHN_UNDEF &&
+ soaddr >= sym->st_value &&
+@@ -576,7 +576,7 @@ Elf32_Sym *find_containing_symbol(const
+ #if 0
+ static void dump(soinfo *si)
+ {
+- Elf32_Sym *s = si->symtab;
++ Elf_Sym *s = si->symtab;
+ unsigned n;
+
+ for(n = 0; n < si->nchain; n++) {
+@@ -705,7 +705,7 @@ is_prelinked(int fd, const char *name)
+ static int
+ verify_elf_object(void *base, const char *name)
+ {
+- Elf32_Ehdr *hdr = (Elf32_Ehdr *) base;
++ Elf_Ehdr *hdr = (Elf_Ehdr *) base;
+
+ if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
+ if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
+@@ -750,8 +750,8 @@ get_lib_extents(int fd, const char *name
+ unsigned min_vaddr = 0xffffffff;
+ unsigned max_vaddr = 0;
+ unsigned char *_hdr = (unsigned char *)__hdr;
+- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr;
+- Elf32_Phdr *phdr;
++ Elf_Ehdr *ehdr = (Elf_Ehdr *)_hdr;
++ Elf_Phdr *phdr;
+ int cnt;
+
+ TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name);
+@@ -770,7 +770,7 @@ get_lib_extents(int fd, const char *name
+ TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name);
+ }
+
+- phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff);
++ phdr = (Elf_Phdr *)(_hdr + ehdr->e_phoff);
+
+ /* find the min/max p_vaddrs from all the PT_LOAD segments so we can
+ * get the range. */
+@@ -885,12 +885,12 @@ err:
+ static int
+ load_segments(int fd, void *header, soinfo *si)
+ {
+- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header;
+- Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff);
+- Elf32_Addr base = (Elf32_Addr) si->base;
++ Elf_Ehdr *ehdr = (Elf_Ehdr *)header;
++ Elf_Phdr *phdr = (Elf_Phdr *)((unsigned char *)header + ehdr->e_phoff);
++ Elf_Addr base = (Elf_Addr) si->base;
+ int cnt;
+ unsigned len;
+- Elf32_Addr tmp;
++ Elf_Addr tmp;
+ unsigned char *pbase;
+ unsigned char *extra_base;
+ unsigned extra_len;
+@@ -956,7 +956,7 @@ load_segments(int fd, void *header, soin
+ * | |
+ * _+---------------------+ page boundary
+ */
+- tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) &
++ tmp = (Elf_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) &
+ (~PAGE_MASK));
+ if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) {
+ extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp;
+@@ -1020,7 +1020,7 @@ load_segments(int fd, void *header, soin
+ phdr->p_vaddr, phdr->p_memsz);
+ goto fail;
+ }
+- si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr);
++ si->gnu_relro_start = (Elf_Addr) (base + phdr->p_vaddr);
+ si->gnu_relro_len = (unsigned) phdr->p_memsz;
+ } else {
+ #ifdef ANDROID_ARM_LINKER
+@@ -1067,11 +1067,11 @@ fail:
+ */
+ #if 0
+ static unsigned
+-get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr)
++get_wr_offset(int fd, const char *name, Elf_Ehdr *ehdr)
+ {
+- Elf32_Shdr *shdr_start;
+- Elf32_Shdr *shdr;
+- int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr);
++ Elf_Shdr *shdr_start;
++ Elf_Shdr *shdr;
++ int shdr_sz = ehdr->e_shnum * sizeof(Elf_Shdr);
+ int cnt;
+ unsigned wr_offset = 0xffffffff;
+
+@@ -1104,7 +1104,7 @@ load_library(const char *name)
+ unsigned req_base;
+ const char *bname;
+ soinfo *si = NULL;
+- Elf32_Ehdr *hdr;
++ Elf_Ehdr *hdr;
+
+ if(fd == -1) {
+ DL_ERR("Library '%s' not found", name);
+@@ -1161,8 +1161,8 @@ load_library(const char *name)
+
+ /* this might not be right. Technically, we don't even need this info
+ * once we go through 'load_segments'. */
+- hdr = (Elf32_Ehdr *)si->base;
+- si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff);
++ hdr = (Elf_Ehdr *)si->base;
++ si->phdr = (Elf_Phdr *)((unsigned char *)si->base + hdr->e_phoff);
+ si->phnum = hdr->e_phnum;
+ /**/
+
+@@ -1261,7 +1261,7 @@ unsigned unload_library(soinfo *si)
+ * in link_image. This is needed to undo the DT_NEEDED hack below.
+ */
+ if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) {
+- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK);
++ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK);
+ unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len;
+ if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0)
+ DL_ERR("%5d %s: could not undo GNU_RELRO protections. "
+@@ -1304,16 +1304,16 @@ unsigned unload_library(soinfo *si)
+ }
+
+ /* TODO: don't use unsigned for addrs below. It works, but is not
+- * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned
++ * ideal. They should probably be either uint32_t, Elf_Addr, or unsigned
+ * long.
+ */
+-static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count)
++static int reloc_library(soinfo *si, Elf_Rel *rel, unsigned count)
+ {
+- Elf32_Sym *symtab = si->symtab;
++ Elf_Sym *symtab = si->symtab;
+ const char *strtab = si->strtab;
+- Elf32_Sym *s;
++ Elf_Sym *s;
+ unsigned base;
+- Elf32_Rel *start = rel;
++ Elf_Rel *start = rel;
+ unsigned idx;
+
+ for (idx = 0; idx < count; ++idx) {
+@@ -1712,7 +1712,7 @@ static int nullify_closed_stdio (void)
+ static int link_image(soinfo *si, unsigned wr_offset)
+ {
+ unsigned *d;
+- Elf32_Phdr *phdr = si->phdr;
++ Elf_Phdr *phdr = si->phdr;
+ int phnum = si->phnum;
+
+ INFO("[ %5d linking %s ]\n", pid, si->name);
+@@ -1795,7 +1795,7 @@ static int link_image(soinfo *si, unsign
+ phdr->p_vaddr, phdr->p_memsz);
+ goto fail;
+ }
+- si->gnu_relro_start = (Elf32_Addr) (si->base + phdr->p_vaddr);
++ si->gnu_relro_start = (Elf_Addr) (si->base + phdr->p_vaddr);
+ si->gnu_relro_len = (unsigned) phdr->p_memsz;
+ }
+ }
+@@ -1822,7 +1822,7 @@ static int link_image(soinfo *si, unsign
+ si->strtab = (const char *) (si->base + *d);
+ break;
+ case DT_SYMTAB:
+- si->symtab = (Elf32_Sym *) (si->base + *d);
++ si->symtab = (Elf_Sym *) (si->base + *d);
+ break;
+ case DT_PLTREL:
+ if(*d != DT_REL) {
+@@ -1831,13 +1831,13 @@ static int link_image(soinfo *si, unsign
+ }
+ break;
+ case DT_JMPREL:
+- si->plt_rel = (Elf32_Rel*) (si->base + *d);
++ si->plt_rel = (Elf_Rel*) (si->base + *d);
+ break;
+ case DT_PLTRELSZ:
+ si->plt_rel_count = *d / 8;
+ break;
+ case DT_REL:
+- si->rel = (Elf32_Rel*) (si->base + *d);
++ si->rel = (Elf_Rel*) (si->base + *d);
+ break;
+ case DT_RELSZ:
+ si->rel_count = *d / 8;
+@@ -1869,7 +1869,7 @@ static int link_image(soinfo *si, unsign
+ pid, si->name, si->init_array);
+ break;
+ case DT_INIT_ARRAYSZ:
+- si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
++ si->init_array_count = ((unsigned)*d) / sizeof(Elf_Addr);
+ break;
+ case DT_FINI_ARRAY:
+ si->fini_array = (unsigned *)(si->base + *d);
+@@ -1877,7 +1877,7 @@ static int link_image(soinfo *si, unsign
+ pid, si->name, si->fini_array);
+ break;
+ case DT_FINI_ARRAYSZ:
+- si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
++ si->fini_array_count = ((unsigned)*d) / sizeof(Elf_Addr);
+ break;
+ case DT_PREINIT_ARRAY:
+ si->preinit_array = (unsigned *)(si->base + *d);
+@@ -1885,7 +1885,7 @@ static int link_image(soinfo *si, unsign
+ pid, si->name, si->preinit_array);
+ break;
+ case DT_PREINIT_ARRAYSZ:
+- si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr);
++ si->preinit_array_count = ((unsigned)*d) / sizeof(Elf_Addr);
+ break;
+ case DT_TEXTREL:
+ /* TODO: make use of this. */
+@@ -1987,7 +1987,7 @@ static int link_image(soinfo *si, unsign
+ #endif
+
+ if (si->gnu_relro_start != 0 && si->gnu_relro_len != 0) {
+- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK);
++ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK);
+ unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len;
+ if (mprotect((void *) start, len, PROT_READ) < 0) {
+ DL_ERR("%5d GNU_RELRO mprotect of library '%s' failed: %d (%s)\n",
+@@ -2170,7 +2170,7 @@ sanitize:
+ while(vecs[0] != 0){
+ switch(vecs[0]){
+ case AT_PHDR:
+- si->phdr = (Elf32_Phdr*) vecs[1];
++ si->phdr = (Elf_Phdr*) vecs[1];
+ break;
+ case AT_PHNUM:
+ si->phnum = (int) vecs[1];
+@@ -2190,7 +2190,7 @@ sanitize:
+ si->base = 0;
+ for ( nn = 0; nn < si->phnum; nn++ ) {
+ if (si->phdr[nn].p_type == PT_PHDR) {
+- si->base = (Elf32_Addr) si->phdr - si->phdr[nn].p_vaddr;
++ si->base = (Elf_Addr) si->phdr - si->phdr[nn].p_vaddr;
+ break;
+ }
+ }
+@@ -2303,9 +2303,9 @@ static unsigned find_linker_base(unsigne
+ */
+ unsigned __linker_init(unsigned **elfdata) {
+ unsigned linker_addr = find_linker_base(elfdata);
+- Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_addr;
+- Elf32_Phdr *phdr =
+- (Elf32_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff);
++ Elf_Ehdr *elf_hdr = (Elf_Ehdr *) linker_addr;
++ Elf_Phdr *phdr =
++ (Elf_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff);
+
+ soinfo linker_so;
+ memset(&linker_so, 0, sizeof(soinfo));
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker.h
++++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.h
+@@ -38,6 +38,26 @@
+ #define PAGE_SIZE 4096
+ #define PAGE_MASK 4095
+
++#if defined(__x86_64__)
++typedef Elf64_Ehdr Elf_Ehdr;
++typedef Elf64_Shdr Elf_Shdr;
++typedef Elf64_Sym Elf_Sym;
++typedef Elf64_Addr Elf_Addr;
++typedef Elf64_Phdr Elf_Phdr;
++typedef Elf64_Half Elf_Half;
++typedef Elf64_Rel Elf_Rel;
++typedef Elf64_Rela Elf_Rela;
++#else
++typedef Elf32_Ehdr Elf_Ehdr;
++typedef Elf32_Shdr Elf_Shdr;
++typedef Elf32_Sym Elf_Sym;
++typedef Elf32_Addr Elf_Addr;
++typedef Elf32_Phdr Elf_Phdr;
++typedef Elf32_Half Elf_Half;
++typedef Elf32_Rel Elf_Rel;
++typedef Elf32_Rela Elf_Rela;
++#endif
++
+ void debugger_init();
+ const char *addr_to_name(unsigned addr);
+
+@@ -55,10 +75,10 @@ struct link_map
+ /* needed for dl_iterate_phdr to be passed to the callbacks provided */
+ struct dl_phdr_info
+ {
+- Elf32_Addr dlpi_addr;
++ Elf_Addr dlpi_addr;
+ const char *dlpi_name;
+- const Elf32_Phdr *dlpi_phdr;
+- Elf32_Half dlpi_phnum;
++ const Elf_Phdr *dlpi_phdr;
++ Elf_Half dlpi_phnum;
+ };
+
+
+@@ -90,7 +110,7 @@ typedef struct soinfo soinfo;
+ struct soinfo
+ {
+ const char name[SOINFO_NAME_LEN];
+- Elf32_Phdr *phdr;
++ Elf_Phdr *phdr;
+ int phnum;
+ unsigned entry;
+ unsigned base;
+@@ -107,7 +127,7 @@ struct soinfo
+ unsigned flags;
+
+ const char *strtab;
+- Elf32_Sym *symtab;
++ Elf_Sym *symtab;
+
+ unsigned nbucket;
+ unsigned nchain;
+@@ -116,10 +136,10 @@ struct soinfo
+
+ unsigned *plt_got;
+
+- Elf32_Rel *plt_rel;
++ Elf_Rel *plt_rel;
+ unsigned plt_rel_count;
+
+- Elf32_Rel *rel;
++ Elf_Rel *rel;
+ unsigned rel_count;
+
+ unsigned *preinit_array;
+@@ -144,7 +164,7 @@ struct soinfo
+
+ int constructors_called;
+
+- Elf32_Addr gnu_relro_start;
++ Elf_Addr gnu_relro_start;
+ unsigned gnu_relro_len;
+
+ };
+@@ -202,10 +222,10 @@ extern soinfo libdl_info;
+
+ soinfo *find_library(const char *name);
+ unsigned unload_library(soinfo *si);
+-Elf32_Sym *lookup_in_library(soinfo *si, const char *name);
+-Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start);
++Elf_Sym *lookup_in_library(soinfo *si, const char *name);
++Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start);
+ soinfo *find_containing_library(const void *addr);
+-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si);
++Elf_Sym *find_containing_symbol(const void *addr, soinfo *si);
+ const char *linker_get_error(void);
+ void call_constructors_recursive(soinfo *si);
+
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker_format.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker_format.c
+@@ -268,7 +268,7 @@ static int log_vprint(int prio, const ch
+ result = vformat_buffer(buf, sizeof buf, fmt, args);
+
+ if (log_fd < 0) {
+- log_fd = open("/dev/log/main", O_WRONLY);
++ log_fd = open("/dev/alog/main", O_WRONLY);
+ if (log_fd < 0) {
+ log_fd = fileno(stdout); // kernel doesn't have android log
+ return result;
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/configure.ac
++++ libhybris-0.1.0+git20131207+e452e83/hybris/configure.ac
+@@ -184,6 +184,8 @@ AC_CONFIG_FILES([
+ input/libis.pc
+ camera/Makefile
+ camera/libcamera.pc
++ media/Makefile
++ media/libmedia.pc
+ include/Makefile
+ utils/Makefile
+ tests/Makefile
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/hardware/hardware.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/hardware/hardware.c
+@@ -17,6 +17,7 @@
+
+ #include <dlfcn.h>
+ #include <stddef.h>
++#include <errno.h>
+ #include <android/hardware/hardware.h>
+ #include <hybris/internal/binding.h>
+
+@@ -26,15 +27,20 @@ static int (*_hw_get_module)(const char
+
+ static int (*_hw_get_module_by_class)(const char *class_id, const char *inst, const struct hw_module_t **module) = NULL;
+
+-#define HARDWARE_DLSYM(fptr, sym) do { if (_libhardware == NULL) { _init_lib_hardware(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libhardware, sym); } } while (0)
++#define HARDWARE_DLSYM(fptr, sym) do { if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libhardware, sym); } } while (0)
+
+-static void _init_lib_hardware()
++static void *_init_lib_hardware()
+ {
+- _libhardware = (void *) android_dlopen("/system/lib/libhardware.so", RTLD_LAZY);
++ if (!_libhardware)
++ _libhardware = (void *) android_dlopen("/system/lib/libhardware.so", RTLD_LAZY);
++ return _libhardware;
+ }
+
+ int hw_get_module(const char *id, const struct hw_module_t **module)
+ {
++ if (!_init_lib_hardware())
++ return -EINVAL;
++
+ HARDWARE_DLSYM(&_hw_get_module, "hw_get_module");
+ return (*_hw_get_module)(id, module);
+ }
+@@ -42,6 +48,9 @@ int hw_get_module(const char *id, const
+ int hw_get_module_by_class(const char *class_id, const char *inst,
+ const struct hw_module_t **module)
+ {
++ if (!_init_lib_hardware())
++ return -EINVAL;
++
+ HARDWARE_DLSYM(&_hw_get_module_by_class, "hw_get_module_by_class");
+ return (*_hw_get_module_by_class)(class_id, inst, module);
+ }
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/Makefile.am
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/Makefile.am
+@@ -65,6 +65,15 @@ propertiesincludedir = $(includedir)/hyb
+ propertiesinclude_HEADERS = \
+ hybris/properties/properties.h
+
++mediaincludedir = $(includedir)/hybris/media
++mediainclude_HEADERS = \
++ hybris/media/media_compatibility_layer.h \
++ hybris/media/media_codec_layer.h \
++ hybris/media/media_codec_list.h \
++ hybris/media/media_format_layer.h \
++ hybris/media/surface_texture_client_hybris.h \
++ hybris/media/recorder_compatibility_layer.h
++
+ dlfcnincludedir = $(includedir)/hybris/dlfcn
+ dlfcninclude_HEADERS = \
+ hybris/dlfcn/dlfcn.h
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/input/input_stack_compatibility_layer.h
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/input/input_stack_compatibility_layer.h
+@@ -109,6 +109,7 @@ extern "C" {
+ int input_area_height;
+ };
+
++ int android_input_check_availability();
+ void android_input_stack_initialize(
+ struct AndroidEventListener* listener,
+ struct InputStackConfiguration* input_stack_configuration);
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/internal/camera_control.h
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/camera_control.h
+@@ -19,7 +19,11 @@
+
+ #include <camera/Camera.h>
+ #include <camera/CameraParameters.h>
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
+ #include <gui/SurfaceTexture.h>
++#else
++#include <gui/GLConsumer.h>
++#endif
+
+ #include <stdint.h>
+ #include <unistd.h>
+@@ -31,15 +35,22 @@ extern "C" {
+ struct CameraControlListener;
+
+ struct CameraControl : public android::CameraListener,
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
+ public android::SurfaceTexture::FrameAvailableListener
++#else
++ public android::GLConsumer::FrameAvailableListener
++#endif
+ {
+ android::Mutex guard;
+ CameraControlListener* listener;
+ android::sp<android::Camera> camera;
+ android::CameraParameters camera_parameters;
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2
+ android::sp<android::SurfaceTexture> preview_texture;
+-
+- // From android::SurfaceTexture::FrameAvailableListener
++#else
++ android::sp<android::GLConsumer> preview_texture;
++#endif
++ // From android::SurfaceTexture/GLConsumer::FrameAvailableListener
+ void onFrameAvailable();
+
+ // From android::CameraListener
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h
+@@ -25,6 +25,7 @@
+
+ #include <utils/misc.h>
+
++#include <gui/Surface.h>
+ #include <gui/SurfaceComposerClient.h>
+ #include <ui/PixelFormat.h>
+ #include <ui/Region.h>
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_codec_layer.h
+@@ -0,0 +1,93 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#ifndef MEDIA_CODEC_LAYER_H_
++#define MEDIA_CODEC_LAYER_H_
++
++#include <stdint.h>
++#include <unistd.h>
++
++#ifdef SIMPLE_PLAYER
++#include <media/stagefright/MediaCodec.h>
++#endif
++
++#include <hybris/media/media_format_layer.h>
++#include <hybris/media/surface_texture_client_hybris.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ typedef void* MediaCodecDelegate;
++
++ typedef void (*on_texture_needs_update)(void *context);
++ void media_codec_set_texture_needs_update_cb(MediaCodecDelegate delegate, on_texture_needs_update cb, void *context);
++
++ MediaCodecDelegate media_codec_create_by_codec_name(const char *name);
++ MediaCodecDelegate media_codec_create_by_codec_type(const char *type);
++
++#ifdef SIMPLE_PLAYER
++ android::MediaCodec* media_codec_get(MediaCodecDelegate delegate);
++#endif
++
++ void media_codec_delegate_destroy(MediaCodecDelegate delegate);
++ void media_codec_delegate_ref(MediaCodecDelegate delegate);
++ void media_codec_delegate_unref(MediaCodecDelegate delegate);
++
++#ifdef SIMPLE_PLAYER
++ int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, void *nativeWindow, uint32_t flags);
++#else
++ int media_codec_configure(MediaCodecDelegate delegate, MediaFormat format, SurfaceTextureClientHybris stc, uint32_t flags);
++#endif
++ int media_codec_set_surface_texture_client(MediaCodecDelegate delegate, SurfaceTextureClientHybris stc);
++
++ int media_codec_queue_csd(MediaCodecDelegate delegate, MediaFormat format);
++ int media_codec_start(MediaCodecDelegate delegate);
++ int media_codec_stop(MediaCodecDelegate delegate);
++ int media_codec_release(MediaCodecDelegate delegate);
++ int media_codec_flush(MediaCodecDelegate delegate);
++ size_t media_codec_get_input_buffers_size(MediaCodecDelegate delegate);
++ uint8_t *media_codec_get_nth_input_buffer(MediaCodecDelegate delegate, size_t n);
++ size_t media_codec_get_nth_input_buffer_capacity(MediaCodecDelegate delegate, size_t n);
++ size_t media_codec_get_output_buffers_size(MediaCodecDelegate delegate);
++ uint8_t *media_codec_get_nth_output_buffer(MediaCodecDelegate delegate, size_t n);
++ size_t media_codec_get_nth_output_buffer_capacity(MediaCodecDelegate delegate, size_t n);
++
++ struct _MediaCodecBufferInfo
++ {
++ size_t index;
++ size_t offset;
++ size_t size;
++ int64_t presentation_time_us;
++ uint32_t flags;
++ uint8_t render_retries;
++ };
++ typedef struct _MediaCodecBufferInfo MediaCodecBufferInfo;
++
++ int media_codec_dequeue_output_buffer(MediaCodecDelegate delegate, MediaCodecBufferInfo *info, int64_t timeout_us);
++ int media_codec_queue_input_buffer(MediaCodecDelegate delegate, const MediaCodecBufferInfo *info);
++ int media_codec_dequeue_input_buffer(MediaCodecDelegate delegate, size_t *index, int64_t timeout_us);
++ int media_codec_release_output_buffer(MediaCodecDelegate delegate, size_t index, uint8_t render);
++
++ MediaFormat media_codec_get_output_format(MediaCodecDelegate delegate);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // MEDIA_CODEC_LAYER_H_
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_codec_list.h
+@@ -0,0 +1,56 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#ifndef MEDIA_CODEC_LIST_PRIV_H_
++#define MEDIA_CODEC_LIST_PRIV_H_
++
++#include <stddef.h>
++#include <stdbool.h>
++#include <unistd.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ ssize_t media_codec_list_find_codec_by_type(const char *type, bool encoder, size_t startIndex);
++ ssize_t media_codec_list_find_codec_by_name(const char *name);
++ size_t media_codec_list_count_codecs();
++ void media_codec_list_get_codec_info_at_id(size_t index);
++ const char *media_codec_list_get_codec_name(size_t index);
++ bool media_codec_list_is_encoder(size_t index);
++ size_t media_codec_list_get_num_supported_types(size_t index);
++ size_t media_codec_list_get_nth_supported_type_len(size_t index, size_t n);
++ int media_codec_list_get_nth_supported_type(size_t index, char *type, size_t n);
++
++ struct _profile_level
++ {
++ uint32_t profile;
++ uint32_t level;
++ };
++ typedef struct _profile_level profile_level;
++
++ size_t media_codec_list_get_num_profile_levels(size_t index, const char*);
++ size_t media_codec_list_get_num_color_formats(size_t index, const char*);
++ int media_codec_list_get_nth_codec_profile_level(size_t index, const char *type, profile_level *pro_level, size_t n);
++ int media_codec_list_get_codec_color_formats(size_t index, const char *type, uint32_t *color_formats);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // MEDIA_CODEC_LIST_PRIV_H_
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_compatibility_layer.h
+@@ -0,0 +1,75 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#ifndef MEDIA_COMPATIBILITY_LAYER_H_
++#define MEDIA_COMPATIBILITY_LAYER_H_
++
++#include <stdint.h>
++#include <unistd.h>
++#include <stdbool.h>
++
++#include <GLES2/gl2.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ // Common compat calls
++ int media_compat_check_availability();
++
++ // Callback types
++ typedef void (*on_msg_set_video_size)(int height, int width, void *context);
++ typedef void (*on_video_texture_needs_update)(void *context);
++ typedef void (*on_msg_error)(void *context);
++ typedef void (*on_playback_complete)(void *context);
++ typedef void (*on_media_prepared)(void *context);
++
++ struct MediaPlayerWrapper;
++
++ // ----- Start of C API ----- //
++
++ // Callback setters
++ void android_media_set_video_size_cb(struct MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context);
++ void android_media_set_video_texture_needs_update_cb(struct MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context);
++ void android_media_set_error_cb(struct MediaPlayerWrapper *mp, on_msg_error cb, void *context);
++ void android_media_set_playback_complete_cb(struct MediaPlayerWrapper *mp, on_playback_complete cb, void *context);
++ void android_media_set_media_prepared_cb(struct MediaPlayerWrapper *mp, on_media_prepared cb, void *context);
++
++ // Main player control API
++ struct MediaPlayerWrapper *android_media_new_player();
++ int android_media_set_data_source(struct MediaPlayerWrapper *mp, const char* url);
++ int android_media_set_preview_texture(struct MediaPlayerWrapper *mp, int texture_id);
++ void android_media_update_surface_texture(struct MediaPlayerWrapper *mp);
++ void android_media_surface_texture_get_transformation_matrix(struct MediaPlayerWrapper *mp, GLfloat*matrix);
++ int android_media_play(struct MediaPlayerWrapper *mp);
++ int android_media_pause(struct MediaPlayerWrapper *mp);
++ int android_media_stop(struct MediaPlayerWrapper *mp);
++ bool android_media_is_playing(struct MediaPlayerWrapper *mp);
++
++ int android_media_seek_to(struct MediaPlayerWrapper *mp, int msec);
++ int android_media_get_current_position(struct MediaPlayerWrapper *mp, int *msec);
++ int android_media_get_duration(struct MediaPlayerWrapper *mp, int *msec);
++
++ int android_media_get_volume(struct MediaPlayerWrapper *mp, int *volume);
++ int android_media_set_volume(struct MediaPlayerWrapper *mp, int volume);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // MEDIA_COMPATIBILITY_LAYER_H_
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_format_layer.h
+@@ -0,0 +1,58 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#ifndef MEDIA_FORMAT_LAYER_H_
++#define MEDIA_FORMAT_LAYER_H_
++
++#include <stddef.h>
++#include <unistd.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ typedef void* MediaFormat;
++
++ MediaFormat media_format_create_video_format(const char *mime, int32_t width, int32_t height, int64_t duration_us, int32_t max_input_size);
++
++ void media_format_destroy(MediaFormat format);
++ void media_format_ref(MediaFormat format);
++ void media_format_unref(MediaFormat format);
++
++ void media_format_set_byte_buffer(MediaFormat format, const char *key, uint8_t *data, size_t size);
++
++ const char* media_format_get_mime(MediaFormat format);
++ int64_t media_format_get_duration_us(MediaFormat format);
++ int32_t media_format_get_width(MediaFormat format);
++ int32_t media_format_get_height(MediaFormat format);
++ int32_t media_format_get_max_input_size(MediaFormat format);
++ int32_t media_format_get_stride(MediaFormat format);
++ int32_t media_format_get_slice_height(MediaFormat format);
++ int32_t media_format_get_color_format(MediaFormat format);
++ int32_t media_format_get_crop_left(MediaFormat format);
++ int32_t media_format_get_crop_right(MediaFormat format);
++ int32_t media_format_get_crop_top(MediaFormat format);
++ int32_t media_format_get_crop_bottom(MediaFormat format);
++
++ // TODO: Add getter for CSD buffer
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // MEDIA_FORMAT_LAYER_H_
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/recorder_compatibility_layer.h
+@@ -0,0 +1,126 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#ifndef RECORDER_COMPATIBILITY_LAYER_H_
++#define RECORDER_COMPATIBILITY_LAYER_H_
++
++#include <stdint.h>
++#include <unistd.h>
++#include <stdint.h>
++#include <stdbool.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ struct MediaRecorderWrapper;
++ struct CameraControl;
++
++ // values are from andoid /frameworks/av/include/media/mediarecorder.h
++ typedef enum
++ {
++ ANDROID_VIDEO_SOURCE_DEFAULT = 0,
++ ANDROID_VIDEO_SOURCE_CAMERA = 1,
++ ANDROID_VIDEO_SOURCE_GRALLOC_BUFFER = 2
++ } VideoSource;
++
++ // values are from andoid /system/core/include/system/audio.h
++ typedef enum
++ {
++ ANDROID_AUDIO_SOURCE_DEFAULT = 0,
++ ANDROID_AUDIO_SOURCE_MIC = 1,
++ ANDROID_AUDIO_SOURCE_VOICE_UPLINK = 2,
++ ANDROID_AUDIO_SOURCE_VOICE_DOWNLINK = 3,
++ ANDROID_AUDIO_SOURCE_VOICE_CALL = 4,
++ ANDROID_AUDIO_SOURCE_CAMCORDER = 5,
++ ANDROID_AUDIO_SOURCE_VOICE_RECOGNITION = 6,
++ ANDROID_AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
++ ANDROID_AUDIO_SOURCE_REMOTE_SUBMIX = 8,
++ ANDROID_AUDIO_SOURCE_CNT,
++ ANDROID_AUDIO_SOURCE_MAX = ANDROID_AUDIO_SOURCE_CNT - 1
++ } AudioSource;
++
++ // values are from andoid /frameworks/av/include/media/mediarecorder.h
++ typedef enum
++ {
++ ANDROID_OUTPUT_FORMAT_DEFAULT = 0,
++ ANDROID_OUTPUT_FORMAT_THREE_GPP = 1,
++ ANDROID_OUTPUT_FORMAT_MPEG_4 = 2,
++ ANDROID_OUTPUT_FORMAT_AUDIO_ONLY_START = 3,
++ /* These are audio only file formats */
++ ANDROID_OUTPUT_FORMAT_RAW_AMR = 3, //to be backward compatible
++ ANDROID_OUTPUT_FORMAT_AMR_NB = 3,
++ ANDROID_OUTPUT_FORMAT_AMR_WB = 4,
++ ANDROID_OUTPUT_FORMAT_AAC_ADIF = 5,
++ ANDROID_OUTPUT_FORMAT_AAC_ADTS = 6,
++ /* Stream over a socket, limited to a single stream */
++ ANDROID_OUTPUT_FORMAT_RTP_AVP = 7,
++ /* H.264/AAC data encapsulated in MPEG2/TS */
++ ANDROID_OUTPUT_FORMAT_MPEG2TS = 8
++ } OutputFormat;
++
++ // values are from andoid /frameworks/av/include/media/mediarecorder.h
++ typedef enum
++ {
++ ANDROID_VIDEO_ENCODER_DEFAULT = 0,
++ ANDROID_VIDEO_ENCODER_H263 = 1,
++ ANDROID_VIDEO_ENCODER_H264 = 2,
++ ANDROID_VIDEO_ENCODER_MPEG_4_SP = 3
++ } VideoEncoder;
++
++ // values are from andoid /frameworks/av/include/media/mediarecorder.h
++ typedef enum
++ {
++ ANDROID_AUDIO_ENCODER_DEFAULT = 0,
++ ANDROID_AUDIO_ENCODER_AMR_NB = 1,
++ ANDROID_AUDIO_ENCODER_AMR_WB = 2,
++ ANDROID_AUDIO_ENCODER_AAC = 3,
++ ANDROID_AUDIO_ENCODER_HE_AAC = 4,
++ ANDROID_AUDIO_ENCODER_AAC_ELD = 5
++ } AudioEncoder;
++
++ // Callback types
++ typedef void (*on_recorder_msg_error)(void *context);
++
++ // Callback setters
++ void android_recorder_set_error_cb(struct MediaRecorderWrapper *mr, on_recorder_msg_error cb,
++ void *context);
++
++ // Main recorder control API
++ struct MediaRecorderWrapper *android_media_new_recorder();
++ int android_recorder_initCheck(struct MediaRecorderWrapper *mr);
++ int android_recorder_setCamera(struct MediaRecorderWrapper *mr, struct CameraControl* control);
++ int android_recorder_setVideoSource(struct MediaRecorderWrapper *mr, VideoSource vs);
++ int android_recorder_setAudioSource(struct MediaRecorderWrapper *mr, AudioSource as);
++ int android_recorder_setOutputFormat(struct MediaRecorderWrapper *mr, OutputFormat of);
++ int android_recorder_setVideoEncoder(struct MediaRecorderWrapper *mr, VideoEncoder ve);
++ int android_recorder_setAudioEncoder(struct MediaRecorderWrapper *mr, AudioEncoder ae);
++ int android_recorder_setOutputFile(struct MediaRecorderWrapper *mr, int fd);
++ int android_recorder_setVideoSize(struct MediaRecorderWrapper *mr, int width, int height);
++ int android_recorder_setVideoFrameRate(struct MediaRecorderWrapper *mr, int frames_per_second);
++ int android_recorder_setParameters(struct MediaRecorderWrapper *mr, const char* parameters);
++ int android_recorder_start(struct MediaRecorderWrapper *mr);
++ int android_recorder_stop(struct MediaRecorderWrapper *mr);
++ int android_recorder_prepare(struct MediaRecorderWrapper *mr);
++ int android_recorder_reset(struct MediaRecorderWrapper *mr);
++ int android_recorder_close(struct MediaRecorderWrapper *mr);
++ int android_recorder_release(struct MediaRecorderWrapper *mr);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/surface_texture_client_hybris.h
+@@ -0,0 +1,63 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ */
++
++#ifndef SURFACE_TEXTURE_CLIENT_HYBRIS_H_
++#define SURFACE_TEXTURE_CLIENT_HYBRIS_H_
++
++#include <stdint.h>
++#include <unistd.h>
++
++#include <EGL/egl.h>
++
++#ifdef __ARM_PCS_VFP
++#define FP_ATTRIB __attribute__((pcs("aapcs")))
++#else
++#define FP_ATTRIB
++#endif
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ // Taken from native_window.h
++ enum {
++ WINDOW_FORMAT_RGBA_8888 = 1,
++ WINDOW_FORMAT_RGBX_8888 = 2,
++ WINDOW_FORMAT_RGB_565 = 4,
++ };
++
++ typedef void* SurfaceTextureClientHybris;
++
++ //SurfaceTextureClientHybris surface_texture_client_get_instance();
++ SurfaceTextureClientHybris surface_texture_client_create(EGLNativeWindowType native_window);
++ SurfaceTextureClientHybris surface_texture_client_create_by_id(unsigned int texture_id);
++ uint8_t surface_texture_client_is_ready_for_rendering(SurfaceTextureClientHybris stc);
++ uint8_t surface_texture_client_hardware_rendering(SurfaceTextureClientHybris stc);
++ void surface_texture_client_set_hardware_rendering(SurfaceTextureClientHybris stc, uint8_t hardware_rendering);
++ void surface_texture_client_get_transformation_matrix(SurfaceTextureClientHybris stc, float *matrix) FP_ATTRIB;
++ void surface_texture_client_update_texture(SurfaceTextureClientHybris stc);
++ void surface_texture_client_destroy(SurfaceTextureClientHybris stc);
++ void surface_texture_client_ref(SurfaceTextureClientHybris stc);
++ void surface_texture_client_unref(SurfaceTextureClientHybris stc);
++ void surface_texture_client_set_surface_texture(SurfaceTextureClientHybris stc, EGLNativeWindowType native_window);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // SURFACE_TEXTURE_CLIENT_HYBRIS_H_
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/ui/ui_compatibility_layer.h
++++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/ui/ui_compatibility_layer.h
+@@ -50,8 +50,10 @@ extern "C" {
+
+ void* graphic_buffer_get_native_buffer(struct graphic_buffer *buffer);
+
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
+ void graphic_buffer_set_index(struct graphic_buffer *buffer, int index);
+ int graphic_buffer_get_index(struct graphic_buffer *buffer);
++#endif
+
+ int graphic_buffer_init_check(struct graphic_buffer *buffer);
+
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/input/is.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/input/is.c
+@@ -28,6 +28,14 @@
+
+ HYBRIS_LIBRARY_INITIALIZE(is, COMPAT_LIBRARY_PATH);
+
++int android_input_check_availability()
++{
++ /* Both are defined via HYBRIS_LIBRARY_INITIALIZE */
++ if (!is_handle)
++ hybris_is_initialize();
++ return is_handle ? 1 : 0;
++}
++
+ HYBRIS_IMPLEMENT_VOID_FUNCTION2(is, android_input_stack_initialize,
+ struct AndroidEventListener*, struct InputStackConfiguration*);
+ HYBRIS_IMPLEMENT_VOID_FUNCTION0(is, android_input_stack_start);
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/media/Makefile.am
+@@ -0,0 +1,17 @@
++lib_LTLIBRARIES = \
++ libmedia.la
++
++libmedia_la_SOURCES = media.c
++libmedia_la_CFLAGS = -I$(top_srcdir)/include
++if WANT_TRACE
++libmedia_la_CFLAGS += -DDEBUG
++endif
++if WANT_DEBUG
++libmedia_la_CFLAGS += -ggdb -O0
++endif
++libmedia_la_LDFLAGS = \
++ $(top_builddir)/common/libhybris-common.la \
++ -version-info "1":"0":"0"
++
++pkgconfigdir = $(libdir)/pkgconfig
++pkgconfig_DATA = libmedia.pc
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/media/libmedia.pc.in
+@@ -0,0 +1,10 @@
++prefix=@prefix@
++exec_prefix=${prefix}
++libdir=@libdir@
++includedir=@includedir@
++
++Name: hybris-media
++Description: libhybris media library
++Version: @VERSION@
++Libs: -L${libdir} -lhybris-common -lmedia
++Cflags: -I${includedir}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/media/media.c
+@@ -0,0 +1,272 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
++ */
++
++#include <assert.h>
++#include <dlfcn.h>
++#include <stddef.h>
++#include <stdbool.h>
++
++#include <hybris/internal/binding.h>
++#include <hybris/media/media_compatibility_layer.h>
++#include <hybris/media/recorder_compatibility_layer.h>
++#include <hybris/media/media_codec_layer.h>
++#include <hybris/media/media_codec_list.h>
++#include <hybris/media/media_format_layer.h>
++#include <hybris/media/surface_texture_client_hybris.h>
++
++#define COMPAT_LIBRARY_PATH "/system/lib/libmedia_compat_layer.so"
++
++#ifdef __ARM_PCS_VFP
++#define FP_ATTRIB __attribute__((pcs("aapcs")))
++#else
++#define FP_ATTRIB
++#endif
++
++HYBRIS_LIBRARY_INITIALIZE(media, COMPAT_LIBRARY_PATH);
++
++int media_compat_check_availability()
++{
++ /* Both are defined via HYBRIS_LIBRARY_INITIALIZE */
++ hybris_media_initialize();
++ return media_handle ? 1 : 0;
++}
++
++HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaPlayerWrapper*,
++ android_media_new_player);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, android_media_update_surface_texture,
++ struct MediaPlayerWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_play,
++ struct MediaPlayerWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_pause,
++ struct MediaPlayerWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_stop,
++ struct MediaPlayerWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, bool, android_media_is_playing,
++ struct MediaPlayerWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_seek_to,
++ struct MediaPlayerWrapper*, int);
++
++// Setters
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_data_source,
++ struct MediaPlayerWrapper*, const char*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_preview_texture,
++ struct MediaPlayerWrapper*, int);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_volume,
++ struct MediaPlayerWrapper*, int);
++
++// Getters
++HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, android_media_surface_texture_get_transformation_matrix,
++ struct MediaPlayerWrapper*, float*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_current_position,
++ struct MediaPlayerWrapper*, int*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_duration,
++ struct MediaPlayerWrapper*, int*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_volume,
++ struct MediaPlayerWrapper*, int*);
++
++// Callbacks
++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_video_size_cb,
++ struct MediaPlayerWrapper*, on_msg_set_video_size, void*);
++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_video_texture_needs_update_cb,
++ struct MediaPlayerWrapper*, on_video_texture_needs_update, void*);
++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_error_cb,
++ struct MediaPlayerWrapper*, on_msg_error, void*);
++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_playback_complete_cb,
++ struct MediaPlayerWrapper*, on_playback_complete, void*);
++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_media_prepared_cb,
++ struct MediaPlayerWrapper*, on_media_prepared, void*);
++
++// Media Codecs
++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaCodecDelegate,
++ media_codec_create_by_codec_name, const char*);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_destroy,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_ref,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_unref,
++ MediaCodecDelegate);
++
++#ifdef SIMPLE_PLAYER
++HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_configure,
++ MediaCodecDelegate, MediaFormat, void*, uint32_t);
++#else
++HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_configure,
++ MediaCodecDelegate, MediaFormat, SurfaceTextureClientHybris, uint32_t);
++#endif
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_set_surface_texture_client,
++ MediaCodecDelegate, SurfaceTextureClientHybris);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_queue_csd,
++ MediaCodecDelegate, MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_start,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_stop,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_release,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_flush,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_get_input_buffers_size,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_FUNCTION2(media, uint8_t*, media_codec_get_nth_input_buffer,
++ MediaCodecDelegate, size_t);
++HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_get_nth_input_buffer_capacity,
++ MediaCodecDelegate, size_t);
++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_get_output_buffers_size,
++ MediaCodecDelegate);
++HYBRIS_IMPLEMENT_FUNCTION2(media, uint8_t*, media_codec_get_nth_output_buffer,
++ MediaCodecDelegate, size_t);
++HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_get_nth_output_buffer_capacity,
++ MediaCodecDelegate, size_t);
++HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_dequeue_output_buffer,
++ MediaCodecDelegate, MediaCodecBufferInfo*, int64_t);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_queue_input_buffer,
++ MediaCodecDelegate, const MediaCodecBufferInfo*);
++HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_dequeue_input_buffer,
++ MediaCodecDelegate, size_t*, int64_t);
++HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_release_output_buffer,
++ MediaCodecDelegate, size_t, uint8_t);
++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaFormat, media_codec_get_output_format,
++ MediaCodecDelegate);
++
++HYBRIS_IMPLEMENT_FUNCTION3(media, ssize_t, media_codec_list_find_codec_by_type,
++ const char*, bool, size_t);
++HYBRIS_IMPLEMENT_FUNCTION1(media, ssize_t, media_codec_list_find_codec_by_name,
++ const char *);
++HYBRIS_IMPLEMENT_FUNCTION0(media, size_t, media_codec_list_count_codecs);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_list_get_codec_info_at_id,
++ size_t);
++HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_codec_list_get_codec_name,
++ size_t);
++HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_list_is_encoder,
++ size_t);
++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_list_get_num_supported_types,
++ size_t);
++HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_nth_supported_type_len,
++ size_t, size_t);
++HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_list_get_nth_supported_type,
++ size_t, char *, size_t);
++HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_num_profile_levels,
++ size_t, const char*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_num_color_formats,
++ size_t, const char*);
++HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_list_get_nth_codec_profile_level,
++ size_t, const char*, profile_level*, size_t);
++HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_list_get_codec_color_formats,
++ size_t, const char*, uint32_t*);
++
++HYBRIS_IMPLEMENT_FUNCTION5(media, MediaFormat, media_format_create_video_format,
++ const char*, int32_t, int32_t, int64_t, int32_t);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_destroy,
++ MediaFormat);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_ref,
++ MediaFormat);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_unref,
++ MediaFormat);
++HYBRIS_IMPLEMENT_VOID_FUNCTION4(media, media_format_set_byte_buffer,
++ MediaFormat, const char*, uint8_t*, size_t);
++HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_format_get_mime,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int64_t, media_format_get_duration_us,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_width,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_height,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_max_input_size,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_stride,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_slice_height,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_color_format,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_left,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_right,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_top,
++ MediaFormat);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_bottom,
++ MediaFormat);
++
++// SurfaceTextureClientHybris
++HYBRIS_IMPLEMENT_FUNCTION1(media, SurfaceTextureClientHybris,
++ surface_texture_client_create, EGLNativeWindowType);
++HYBRIS_IMPLEMENT_FUNCTION1(media, SurfaceTextureClientHybris,
++ surface_texture_client_create_by_id, unsigned int);
++HYBRIS_IMPLEMENT_FUNCTION1(media, uint8_t,
++ surface_texture_client_is_ready_for_rendering, SurfaceTextureClientHybris);
++HYBRIS_IMPLEMENT_FUNCTION1(media, uint8_t,
++ surface_texture_client_hardware_rendering, SurfaceTextureClientHybris);
++HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_set_hardware_rendering,
++ SurfaceTextureClientHybris, uint8_t);
++HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_get_transformation_matrix,
++ SurfaceTextureClientHybris, GLfloat*);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_update_texture,
++ SurfaceTextureClientHybris);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_destroy,
++ SurfaceTextureClientHybris);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_ref,
++ SurfaceTextureClientHybris);
++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_unref,
++ SurfaceTextureClientHybris);
++HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_set_surface_texture,
++ SurfaceTextureClientHybris, EGLNativeWindowType);
++
++// Recorder
++HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaRecorderWrapper*,
++ android_media_new_recorder);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_initCheck,
++ struct MediaRecorderWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setCamera,
++ struct MediaRecorderWrapper*, struct CameraControl*);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoSource,
++ struct MediaRecorderWrapper*, VideoSource);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setAudioSource,
++ struct MediaRecorderWrapper*, AudioSource);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setOutputFormat,
++ struct MediaRecorderWrapper*, OutputFormat);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoEncoder,
++ struct MediaRecorderWrapper*, VideoEncoder);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setAudioEncoder,
++ struct MediaRecorderWrapper*, AudioEncoder);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setOutputFile,
++ struct MediaRecorderWrapper*, int);
++HYBRIS_IMPLEMENT_FUNCTION3(media, int, android_recorder_setVideoSize,
++ struct MediaRecorderWrapper*, int, int);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoFrameRate,
++ struct MediaRecorderWrapper*, int);
++HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setParameters,
++ struct MediaRecorderWrapper*, const char*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_start,
++ struct MediaRecorderWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_stop,
++ struct MediaRecorderWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_prepare,
++ struct MediaRecorderWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_reset,
++ struct MediaRecorderWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_close,
++ struct MediaRecorderWrapper*);
++HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_release,
++ struct MediaRecorderWrapper*);
++
++// Recorder Callbacks
++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_recorder_set_error_cb,
++ struct MediaRecorderWrapper *, on_recorder_msg_error, void*);
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/Makefile.am
++++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/Makefile.am
+@@ -7,6 +7,8 @@ bin_PROGRAMS = \
+ test_sensors \
+ test_input \
+ test_camera \
++ test_media \
++ test_recorder \
+ test_gps
+
+ if HAS_ANDROID_4_2_0
+@@ -140,6 +142,28 @@ test_camera_LDADD = \
+ $(top_builddir)/camera/libcamera.la \
+ $(top_builddir)/input/libis.la
+
++test_media_SOURCES = test_media.c
++test_media_CFLAGS = \
++ -I$(top_srcdir)/include
++test_media_LDADD = \
++ $(top_builddir)/common/libhybris-common.la \
++ $(top_builddir)/egl/libEGL.la \
++ $(top_builddir)/glesv2/libGLESv2.la \
++ $(top_builddir)/media/libmedia.la \
++ $(top_builddir)/sf/libsf.la
++
++test_recorder_SOURCES = test_recorder.c
++test_recorder_CFLAGS = \
++ -I$(top_srcdir)/include
++test_recorder_LDADD = \
++ $(top_builddir)/common/libhybris-common.la \
++ $(top_builddir)/egl/libEGL.la \
++ $(top_builddir)/glesv2/libGLESv2.la \
++ $(top_builddir)/media/libmedia.la \
++ $(top_builddir)/camera/libcamera.la \
++ $(top_builddir)/input/libis.la \
++ $(top_builddir)/sf/libsf.la
++
+ test_gps_SOURCES = test_gps.c
+ test_gps_CFLAGS = -pthread \
+ -I$(top_srcdir)/include \
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_media.c
+@@ -0,0 +1,373 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
++ */
++
++#include <hybris/media/media_compatibility_layer.h>
++#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h>
++
++#include <EGL/egl.h>
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++
++#include <assert.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdbool.h>
++#include <limits.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++
++enum {
++ OK = 0,
++ NO_ERROR = 0,
++};
++
++static float DestWidth = 0.0, DestHeight = 0.0;
++// Actual video dimmensions
++static int Width = 0, Height = 0;
++
++static GLuint gProgram;
++static GLuint gaPositionHandle, gaTexHandle, gsTextureHandle, gmTexMatrix;
++
++static GLfloat positionCoordinates[8];
++
++struct MediaPlayerWrapper *player = NULL;
++
++void calculate_position_coordinates()
++{
++ // Assuming cropping output for now
++ float x = 1, y = 1;
++
++ // Black borders
++ x = (float) (Width / DestWidth);
++ y = (float) (Height / DestHeight);
++
++ // Make the larger side be 1
++ if (x > y) {
++ y /= x;
++ x = 1;
++ } else {
++ x /= y;
++ y = 1;
++ }
++
++ positionCoordinates[0] = -x;
++ positionCoordinates[1] = y;
++ positionCoordinates[2] = -x;
++ positionCoordinates[3] = -y;
++ positionCoordinates[4] = x;
++ positionCoordinates[5] = -y;
++ positionCoordinates[6] = x;
++ positionCoordinates[7] = y;
++}
++
++struct ClientWithSurface
++{
++ struct SfClient* client;
++ struct SfSurface* surface;
++};
++
++struct ClientWithSurface client_with_surface(bool setup_surface_with_egl)
++{
++ struct ClientWithSurface cs;
++
++ cs.client = sf_client_create();
++
++ if (!cs.client) {
++ printf("Problem creating client ... aborting now.");
++ return cs;
++ }
++
++ static const size_t primary_display = 0;
++
++ DestWidth = sf_get_display_width(primary_display);
++ DestHeight = sf_get_display_height(primary_display);
++ printf("Primary display width: %f, height: %f\n", DestWidth, DestHeight);
++
++ SfSurfaceCreationParameters params = {
++ 0,
++ 0,
++ DestWidth,
++ DestHeight,
++ -1, //PIXEL_FORMAT_RGBA_8888,
++ 15000,
++ 0.5f,
++ setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL
++ "MediaCompatLayerTestSurface"
++ };
++
++ cs.surface = sf_surface_create(cs.client, ¶ms);
++
++ if (!cs.surface) {
++ printf("Problem creating surface ... aborting now.");
++ return cs;
++ }
++
++ sf_surface_make_current(cs.surface);
++
++ return cs;
++}
++
++static const char *vertex_shader()
++{
++ return
++ "attribute vec4 a_position; \n"
++ "attribute vec2 a_texCoord; \n"
++ "uniform mat4 m_texMatrix; \n"
++ "varying vec2 v_texCoord; \n"
++ "varying float topDown; \n"
++ "void main() \n"
++ "{ \n"
++ " gl_Position = a_position; \n"
++ " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n"
++ "} \n";
++}
++
++static const char *fragment_shader()
++{
++ return
++ "#extension GL_OES_EGL_image_external : require \n"
++ "precision mediump float; \n"
++ "varying vec2 v_texCoord; \n"
++ "uniform samplerExternalOES s_texture; \n"
++ "void main() \n"
++ "{ \n"
++ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
++ "} \n";
++}
++
++static GLuint loadShader(GLenum shaderType, const char* pSource)
++{
++ GLuint shader = glCreateShader(shaderType);
++
++ if (shader) {
++ glShaderSource(shader, 1, &pSource, NULL);
++ glCompileShader(shader);
++ GLint compiled = 0;
++ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
++
++ if (!compiled) {
++ GLint infoLen = 0;
++ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
++ if (infoLen) {
++ char* buf = (char*) malloc(infoLen);
++ if (buf) {
++ glGetShaderInfoLog(shader, infoLen, NULL, buf);
++ fprintf(stderr, "Could not compile shader %d:\n%s\n",
++ shaderType, buf);
++ free(buf);
++ }
++ glDeleteShader(shader);
++ shader = 0;
++ }
++ }
++ } else {
++ printf("Error, during shader creation: %i\n", glGetError());
++ }
++
++ return shader;
++}
++
++static GLuint create_program(const char* pVertexSource, const char* pFragmentSource)
++{
++ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
++ if (!vertexShader) {
++ printf("vertex shader not compiled\n");
++ return 0;
++ }
++
++ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
++ if (!pixelShader) {
++ printf("frag shader not compiled\n");
++ return 0;
++ }
++
++ GLuint program = glCreateProgram();
++ if (program) {
++ glAttachShader(program, vertexShader);
++ glAttachShader(program, pixelShader);
++ glLinkProgram(program);
++ GLint linkStatus = GL_FALSE;
++
++ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
++ if (linkStatus != GL_TRUE) {
++ GLint bufLength = 0;
++ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
++ if (bufLength) {
++ char* buf = (char*) malloc(bufLength);
++ if (buf) {
++ glGetProgramInfoLog(program, bufLength, NULL, buf);
++ fprintf(stderr, "Could not link program:\n%s\n", buf);
++ free(buf);
++ }
++ }
++ glDeleteProgram(program);
++ program = 0;
++ }
++ }
++
++ return program;
++}
++
++static int setup_video_texture(struct ClientWithSurface *cs, GLuint *preview_texture_id)
++{
++ assert(cs != NULL);
++ assert(preview_texture_id != NULL);
++
++ sf_surface_make_current(cs->surface);
++
++ glGenTextures(1, preview_texture_id);
++ glClearColor(0, 0, 0, 0);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++
++ android_media_set_preview_texture(player, *preview_texture_id);
++
++ return 0;
++}
++
++void set_video_size_cb(int height, int width, void *context)
++{
++ printf("Video height: %d, width: %d\n", height, width);
++ printf("Video dest height: %f, width: %f\n", DestHeight, DestWidth);
++
++ Height = height;
++ Width = width;
++}
++
++void media_prepared_cb(void *context)
++{
++ printf("Media is prepared for playback.\n");
++}
++
++int main(int argc, char **argv)
++{
++ if (argc < 2) {
++ printf("Usage: test_media <video_to_play>\n");
++ return EXIT_FAILURE;
++ }
++
++ player = android_media_new_player();
++ if (player == NULL) {
++ printf("Problem creating new media player.\n");
++ return EXIT_FAILURE;
++ }
++
++ // Set player event cb for when the video size is known:
++ android_media_set_video_size_cb(player, set_video_size_cb, NULL);
++ android_media_set_media_prepared_cb(player, media_prepared_cb, NULL);
++
++ printf("Setting data source to: %s.\n", argv[1]);
++
++ if (android_media_set_data_source(player, argv[1]) != OK) {
++ printf("Failed to set data source: %s\n", argv[1]);
++ return EXIT_FAILURE;
++ }
++
++ printf("Creating EGL surface.\n");
++ struct ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */);
++ if (!cs.surface) {
++ printf("Problem acquiring surface for preview");
++ return EXIT_FAILURE;
++ }
++
++ printf("Creating GL texture.\n");
++
++ GLuint preview_texture_id;
++ EGLDisplay disp = sf_client_get_egl_display(cs.client);
++ EGLSurface surface = sf_surface_get_egl_surface(cs.surface);
++
++ sf_surface_make_current(cs.surface);
++
++ if (setup_video_texture(&cs, &preview_texture_id) != OK) {
++ printf("Problem setting up GL texture for video surface.\n");
++ return EXIT_FAILURE;
++ }
++
++ printf("Starting video playback.\n");
++ android_media_play(player);
++
++ while (android_media_is_playing(player)) {
++ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
++
++ const GLfloat textureCoordinates[] = {
++ 1.0f, 1.0f,
++ 0.0f, 1.0f,
++ 0.0f, 0.0f,
++ 1.0f, 0.0f
++ };
++
++ android_media_update_surface_texture(player);
++
++ calculate_position_coordinates();
++
++ gProgram = create_program(vertex_shader(), fragment_shader());
++ gaPositionHandle = glGetAttribLocation(gProgram, "a_position");
++ gaTexHandle = glGetAttribLocation(gProgram, "a_texCoord");
++ gsTextureHandle = glGetUniformLocation(gProgram, "s_texture");
++ gmTexMatrix = glGetUniformLocation(gProgram, "m_texMatrix");
++
++ glClear(GL_COLOR_BUFFER_BIT);
++
++ // Use the program object
++ glUseProgram(gProgram);
++ // Enable attributes
++ glEnableVertexAttribArray(gaPositionHandle);
++ glEnableVertexAttribArray(gaTexHandle);
++ // Load the vertex position
++ glVertexAttribPointer(gaPositionHandle,
++ 2,
++ GL_FLOAT,
++ GL_FALSE,
++ 0,
++ positionCoordinates);
++ // Load the texture coordinate
++ glVertexAttribPointer(gaTexHandle,
++ 2,
++ GL_FLOAT,
++ GL_FALSE,
++ 0,
++ textureCoordinates);
++
++ GLfloat matrix[16];
++ android_media_surface_texture_get_transformation_matrix(player, matrix);
++
++ glUniformMatrix4fv(gmTexMatrix, 1, GL_FALSE, matrix);
++
++ glActiveTexture(GL_TEXTURE0);
++ // Set the sampler texture unit to 0
++ glUniform1i(gsTextureHandle, 0);
++ glUniform1i(gmTexMatrix, 0);
++ android_media_update_surface_texture(player);
++ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
++ //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
++ glDisableVertexAttribArray(gaPositionHandle);
++ glDisableVertexAttribArray(gaTexHandle);
++
++ eglSwapBuffers(disp, surface);
++ }
++
++ android_media_stop(player);
++
++ return EXIT_SUCCESS;
++}
+--- /dev/null
++++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_recorder.c
+@@ -0,0 +1,490 @@
++/*
++ * Copyright (C) 2013 Canonical Ltd
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
++ * Guenter Schwann <guenter.schwann@canonical.com>
++ * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
++ */
++
++#include <hybris/camera/camera_compatibility_layer.h>
++#include <hybris/camera/camera_compatibility_layer_capabilities.h>
++
++#include <hybris/media/recorder_compatibility_layer.h>
++
++#include <hybris/input/input_stack_compatibility_layer.h>
++#include <hybris/input/input_stack_compatibility_layer_codes_key.h>
++#include <hybris/input/input_stack_compatibility_layer_flags_key.h>
++
++#include <hybris/surface_flinger/surface_flinger_compatibility_layer.h>
++
++#include <EGL/egl.h>
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++
++#include <assert.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdbool.h>
++#include <limits.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++
++int shot_counter = 1;
++int32_t current_zoom_level = 1;
++bool new_camera_frame_available = true;
++struct MediaRecorderWrapper *mr = 0;
++GLuint preview_texture_id = 0;
++
++static GLuint gProgram;
++static GLuint gaPositionHandle, gaTexHandle, gsTextureHandle, gmTexMatrix;
++
++void error_msg_cb(void* context)
++{
++ printf("%s \n", __PRETTY_FUNCTION__);
++}
++
++void shutter_msg_cb(void* context)
++{
++ printf("%s \n", __PRETTY_FUNCTION__);
++}
++
++void zoom_msg_cb(void* context, int32_t new_zoom_level)
++{
++ printf("%s \n", __PRETTY_FUNCTION__);
++
++ struct CameraControl* cc = (struct CameraControl*) context;
++ static int zoom;
++ current_zoom_level = new_zoom_level;
++}
++
++void autofocus_msg_cb(void* context)
++{
++ printf("%s \n", __PRETTY_FUNCTION__);
++}
++
++void raw_data_cb(void* data, uint32_t data_size, void* context)
++{
++ printf("%s: %d \n", __PRETTY_FUNCTION__, data_size);
++}
++
++void jpeg_data_cb(void* data, uint32_t data_size, void* context)
++{
++ printf("%s: %d \n", __PRETTY_FUNCTION__, data_size);
++ struct CameraControl* cc = (struct CameraControl*) context;
++ android_camera_start_preview(cc);
++}
++
++void size_cb(void* ctx, int width, int height)
++{
++ printf("Supported size: [%d,%d]\n", width, height);
++}
++
++void preview_texture_needs_update_cb(void* ctx)
++{
++ new_camera_frame_available = true;
++}
++
++void on_new_input_event(struct Event* event, void* context)
++{
++ assert(context);
++
++ if (event->type == KEY_EVENT_TYPE && event->action == ISCL_KEY_EVENT_ACTION_UP) {
++ printf("We have got a key event: %d \n", event->details.key.key_code);
++
++ struct CameraControl* cc = (struct CameraControl*) context;
++
++ int ret;
++ switch (event->details.key.key_code) {
++ case ISCL_KEYCODE_VOLUME_UP:
++ printf("Starting video recording\n");
++
++ android_camera_unlock(cc);
++
++ ret = android_recorder_setCamera(mr, cc);
++ if (ret < 0) {
++ printf("android_recorder_setCamera() failed\n");
++ return;
++ }
++ //state initial / idle
++ ret = android_recorder_setAudioSource(mr, ANDROID_AUDIO_SOURCE_CAMCORDER);
++ if (ret < 0) {
++ printf("android_recorder_setAudioSource() failed\n");
++ return;
++ }
++ ret = android_recorder_setVideoSource(mr, ANDROID_VIDEO_SOURCE_CAMERA);
++ if (ret < 0) {
++ printf("android_recorder_setVideoSource() failed\n");
++ return;
++ }
++ //state initialized
++ ret = android_recorder_setOutputFormat(mr, ANDROID_OUTPUT_FORMAT_MPEG_4);
++ if (ret < 0) {
++ printf("android_recorder_setOutputFormat() failed\n");
++ return;
++ }
++ //state DataSourceConfigured
++ ret = android_recorder_setAudioEncoder(mr, ANDROID_AUDIO_ENCODER_AAC);
++ if (ret < 0) {
++ printf("android_recorder_setAudioEncoder() failed\n");
++ return;
++ }
++ ret = android_recorder_setVideoEncoder(mr, ANDROID_VIDEO_ENCODER_H264);
++ if (ret < 0) {
++ printf("android_recorder_setVideoEncoder() failed\n");
++ return;
++ }
++
++ int fd;
++ fd = open("/tmp/test_video_recorder.avi", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
++ if (fd < 0) {
++ printf("Could not open file for video recording\n");
++ printf("FD: %i\n", fd);
++ return;
++ }
++ ret = android_recorder_setOutputFile(mr, fd);
++ if (ret < 0) {
++ printf("android_recorder_setOutputFile() failed\n");
++ return;
++ }
++
++ ret = android_recorder_setVideoSize(mr, 1280, 720);
++ if (ret < 0) {
++ printf("android_recorder_setVideoSize() failed\n");
++ return;
++ }
++ ret = android_recorder_setVideoFrameRate(mr, 30);
++ if (ret < 0) {
++ printf("android_recorder_setVideoFrameRate() failed\n");
++ return;
++ }
++
++ ret = android_recorder_prepare(mr);
++ if (ret < 0) {
++ printf("android_recorder_prepare() failed\n");
++ return;
++ }
++ //state prepared
++ ret = android_recorder_start(mr);
++ if (ret < 0) {
++ printf("android_recorder_start() failed\n");
++ return;
++ }
++ break;
++ case ISCL_KEYCODE_VOLUME_DOWN:
++ printf("Stoping video recording\n");
++ ret = android_recorder_stop(mr);
++
++ printf("Stoping video recording returned\n");
++ if (ret < 0) {
++ printf("android_recorder_stop() failed\n");
++ return;
++ }
++ printf("Stopped video recording\n");
++ ret = android_recorder_reset(mr);
++ if (ret < 0) {
++ printf("android_recorder_reset() failed\n");
++ return;
++ }
++ printf("Reset video recorder\n");
++ break;
++ }
++ }
++}
++
++struct ClientWithSurface
++{
++ struct SfClient* client;
++ struct SfSurface* surface;
++};
++
++struct ClientWithSurface client_with_surface(bool setup_surface_with_egl)
++{
++ struct ClientWithSurface cs;
++
++ cs.client = sf_client_create();
++
++ if (!cs.client) {
++ printf("Problem creating client ... aborting now.");
++ return cs;
++ }
++
++ static const size_t primary_display = 0;
++
++ SfSurfaceCreationParameters params = {
++ 0,
++ 0,
++ sf_get_display_width(primary_display),
++ sf_get_display_height(primary_display),
++ -1, //PIXEL_FORMAT_RGBA_8888,
++ 15000,
++ 0.5f,
++ setup_surface_with_egl, // Do not associate surface with egl, will be done by camera HAL
++ "CameraCompatLayerTestSurface"
++ };
++
++ cs.surface = sf_surface_create(cs.client, ¶ms);
++
++ if (!cs.surface) {
++ printf("Problem creating surface ... aborting now.");
++ return cs;
++ }
++
++ sf_surface_make_current(cs.surface);
++
++ return cs;
++}
++
++static const char* vertex_shader()
++{
++ return
++ "#extension GL_OES_EGL_image_external : require \n"
++ "attribute vec4 a_position; \n"
++ "attribute vec2 a_texCoord; \n"
++ "uniform mat4 m_texMatrix; \n"
++ "varying vec2 v_texCoord; \n"
++ "varying float topDown; \n"
++ "void main() \n"
++ "{ \n"
++ " gl_Position = a_position; \n"
++ " v_texCoord = a_texCoord; \n"
++ // " v_texCoord = (m_texMatrix * vec4(a_texCoord, 0.0, 1.0)).xy;\n"
++ //" topDown = v_texCoord.y; \n"
++ "} \n";
++}
++
++static const char* fragment_shader()
++{
++ return
++ "#extension GL_OES_EGL_image_external : require \n"
++ "precision mediump float; \n"
++ "varying vec2 v_texCoord; \n"
++ "uniform samplerExternalOES s_texture; \n"
++ "void main() \n"
++ "{ \n"
++ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
++ "} \n";
++}
++
++static GLuint loadShader(GLenum shaderType, const char* pSource) {
++ GLuint shader = glCreateShader(shaderType);
++
++ if (shader) {
++ glShaderSource(shader, 1, &pSource, NULL);
++ glCompileShader(shader);
++ GLint compiled = 0;
++ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
++
++ if (!compiled) {
++ GLint infoLen = 0;
++ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
++ if (infoLen) {
++ char* buf = (char*) malloc(infoLen);
++ if (buf) {
++ glGetShaderInfoLog(shader, infoLen, NULL, buf);
++ fprintf(stderr, "Could not compile shader %d:\n%s\n",
++ shaderType, buf);
++ free(buf);
++ }
++ glDeleteShader(shader);
++ shader = 0;
++ }
++ }
++ } else {
++ printf("Error, during shader creation: %i\n", glGetError());
++ }
++
++ return shader;
++}
++
++static GLuint create_program(const char* pVertexSource, const char* pFragmentSource) {
++ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
++ if (!vertexShader) {
++ printf("vertex shader not compiled\n");
++ return 0;
++ }
++
++ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
++ if (!pixelShader) {
++ printf("frag shader not compiled\n");
++ return 0;
++ }
++
++ GLuint program = glCreateProgram();
++ if (program) {
++ glAttachShader(program, vertexShader);
++ glAttachShader(program, pixelShader);
++ glLinkProgram(program);
++ GLint linkStatus = GL_FALSE;
++
++ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
++ if (linkStatus != GL_TRUE) {
++ GLint bufLength = 0;
++ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
++ if (bufLength) {
++ char* buf = (char*) malloc(bufLength);
++ if (buf) {
++ glGetProgramInfoLog(program, bufLength, NULL, buf);
++ fprintf(stderr, "Could not link program:\n%s\n", buf);
++ free(buf);
++ }
++ }
++ glDeleteProgram(program);
++ program = 0;
++ }
++ }
++
++ return program;
++}
++
++int main(int argc, char** argv)
++{
++ printf("Test application for video recording using the camera\n");
++ printf("Recording start with volume up button. And stops with volume down.\n");
++ printf("The result is stored to /root/test_video.avi\n\n");
++
++ struct CameraControlListener listener;
++ memset(&listener, 0, sizeof(listener));
++ listener.on_msg_error_cb = error_msg_cb;
++ listener.on_msg_shutter_cb = shutter_msg_cb;
++ listener.on_msg_focus_cb = autofocus_msg_cb;
++ listener.on_msg_zoom_cb = zoom_msg_cb;
++
++ listener.on_data_raw_image_cb = raw_data_cb;
++ listener.on_data_compressed_image_cb = jpeg_data_cb;
++ listener.on_preview_texture_needs_update_cb = preview_texture_needs_update_cb;
++ struct CameraControl* cc = android_camera_connect_to(BACK_FACING_CAMERA_TYPE,
++ &listener);
++ if (cc == NULL) {
++ printf("Problem connecting to camera");
++ return 1;
++ }
++
++ listener.context = cc;
++
++ mr = android_media_new_recorder();
++
++ struct AndroidEventListener event_listener;
++ event_listener.on_new_event = on_new_input_event;
++ event_listener.context = cc;
++
++ struct InputStackConfiguration input_configuration = { false, 25000 };
++
++ android_input_stack_initialize(&event_listener, &input_configuration);
++ android_input_stack_start();
++
++ android_camera_dump_parameters(cc);
++
++ printf("Supported video sizes:\n");
++ android_camera_enumerate_supported_video_sizes(cc, size_cb, NULL);
++
++ int min_fps, max_fps, current_fps;
++
++ android_camera_set_preview_size(cc, 1280, 720);
++
++ int width, height;
++ android_camera_get_video_size(cc, &width, &height);
++ printf("Current video size: [%d,%d]\n", width, height);
++
++ struct ClientWithSurface cs = client_with_surface(true /* Associate surface with egl. */);
++
++ if (!cs.surface) {
++ printf("Problem acquiring surface for preview");
++ return 1;
++ }
++
++ EGLDisplay disp = sf_client_get_egl_display(cs.client);
++ EGLSurface surface = sf_surface_get_egl_surface(cs.surface);
++
++ sf_surface_make_current(cs.surface);
++
++ gProgram = create_program(vertex_shader(), fragment_shader());
++ gaPositionHandle = glGetAttribLocation(gProgram, "a_position");
++ gaTexHandle = glGetAttribLocation(gProgram, "a_texCoord");
++ gsTextureHandle = glGetUniformLocation(gProgram, "s_texture");
++ gmTexMatrix = glGetUniformLocation(gProgram, "m_texMatrix");
++
++ glGenTextures(1, &preview_texture_id);
++ glClearColor(1.0, 0., 0.5, 1.);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(
++ GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(
++ GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++ android_camera_set_preview_texture(cc, preview_texture_id);
++ android_camera_start_preview(cc);
++
++ GLfloat transformation_matrix[16];
++ android_camera_get_preview_texture_transformation(cc, transformation_matrix);
++ glUniformMatrix4fv(gmTexMatrix, 1, GL_FALSE, transformation_matrix);
++
++ printf("Started camera preview.\n");
++
++ while (true) {
++ /*if (new_camera_frame_available)
++ {
++ printf("Updating texture");
++ new_camera_frame_available = false;
++ }*/
++ static GLfloat vVertices[] = { 0.0f, 0.0f, 0.0f, // Position 0
++ 0.0f, 0.0f, // TexCoord 0
++ 0.0f, 1.0f, 0.0f, // Position 1
++ 0.0f, 1.0f, // TexCoord 1
++ 1.0f, 1.0f, 0.0f, // Position 2
++ 1.0f, 1.0f, // TexCoord 2
++ 1.0f, 0.0f, 0.0f, // Position 3
++ 1.0f, 0.0f // TexCoord 3
++ };
++
++ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
++
++ // Set the viewport
++ // Clear the color buffer
++ glClear(GL_COLOR_BUFFER_BIT);
++ // Use the program object
++ glUseProgram(gProgram);
++ // Enable attributes
++ glEnableVertexAttribArray(gaPositionHandle);
++ glEnableVertexAttribArray(gaTexHandle);
++ // Load the vertex position
++ glVertexAttribPointer(gaPositionHandle,
++ 3,
++ GL_FLOAT,
++ GL_FALSE,
++ 5 * sizeof(GLfloat),
++ vVertices);
++ // Load the texture coordinate
++ glVertexAttribPointer(gaTexHandle,
++ 2,
++ GL_FLOAT,
++ GL_FALSE,
++ 5 * sizeof(GLfloat),
++ vVertices+3);
++
++ glActiveTexture(GL_TEXTURE0);
++ // Set the sampler texture unit to 0
++ glUniform1i(gsTextureHandle, 0);
++ glUniform1i(gmTexMatrix, 0);
++ android_camera_update_preview_texture(cc);
++ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
++ glDisableVertexAttribArray(gaPositionHandle);
++ glDisableVertexAttribArray(gaTexHandle);
++
++ eglSwapBuffers(disp, surface);
++ }
++}
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/test_ui.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_ui.c
+@@ -52,8 +52,10 @@ int main(int argc, char **argv)
+ graphic_buffer_lock(buffer, GRALLOC_USAGE_HW_RENDER, &vaddr);
+ graphic_buffer_unlock(buffer);
+
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
+ graphic_buffer_set_index(buffer, 11);
+ assert(graphic_buffer_get_index(buffer) == 11);
++#endif
+
+ graphic_buffer_free(buffer);
+
+--- libhybris-0.1.0+git20131207+e452e83.orig/hybris/ui/ui.c
++++ libhybris-0.1.0+git20131207+e452e83/hybris/ui/ui.c
+@@ -48,9 +48,11 @@ HYBRIS_IMPLEMENT_FUNCTION1(ui, uint32_t,
+ struct graphic_buffer*);
+ HYBRIS_IMPLEMENT_FUNCTION1(ui, void*, graphic_buffer_get_native_buffer,
+ struct graphic_buffer*);
++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3
+ HYBRIS_IMPLEMENT_VOID_FUNCTION2(ui, graphic_buffer_set_index,
+ struct graphic_buffer*, int);
+ HYBRIS_IMPLEMENT_FUNCTION1(ui, int, graphic_buffer_get_index,
+ struct graphic_buffer*);
++#endif
+ HYBRIS_IMPLEMENT_FUNCTION1(ui, int, graphic_buffer_init_check,
+ struct graphic_buffer*);