X-Git-Url: https://git.piment-noir.org/?p=deb_libhybris.git;a=blobdiff_plain;f=debian%2Fpatches%2Fdebian-changes;fp=debian%2Fpatches%2Fdebian-changes;h=96cd18e540ccdee5b70cc878746e25a99e32ce1f;hp=0000000000000000000000000000000000000000;hb=4395b8c4430d414035c345cf4c757204b39ac993;hpb=d42e7319e80e2f113a97047d135e749e50348b4f diff --git a/debian/patches/debian-changes b/debian/patches/debian-changes new file mode 100644 index 0000000..96cd18e --- /dev/null +++ b/debian/patches/debian-changes @@ -0,0 +1,7670 @@ +Subject: Collected Debian patches for libhybris +Author: Ricardo Salveti de Araujo + +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 + #include + #include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 + #include ++#else ++#include ++#endif + #include + ++#include ++#include ++ + #undef LOG_TAG + #define LOG_TAG "CameraCompatibilityLayer" + #include + #include ++#include + + #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 native_alloc( + new android::NativeBufferAlloc() + ); + + android::sp 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( + new android::SurfaceTexture( ++#else ++ control->preview_texture = android::sp( ++ 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(control)); ++#else ++ android::sp(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 ++ ++#include "SimplePlayer.h" ++ ++#include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define USE_MEDIA_CODEC_LAYER ++ ++namespace android { ++ ++SimplePlayer::SimplePlayer() ++ : mState(UNINITIALIZED), ++ mDoMoreStuffGeneration(0), ++ mStartTimeRealUs(-1ll) { ++} ++ ++SimplePlayer::~SimplePlayer() { ++} ++ ++// static ++status_t PostAndAwaitResponse( ++ const sp &msg, sp *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 msg = new AMessage(kWhatSetDataSource, id()); ++ msg->setString("path", path); ++ sp response; ++ return PostAndAwaitResponse(msg, &response); ++} ++ ++status_t SimplePlayer::setSurface(const sp &surfaceTexture) { ++ sp msg = new AMessage(kWhatSetSurface, id()); ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ sp surfaceTextureClient; ++ if (surfaceTexture != NULL) { ++ surfaceTextureClient = new SurfaceTextureClient(surfaceTexture); ++ } ++#else ++ sp surfaceTextureClient; ++ if (surfaceTexture != NULL) { ++ surfaceTextureClient = new Surface(surfaceTexture); ++ } ++#endif ++ ++ msg->setObject( ++ "native-window", new NativeWindowWrapper(surfaceTextureClient)); ++ ++ sp response; ++ return PostAndAwaitResponse(msg, &response); ++} ++ ++status_t SimplePlayer::prepare() { ++ sp msg = new AMessage(kWhatPrepare, id()); ++ sp response; ++ return PostAndAwaitResponse(msg, &response); ++} ++ ++status_t SimplePlayer::start() { ++ printf("%s\n", __PRETTY_FUNCTION__); ++ sp msg = new AMessage(kWhatStart, id()); ++ sp response; ++ return PostAndAwaitResponse(msg, &response); ++} ++ ++status_t SimplePlayer::stop() { ++ sp msg = new AMessage(kWhatStop, id()); ++ sp response; ++ return PostAndAwaitResponse(msg, &response); ++} ++ ++status_t SimplePlayer::reset() { ++ sp msg = new AMessage(kWhatReset, id()); ++ sp response; ++ return PostAndAwaitResponse(msg, &response); ++} ++ ++void SimplePlayer::onMessageReceived(const sp &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 response = new AMessage; ++ response->setInt32("err", err); ++ response->postReply(replyID); ++ break; ++ } ++ ++ case kWhatSetSurface: ++ { ++ status_t err; ++ if (mState != UNPREPARED) { ++ err = INVALID_OPERATION; ++ } else { ++ sp obj; ++ CHECK(msg->findObject("native-window", &obj)); ++ ++ mNativeWindow = static_cast(obj.get()); ++ ++ err = OK; ++ } ++ ++ uint32_t replyID; ++ CHECK(msg->senderAwaitsResponse(&replyID)); ++ ++ sp 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 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 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 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 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 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 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 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; imCodecDelegate, 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 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 &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 &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 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 &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 &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 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 &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 ++#include ++#include ++ ++#include ++ ++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 &surfaceTexture); ++#else ++ status_t setSurface(const sp &surfaceTexture); ++#endif ++ status_t prepare(); ++ status_t start(); ++ status_t stop(); ++ status_t reset(); ++ ++protected: ++ virtual ~SimplePlayer(); ++ ++ virtual void onMessageReceived(const sp &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 mCodec; ++ MediaCodecDelegate mCodecDelegate; ++ Vector > mCSD; ++ Vector > mBuffers[2]; ++ ++ List mAvailInputBufferIndices; ++ List mAvailOutputBufferInfos; ++ ++ sp mAudioTrack; ++ uint32_t mNumFramesWritten; ++ }; ++ ++ State mState; ++ AString mPath; ++ sp mNativeWindow; ++ ++ sp mExtractor; ++ sp mCodecLooper; ++ KeyedVector 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 &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 ++ ++#include "SimplePlayer.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 mCodec; ++ Vector > mInBuffers; ++ Vector > mOutBuffers; ++ bool mSignalledInputEOS; ++ bool mSawOutputEOS; ++ int64_t mNumBuffersDecoded; ++ int64_t mNumBytesDecoded; ++ bool mIsAudio; ++}; ++ ++} // namespace android ++ ++static int decode( ++ const android::sp &looper, ++ const char *path, ++ bool useAudio, ++ bool useVideo, ++ const android::sp &surface) { ++ using namespace android; ++ ++ static int64_t kTimeout = 500ll; ++ ++ sp extractor = new NuMediaExtractor; ++ if (extractor->setDataSource(path) != OK) { ++ fprintf(stderr, "unable to instantiate extractor.\n"); ++ return 1; ++ } ++ ++ KeyedVector stateByTrack; ++ ++ bool haveAudio = false; ++ bool haveVideo = false; ++ for (size_t i = 0; i < extractor->countTracks(); ++i) { ++ sp 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 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 &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 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 looper = new ALooper; ++ looper->start(); ++ ++ sp composerClient; ++ sp control; ++ sp surface; ++ ++ if (playback || (useSurface && useVideo)) { ++ composerClient = new SurfaceComposerClient; ++ CHECK_EQ(composerClient->initCheck(), (status_t)OK); ++ ++ sp 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 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 ++ * Ricardo Salveti de Araujo ++ */ ++ ++#include ++#include "direct_media_test.h" ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++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 \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 ++ */ ++ ++#ifndef DIRECT_MEDIA_TEST_H_ ++#define DIRECT_MEDIA_TEST_H_ ++ ++#include ++#include ++#include ++ ++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 ++ */ ++ ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "MediaCodecLayer" ++ ++#include ++#include ++#include ++ ++#include "media_format_layer_priv.h" ++#include "surface_texture_client_hybris_priv.h" ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#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 &msg) { } ++ ++public: ++ sp media_codec; ++ sp looper; ++ ++ Vector > input_buffers; ++ Vector > output_buffers; ++ List available_output_buffer_infos; ++ List 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 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 = static_cast(nativeWindow); ++#else ++ sp surfaceTextureClient = static_cast(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 > input_bufs[1]; ++ err = d->media_codec->getInputBuffers(&input_bufs[0]); ++ CHECK_EQ(err, static_cast(OK)); ++ ++ for (size_t i=0; i<2; ++i) ++ { ++ const sp &srcBuffer = format_priv->csd; ++ ++ size_t index = 0; ++ err = d->media_codec->dequeueInputBuffer(&index, -1ll); ++ CHECK_EQ(err, static_cast(OK)); ++ ++ const sp &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(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 > 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 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 ++ */ ++ ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "MediaCodecList" ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#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 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 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 types; ++ status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); ++ for (size_t i=0; i profile_levels; ++ Vector 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 profile_levels; ++ Vector 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 profile_levels; ++ Vector 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 ++ * Ricardo Salveti de Araujo ++ */ ++ ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "MediaCompatibilityLayer" ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) ++ ++namespace android ++{ ++NativeBufferAlloc::NativeBufferAlloc() { ++} ++ ++NativeBufferAlloc::~NativeBufferAlloc() { ++} ++ ++sp NativeBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, ++ PixelFormat format, uint32_t usage, status_t* error) { ++ sp 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 &surfaceTexture) ++#else ++ android::status_t setVideoSurfaceTexture(android::sp bq, const android::sp &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 texture; ++#else ++ android::sp texture; ++#endif ++ android::sp media_player_listener; ++ android::sp 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 native_alloc( ++ new android::NativeBufferAlloc() ++ ); ++ ++ android::sp 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( ++ new android::SurfaceTexture( ++#else ++ mp->setVideoSurfaceTexture(buffer_queue, android::sp( ++ 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 ++ */ ++ ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "MediaFormatLayer" ++ ++#include ++#include "media_format_layer_priv.h" ++ ++#include ++ ++#include ++ ++#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(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 ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#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 ++ */ ++ ++#ifndef MEDIA_FORMAT_LAYER_PRIV_H_ ++#define MEDIA_FORMAT_LAYER_PRIV_H_ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++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 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 ++ * Guenter Schwann ++ * Ricardo Salveti de Araujo ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++//#define LOG_NDEBUG 0 ++#undef LOG_TAG ++#define LOG_TAG "MediaRecorderCompatibilityLayer" ++#include ++#include ++ ++#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 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(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(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(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(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(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 ++ */ ++ ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "SurfaceTextureClientHybris" ++ ++#include ++#include "surface_texture_client_hybris_priv.h" ++ ++#include ++#include ++#include ++#include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++#include ++#endif ++ ++#include ++#include ++ ++#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 &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 &st) ++ : SurfaceTextureClient::SurfaceTextureClient(st), ++#else ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &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& surface_texture) ++{ ++ SurfaceTextureClient::setISurfaceTexture(surface_texture); ++#else ++void _SurfaceTextureClientHybris::setISurfaceTexture(const sp& 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 &surface_texture) ++#else ++static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp &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 native_alloc(new NativeBufferAlloc()); ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++ sp buffer_queue(new BufferQueue(false, NULL, native_alloc)); ++ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris); ++#else ++ sp 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(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(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(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 = static_cast(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 ++ */ ++ ++#include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++#include ++#else ++#include ++#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 &st); ++#else ++ _SurfaceTextureClientHybris(const android::sp &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& surface_texture); ++#else ++ void setISurfaceTexture(const android::sp& 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 surface_texture; ++#else ++ android::sp 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 + #include + #include ++#include + #include + #include + #include +@@ -42,6 +43,10 @@ + #include + #include + ++#include ++#include ++#include ++ + #include + #include + #include +@@ -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 + ++/* 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; inchain; 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 + #include ++#include + #include + #include + +@@ -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 + #include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 + #include ++#else ++#include ++#endif + + #include + #include +@@ -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 camera; + android::CameraParameters camera_parameters; ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 + android::sp preview_texture; +- +- // From android::SurfaceTexture::FrameAvailableListener ++#else ++ android::sp 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 + ++#include + #include + #include + #include +--- /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 ++ */ ++ ++#ifndef MEDIA_CODEC_LAYER_H_ ++#define MEDIA_CODEC_LAYER_H_ ++ ++#include ++#include ++ ++#ifdef SIMPLE_PLAYER ++#include ++#endif ++ ++#include ++#include ++ ++#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 ++ */ ++ ++#ifndef MEDIA_CODEC_LIST_PRIV_H_ ++#define MEDIA_CODEC_LIST_PRIV_H_ ++ ++#include ++#include ++#include ++ ++#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 ++ */ ++ ++#ifndef MEDIA_COMPATIBILITY_LAYER_H_ ++#define MEDIA_COMPATIBILITY_LAYER_H_ ++ ++#include ++#include ++#include ++ ++#include ++ ++#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 ++ */ ++ ++#ifndef MEDIA_FORMAT_LAYER_H_ ++#define MEDIA_FORMAT_LAYER_H_ ++ ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++ ++#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 ++ */ ++ ++#ifndef SURFACE_TEXTURE_CLIENT_HYBRIS_H_ ++#define SURFACE_TEXTURE_CLIENT_HYBRIS_H_ ++ ++#include ++#include ++ ++#include ++ ++#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 ++ * Ricardo Salveti de Araujo ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ * Ricardo Salveti de Araujo ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 \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 ++ * Guenter Schwann ++ * Ricardo Salveti de Araujo ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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*);