summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/doppelganger/appops.cpp50
-rw-r--r--src/doppelganger/appops.h29
-rw-r--r--src/doppelganger/doppelganger.pro22
-rw-r--r--src/doppelganger/main.cpp36
-rw-r--r--src/doppelganger/permissioncontroller.cpp38
-rw-r--r--src/doppelganger/permissioncontroller.h35
-rw-r--r--src/doppelganger/powermanager.cpp88
-rw-r--r--src/doppelganger/powermanager.h62
-rw-r--r--src/doppelganger/schedulingpolicyservice.cpp88
-rw-r--r--src/doppelganger/schedulingpolicyservice.h44
-rw-r--r--src/imports/nativemedia/BufferQueue.cpp1061
-rw-r--r--src/imports/nativemedia/BufferQueue.h490
-rw-r--r--src/imports/nativemedia/SurfaceTexture.cpp23
-rw-r--r--src/imports/nativemedia/SurfaceTexture.h23
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_0.cpp1236
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_0.h517
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_1.cpp866
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_1.h420
-rw-r--r--src/imports/nativemedia/main.cpp73
-rw-r--r--src/imports/nativemedia/nativemedia.pro21
-rw-r--r--src/imports/nativemedia/omx.cpp666
-rw-r--r--src/imports/nativemedia/omxmodule.cpp37
-rw-r--r--src/imports/nativemedia/omxnode.cpp204
-rw-r--r--src/imports/nativemedia/omxnode.h129
-rw-r--r--src/imports/nativemedia/omxplayer.h42
-rw-r--r--src/imports/nativemedia/qmldir2
-rw-r--r--src/imports/nativemedia/test.qml53
-rw-r--r--src/plugins/plugins.pro3
-rw-r--r--src/plugins/sensors/eandroid/eandroid.pro30
-rw-r--r--src/plugins/sensors/eandroid/eandroidaccelerometer.cpp38
-rw-r--r--src/plugins/sensors/eandroid/eandroidaccelerometer.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp47
-rw-r--r--src/plugins/sensors/eandroid/eandroidambientlightsensor.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidbasesensor.cpp59
-rw-r--r--src/plugins/sensors/eandroid/eandroidbasesensor.h40
-rw-r--r--src/plugins/sensors/eandroid/eandroidgyroscope.cpp40
-rw-r--r--src/plugins/sensors/eandroid/eandroidgyroscope.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidlight.cpp36
-rw-r--r--src/plugins/sensors/eandroid/eandroidlight.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidmagnetometer.cpp57
-rw-r--r--src/plugins/sensors/eandroid/eandroidmagnetometer.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidrotationsensor.cpp42
-rw-r--r--src/plugins/sensors/eandroid/eandroidrotationsensor.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidsensordevice.cpp212
-rw-r--r--src/plugins/sensors/eandroid/eandroidsensordevice.h99
-rw-r--r--src/plugins/sensors/eandroid/main.cpp142
-rw-r--r--src/plugins/sensors/eandroid/plugin.json1
-rw-r--r--src/plugins/sensors/sensors.pro3
-rw-r--r--src/qconnectivity/main.cpp476
-rw-r--r--src/qconnectivity/qconnectivity.pro13
-rw-r--r--src/qt_hw_init/main.cpp30
-rw-r--r--src/qt_hw_init/qt_hw_init.pro8
-rw-r--r--src/src.pro4
53 files changed, 0 insertions, 7963 deletions
diff --git a/src/doppelganger/appops.cpp b/src/doppelganger/appops.cpp
deleted file mode 100644
index adeddcc..0000000
--- a/src/doppelganger/appops.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#include "appops.h"
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
-#include <binder/IServiceManager.h>
-#include <binder/IAppOpsCallback.h>
-
-class AppOpsPrivate : public android::BnAppOpsCallback
-{
-public:
- virtual void opChanged(int32_t, const android::String16&)
- {
-
- }
-
- virtual android::status_t onTransact(uint32_t,
- const android::Parcel&,
- android::Parcel*,
- uint32_t flags = 0)
- {
- (void)flags;
- return android::OK;
- }
-};
-#endif
-
-void AppOps::instantiate()
-{
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
- android::defaultServiceManager()->addService(android::String16("appops"), new AppOpsPrivate);
-#endif
-}
diff --git a/src/doppelganger/appops.h b/src/doppelganger/appops.h
deleted file mode 100644
index 5e765a6..0000000
--- a/src/doppelganger/appops.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#ifndef APPOPS_H
-#define APPOPS_H
-
-class AppOps
-{
-public:
- static void instantiate();
-};
-
-#endif // APPOPS_H
diff --git a/src/doppelganger/doppelganger.pro b/src/doppelganger/doppelganger.pro
deleted file mode 100644
index fa91169..0000000
--- a/src/doppelganger/doppelganger.pro
+++ /dev/null
@@ -1,22 +0,0 @@
-QT -= core gui
-
-TARGET = doppelganger
-
-LIBS += -lutils -lbinder -lcutils \
- -L$${ANDROID_PRODUCT_OUT}/obj/STATIC_LIBRARIES/libscheduling_policy_intermediates -lscheduling_policy -lpowermanager
-
-TEMPLATE = app
-
-SOURCES += main.cpp \
- permissioncontroller.cpp \
- schedulingpolicyservice.cpp \
- powermanager.cpp \
- appops.cpp
-
-HEADERS += \
- permissioncontroller.h \
- schedulingpolicyservice.h \
- powermanager.h \
- appops.h
-
-load(qt_tool)
diff --git a/src/doppelganger/main.cpp b/src/doppelganger/main.cpp
deleted file mode 100644
index 3e86a66..0000000
--- a/src/doppelganger/main.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <binder/IPCThreadState.h>
-
-#include "permissioncontroller.h"
-#include "schedulingpolicyservice.h"
-#include "powermanager.h"
-#include "appops.h"
-
-using namespace android;
-
-int main(int, char *[])
-{
- sp<ProcessState> proc(ProcessState::self());
- SchedulingPolicyService::instantiate();
- PermissionController::instantiate();
- PowerManager::instantiate();
- AppOps::instantiate();
- IPCThreadState::self()->joinThreadPool();
-}
diff --git a/src/doppelganger/permissioncontroller.cpp b/src/doppelganger/permissioncontroller.cpp
deleted file mode 100644
index 9538b1a..0000000
--- a/src/doppelganger/permissioncontroller.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "permissioncontroller.h"
-
-#include <binder/IServiceManager.h>
-
-using namespace android;
-
-PermissionController::PermissionController()
-{
-}
-
-void PermissionController::instantiate()
-{
- defaultServiceManager()->addService(String16("permission"), new PermissionController);
-}
-
-bool PermissionController::checkPermission(const String16 &, int32_t, int32_t)
-{
- // just bypass any permission
- return true;
-}
diff --git a/src/doppelganger/permissioncontroller.h b/src/doppelganger/permissioncontroller.h
deleted file mode 100644
index 211a346..0000000
--- a/src/doppelganger/permissioncontroller.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef PERMISSIONCONTROLLER_H
-#define PERMISSIONCONTROLLER_H
-
-#include <binder/IPermissionController.h>
-
-class PermissionController : public android::BnPermissionController
-{
-public:
- static void instantiate();
-
- bool checkPermission(const android::String16 &permission, int32_t pid, int32_t uid);
-
-private:
- PermissionController();
-};
-
-#endif // PERMISSIONCONTROLLER_H
diff --git a/src/doppelganger/powermanager.cpp b/src/doppelganger/powermanager.cpp
deleted file mode 100644
index 7f0da97..0000000
--- a/src/doppelganger/powermanager.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-
-#include "powermanager.h"
-
-#include <binder/IServiceManager.h>
-
-using namespace android;
-
-enum {
- ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
- ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
- RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
- UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
-};
-
-void PowerManager::instantiate()
-{
- defaultServiceManager()->addService(String16("power"), new PowerManager());
-}
-
-status_t PowerManager::onTransact(uint32_t code,
- const Parcel &,
- Parcel *,
- uint32_t)
-{
- switch (code) {
- case ACQUIRE_WAKE_LOCK:
- case ACQUIRE_WAKE_LOCK_UID:
- case RELEASE_WAKE_LOCK:
- case UPDATE_WAKE_LOCK_UIDS:
- return NO_ERROR;
- default:
- break;
- }
-}
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
-status_t PowerManager::acquireWakeLock(int,
- const sp<IBinder> &,
- const String16 &,
- const String16 &)
-{
- return OK;
-}
-
-status_t PowerManager::acquireWakeLockWithUid(int,
- const sp<IBinder> &,
- const String16 &,
- const String16 &,
- int)
-{
- return OK;
-}
-
-status_t PowerManager::updateWakeLockUids(const sp<IBinder> &,
- int,
- const int *)
-{
- return OK;
-}
-#else // < 4.4
-status_t PowerManager::acquireWakeLock(int, const sp<android::IBinder> &, const String16 &)
-{
- return OK;
-}
-#endif
-
-status_t PowerManager::releaseWakeLock(const sp<IBinder> &, int)
-{
- return OK;
-}
diff --git a/src/doppelganger/powermanager.h b/src/doppelganger/powermanager.h
deleted file mode 100644
index 23f2695..0000000
--- a/src/doppelganger/powermanager.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-
-#ifndef POWERMANAGER_H
-#define POWERMANAGER_H
-
-#include <powermanager/IPowerManager.h>
-
-namespace android {
-
-typedef BnInterface<IPowerManager> BnPowerManagerService;
-
-} // namespace android
-
-class PowerManager : public android::BnPowerManagerService
-{
-public:
- static void instantiate();
- android::status_t onTransact(uint32_t code,
- const android::Parcel &data,
- android::Parcel *reply,
- uint32_t flags);
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
- virtual android::status_t acquireWakeLock(int flags,
- const android::sp<android::IBinder>& lock,
- const android::String16& tag,
- const android::String16& packageName);
- virtual android::status_t acquireWakeLockWithUid(int flags,
- const android::sp<android::IBinder>& lock,
- const android::String16& tag,
- const android::String16& packageName,
- int uid);
- virtual android::status_t updateWakeLockUids(const android::sp<android::IBinder>& lock,
- int len,
- const int *uids);
-#else // < 4.4
- virtual android::status_t acquireWakeLock(int flags,
- const android::sp<android::IBinder>& lock,
- const android::String16& tag);
-#endif
-
- virtual android::status_t releaseWakeLock(const android::sp<android::IBinder>& lock, int flags);
-};
-
-#endif // POWERMANAGER_H
diff --git a/src/doppelganger/schedulingpolicyservice.cpp b/src/doppelganger/schedulingpolicyservice.cpp
deleted file mode 100644
index 7113e6a..0000000
--- a/src/doppelganger/schedulingpolicyservice.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "schedulingpolicyservice.h"
-
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <cutils/sched_policy.h>
-#include <sched.h>
-
-using namespace android;
-
-enum {
- REQUEST_PRIORITY_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
-};
-
-#define PRIORITY_MIN 1
-#define PRIORITY_MAX 3
-
-SchedulingPolicyService::SchedulingPolicyService()
-{
-}
-
-void SchedulingPolicyService::instantiate()
-{
- defaultServiceManager()->addService(String16("scheduling_policy"), new SchedulingPolicyService);
-}
-
-status_t SchedulingPolicyService::onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags)
-{
- switch (code) {
- case REQUEST_PRIORITY_TRANSACTION: {
- CHECK_INTERFACE(ISchedulingPolicyService, data, reply);
- int32_t pid = data.readInt32();
- int32_t tid = data.readInt32();
- int32_t prio = data.readInt32();
- int res = requestPriority_helper(pid, tid, prio);
- reply->writeNoException();
- reply->writeInt32(res);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
-int SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t prio)
-#else
-int SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t prio, bool)
-#endif
-{
- return requestPriority_helper(pid, tid, prio);
-}
-
-int SchedulingPolicyService::requestPriority_helper(int32_t pid, int32_t tid, int32_t prio)
-{
- if (prio < PRIORITY_MIN || prio > PRIORITY_MAX)
- return PERMISSION_DENIED;
-
- int res = set_sched_policy(tid, IPCThreadState::self()->getCallingPid() == pid ? SP_AUDIO_SYS
- : SP_AUDIO_APP);
- if (res != NO_ERROR)
- return PERMISSION_DENIED;
-
- struct sched_param param;
- param.sched_priority = prio;
- res = sched_setscheduler(tid, SCHED_FIFO, &param);
- if (res)
- return PERMISSION_DENIED;
-
- return OK;
-}
diff --git a/src/doppelganger/schedulingpolicyservice.h b/src/doppelganger/schedulingpolicyservice.h
deleted file mode 100644
index 2dc1e42..0000000
--- a/src/doppelganger/schedulingpolicyservice.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef SCHEDULINGPOLICYSERVICE_H
-#define SCHEDULINGPOLICYSERVICE_H
-
-#include <frameworks/av/services/audioflinger/ISchedulingPolicyService.h>
-#include <binder/Parcel.h>
-
-class SchedulingPolicyService : public android::BnSchedulingPolicyService
-{
-public:
- static void instantiate();
-
- android::status_t onTransact(uint32_t code, const android::Parcel &data,
- android::Parcel *reply, uint32_t flags);
-
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
- int requestPriority(int32_t pid, int32_t tid, int32_t prio);
-#else
- int requestPriority(int32_t pid, int32_t tid, int32_t prio, bool);
-#endif
-
-private:
- SchedulingPolicyService();
- int requestPriority_helper(int32_t pid, int32_t tid, int32_t prio);
-};
-
-#endif // SCHEDULINGPOLICYSERVICE_H
diff --git a/src/imports/nativemedia/BufferQueue.cpp b/src/imports/nativemedia/BufferQueue.cpp
deleted file mode 100644
index 1dbd498..0000000
--- a/src/imports/nativemedia/BufferQueue.cpp
+++ /dev/null
@@ -1,1061 +0,0 @@
-/*
- * 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.
- */
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1)
-
-#define LOG_TAG "BufferQueue"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <gui/BufferQueue.h>
-#include <gui/ISurfaceComposer.h>
-#include <private/gui/ComposerService.h>
-
-#include <utils/Log.h>
-#include <gui/SurfaceTexture.h>
-#include <utils/Trace.h>
-
-// This compile option causes SurfaceTexture to return the buffer that is currently
-// attached to the GL texture from dequeueBuffer when no other buffers are
-// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
-// implicit cross-process synchronization to prevent the buffer from being
-// written to before the buffer has (a) been detached from the GL texture and
-// (b) all GL reads from the buffer have completed.
-
-// During refactoring, do not support dequeuing the current buffer
-#undef ALLOW_DEQUEUE_CURRENT_BUFFER
-
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
-#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
-#else
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
-#endif
-
-// Macros for including the BufferQueue name in log messages
-#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-
-#define ATRACE_BUFFER_INDEX(index) \
- if (ATRACE_ENABLED()) { \
- char ___traceBuf[1024]; \
- snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), \
- (index)); \
- android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \
- }
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-static const char* scalingModeName(int scalingMode) {
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
- default: return "Unknown";
- }
-}
-
-BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) :
- mDefaultWidth(1),
- mDefaultHeight(1),
- mPixelFormat(PIXEL_FORMAT_RGBA_8888),
- mMinUndequeuedBuffers(bufferCount),
- mMinAsyncBufferSlots(bufferCount + 1),
- mMinSyncBufferSlots(bufferCount),
- mBufferCount(mMinAsyncBufferSlots),
- mClientBufferCount(0),
- mServerBufferCount(mMinAsyncBufferSlots),
- mSynchronousMode(false),
- mAllowSynchronousMode(allowSynchronousMode),
- mConnectedApi(NO_CONNECTED_API),
- mAbandoned(false),
- mFrameCounter(0),
- mBufferHasBeenQueued(false),
- mDefaultBufferFormat(0),
- mConsumerUsageBits(0),
- mTransformHint(0)
-{
- // Choose a name using the PID and a process-unique ID.
- mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- ST_LOGV("BufferQueue");
-#if 0
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
- if (mGraphicBufferAlloc == 0) {
- ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()");
- }
-#endif
-}
-
-BufferQueue::~BufferQueue() {
- ST_LOGV("~BufferQueue");
-}
-
-status_t BufferQueue::setBufferCountServerLocked(int bufferCount) {
- if (bufferCount > NUM_BUFFER_SLOTS)
- return BAD_VALUE;
-
- // special-case, nothing to do
- if (bufferCount == mBufferCount)
- return OK;
-
- if (!mClientBufferCount &&
- bufferCount >= mBufferCount) {
- // easy, we just have more buffers
- mBufferCount = bufferCount;
- mServerBufferCount = bufferCount;
- mDequeueCondition.broadcast();
- } else {
- // we're here because we're either
- // - reducing the number of available buffers
- // - or there is a client-buffer-count in effect
-
- // less than 2 buffers is never allowed
- if (bufferCount < 2)
- return BAD_VALUE;
-
- // when there is non client-buffer-count in effect, the client is not
- // allowed to dequeue more than one buffer at a time,
- // so the next time they dequeue a buffer, we know that they don't
- // own one. the actual resizing will happen during the next
- // dequeueBuffer.
-
- mServerBufferCount = bufferCount;
- mDequeueCondition.broadcast();
- }
- return OK;
-}
-
-bool BufferQueue::isSynchronousMode() const {
- Mutex::Autolock lock(mMutex);
- return mSynchronousMode;
-}
-
-void BufferQueue::setConsumerName(const String8& name) {
- Mutex::Autolock lock(mMutex);
- mConsumerName = name;
-}
-
-status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock lock(mMutex);
- mDefaultBufferFormat = defaultFormat;
- return OK;
-}
-
-status_t BufferQueue::setConsumerUsageBits(uint32_t usage) {
- Mutex::Autolock lock(mMutex);
- mConsumerUsageBits = usage;
- return OK;
-}
-
-status_t BufferQueue::setTransformHint(uint32_t hint) {
- Mutex::Autolock lock(mMutex);
- mTransformHint = hint;
- return OK;
-}
-
-status_t BufferQueue::setBufferCount(int bufferCount) {
- ST_LOGV("setBufferCount: count=%d", bufferCount);
-
- sp<ConsumerListener> listener;
- {
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ST_LOGE("setBufferCount: bufferCount larger than slots available");
- return BAD_VALUE;
- }
-
- // Error out if the user has dequeued buffers
- for (int i=0 ; i<mBufferCount ; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ST_LOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
-
- const int minBufferSlots = mSynchronousMode ?
- mMinSyncBufferSlots : mMinAsyncBufferSlots;
- if (bufferCount == 0) {
- mClientBufferCount = 0;
- bufferCount = (mServerBufferCount >= minBufferSlots) ?
- mServerBufferCount : minBufferSlots;
- return setBufferCountServerLocked(bufferCount);
- }
-
- if (bufferCount < minBufferSlots) {
- ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
-
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references.
- freeAllBuffersLocked();
- mBufferCount = bufferCount;
- mClientBufferCount = bufferCount;
- mBufferHasBeenQueued = false;
- mQueue.clear();
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } // scope for lock
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return OK;
-}
-
-int BufferQueue::query(int what, int* outValue)
-{
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("query: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mPixelFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = mSynchronousMode ?
- (mMinUndequeuedBuffers-1) : mMinUndequeuedBuffers;
- break;
- case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
- value = (mQueue.size() >= 2);
- break;
- default:
- return BAD_VALUE;
- }
- outValue[0] = value;
- return NO_ERROR;
-}
-
-status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- ATRACE_CALL();
- ST_LOGV("requestBuffer: slot=%d", slot);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (slot < 0 || mBufferCount <= slot) {
- ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, slot);
- return BAD_VALUE;
- }
- mSlots[slot].mRequestBufferCalled = true;
- *buf = mSlots[slot].mGraphicBuffer;
- return NO_ERROR;
-}
-
-status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
- uint32_t format, uint32_t usage) {
- ATRACE_CALL();
- ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
-
- if ((w && !h) || (!w && h)) {
- ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
- return BAD_VALUE;
- }
-
- status_t returnFlags(OK);
- EGLDisplay dpy = EGL_NO_DISPLAY;
- EGLSyncKHR fence = EGL_NO_SYNC_KHR;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (format == 0) {
- format = mDefaultBufferFormat;
- }
- // turn on usage bits the consumer requested
- usage |= mConsumerUsageBits;
-
- int found = -1;
- int foundSync = -1;
- int dequeuedCount = 0;
- bool tryAgain = true;
- while (tryAgain) {
- if (mAbandoned) {
- ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- // We need to wait for the FIFO to drain if the number of buffer
- // needs to change.
- //
- // The condition "number of buffers needs to change" is true if
- // - the client doesn't care about how many buffers there are
- // - AND the actual number of buffer is different from what was
- // set in the last setBufferCountServer()
- // - OR -
- // setBufferCountServer() was set to a value incompatible with
- // the synchronization mode (for instance because the sync mode
- // changed since)
- //
- // As long as this condition is true AND the FIFO is not empty, we
- // wait on mDequeueCondition.
-
- const int minBufferCountNeeded = mSynchronousMode ?
- mMinSyncBufferSlots : mMinAsyncBufferSlots;
-
- const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
- ((mServerBufferCount != mBufferCount) ||
- (mServerBufferCount < minBufferCountNeeded));
-
- if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
- // wait for the FIFO to drain
- mDequeueCondition.wait(mMutex);
- // NOTE: we continue here because we need to reevaluate our
- // whole state (eg: we could be abandoned or disconnected)
- continue;
- }
-
- if (numberOfBuffersNeedsToChange) {
- // here we're guaranteed that mQueue is empty
- freeAllBuffersLocked();
- mBufferCount = mServerBufferCount;
- if (mBufferCount < minBufferCountNeeded)
- mBufferCount = minBufferCountNeeded;
- mBufferHasBeenQueued = false;
- returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
- }
-
- // look for a free buffer to give to the client
- found = INVALID_BUFFER_SLOT;
- foundSync = INVALID_BUFFER_SLOT;
- dequeuedCount = 0;
- for (int i = 0; i < mBufferCount; i++) {
- const int state = mSlots[i].mBufferState;
- if (state == BufferSlot::DEQUEUED) {
- dequeuedCount++;
- }
-
- // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER)
- // but dequeuing the current buffer is disabled.
- if (false) {
- // This functionality has been temporarily removed so
- // BufferQueue and SurfaceTexture can be refactored into
- // separate objects
- } else {
- if (state == BufferSlot::FREE) {
- /* We return the oldest of the free buffers to avoid
- * stalling the producer if possible. This is because
- * the consumer may still have pending reads of the
- * buffers in flight.
- */
- bool isOlder = mSlots[i].mFrameNumber <
- mSlots[found].mFrameNumber;
- if (found < 0 || isOlder) {
- foundSync = i;
- found = i;
- }
- }
- }
- }
-
- // clients are not allowed to dequeue more than one buffer
- // if they didn't set a buffer count.
- if (!mClientBufferCount && dequeuedCount) {
- ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
- "setting the buffer count");
- return -EINVAL;
- }
-
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the
- // mMinUndequeuedBuffers check below.
- if (mBufferHasBeenQueued) {
- // make sure the client is not trying to dequeue more buffers
- // than allowed.
- const int avail = mBufferCount - (dequeuedCount+1);
- if (avail < (mMinUndequeuedBuffers-int(mSynchronousMode))) {
- ST_LOGE("dequeueBuffer: mMinUndequeuedBuffers=%d exceeded "
- "(dequeued=%d)",
- mMinUndequeuedBuffers-int(mSynchronousMode),
- dequeuedCount);
- return -EBUSY;
- }
- }
-
- // if no buffer is found, wait for a buffer to be released
- tryAgain = found == INVALID_BUFFER_SLOT;
- if (tryAgain) {
- mDequeueCondition.wait(mMutex);
- }
- }
-
-
- if (found == INVALID_BUFFER_SLOT) {
- // This should not happen.
- ST_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- const int buf = found;
- *outBuf = found;
-
- ATRACE_BUFFER_INDEX(buf);
-
- const bool useDefaultSize = !w && !h;
- if (useDefaultSize) {
- // use the default size
- w = mDefaultWidth;
- h = mDefaultHeight;
- }
-
- const bool updateFormat = (format != 0);
- if (!updateFormat) {
- // keep the current (or default) format
- format = mPixelFormat;
- }
-
- // buffer is now in DEQUEUED (but can also be current at the same time,
- // if we're in synchronous mode)
- mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
- if ((buffer == NULL) ||
- (uint32_t(buffer->width) != w) ||
- (uint32_t(buffer->height) != h) ||
- (uint32_t(buffer->format) != format) ||
- ((uint32_t(buffer->usage) & usage) != usage))
- {
- status_t error;
- sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(w, h, format, usage);
- if (graphicBuffer == 0) {
- ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
- "failed");
- return error;
- }
- if (updateFormat) {
- mPixelFormat = format;
- }
-
- mSlots[buf].mAcquireCalled = false;
- mSlots[buf].mGraphicBuffer = graphicBuffer;
- mSlots[buf].mRequestBufferCalled = false;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
-
- returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
- }
-
- dpy = mSlots[buf].mEglDisplay;
- fence = mSlots[buf].mFence;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- } // end lock scope
-
- if (fence != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
- // If something goes wrong, log the error, but return the buffer without
- // synchronizing access to it. It's too late at this point to abort the
- // dequeue operation.
- if (result == EGL_FALSE) {
- ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ST_LOGE("dequeueBuffer: timeout waiting for fence");
- }
- eglDestroySyncKHR(dpy, fence);
- }
-
- ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
- mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
-
- return returnFlags;
-}
-
-status_t BufferQueue::setSynchronousMode(bool enabled) {
- ATRACE_CALL();
- ST_LOGV("setSynchronousMode: enabled=%d", enabled);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- status_t err = OK;
- if (!mAllowSynchronousMode && enabled)
- return err;
-
- if (!enabled) {
- // going to asynchronous mode, drain the queue
- err = drainQueueLocked();
- if (err != NO_ERROR)
- return err;
- }
-
- if (mSynchronousMode != enabled) {
- // - if we're going to asynchronous mode, the queue is guaranteed to be
- // empty here
- // - if the client set the number of buffers, we're guaranteed that
- // we have at least 3 (because we don't allow less)
- mSynchronousMode = enabled;
- mDequeueCondition.broadcast();
- }
- return err;
-}
-
-status_t BufferQueue::queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output) {
- ATRACE_CALL();
- ATRACE_BUFFER_INDEX(buf);
-
- Rect crop;
- uint32_t transform;
- int scalingMode;
- int64_t timestamp;
-
- input.deflate(&timestamp, &crop, &scalingMode, &transform);
-
- ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
- "scale=%s",
- buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
- transform, scalingModeName(scalingMode));
-
- sp<ConsumerListener> listener;
-
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return -EINVAL;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("queueBuffer: slot %d is not owned by the client "
- "(state=%d)", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- } else if (!mSlots[buf].mRequestBufferCalled) {
- ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
- "buffer", buf);
- return -EINVAL;
- }
-
- const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
- Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
- Rect croppedCrop;
- crop.intersect(bufferRect, &croppedCrop);
- if (croppedCrop != crop) {
- ST_LOGE("queueBuffer: crop rect is not contained within the "
- "buffer in slot %d", buf);
- return -EINVAL;
- }
-
- if (mSynchronousMode) {
- // In synchronous mode we queue all buffers in a FIFO.
- mQueue.push_back(buf);
-
- // Synchronous mode always signals that an additional frame should
- // be consumed.
- listener = mConsumerListener;
- } else {
- // In asynchronous mode we only keep the most recent buffer.
- if (mQueue.empty()) {
- mQueue.push_back(buf);
-
- // Asynchronous mode only signals that a frame should be
- // consumed if no previous frame was pending. If a frame were
- // pending then the consumer would have already been notified.
- listener = mConsumerListener;
- } else {
- Fifo::iterator front(mQueue.begin());
- // buffer currently queued is freed
- mSlots[*front].mBufferState = BufferSlot::FREE;
- // and we record the new buffer index in the queued list
- *front = buf;
- }
- }
-
- mSlots[buf].mTimestamp = timestamp;
- mSlots[buf].mCrop = crop;
- mSlots[buf].mTransform = transform;
-
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
- break;
- default:
- ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
- scalingMode = mSlots[buf].mScalingMode;
- break;
- }
-
- mSlots[buf].mBufferState = BufferSlot::QUEUED;
- mSlots[buf].mScalingMode = scalingMode;
- mFrameCounter++;
- mSlots[buf].mFrameNumber = mFrameCounter;
-
- mBufferHasBeenQueued = true;
- mDequeueCondition.broadcast();
-
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
- mQueue.size());
-
- ATRACE_INT(mConsumerName.string(), mQueue.size());
- } // scope for the lock
-
- // call back without lock held
- if (listener != 0) {
- listener->onFrameAvailable();
- }
- return OK;
-}
-
-void BufferQueue::cancelBuffer(int buf) {
- ATRACE_CALL();
- ST_LOGV("cancelBuffer: slot=%d", buf);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGW("cancelBuffer: BufferQueue has been abandoned!");
- return;
- }
-
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
- buf, mSlots[buf].mBufferState);
- return;
- }
- mSlots[buf].mBufferState = BufferSlot::FREE;
- mSlots[buf].mFrameNumber = 0;
- mDequeueCondition.broadcast();
-}
-
-status_t BufferQueue::connect(int api, QueueBufferOutput* output) {
- ATRACE_CALL();
- ST_LOGV("connect: api=%d", api);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("connect: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- if (mConsumerListener == NULL) {
- ST_LOGE("connect: BufferQueue has no consumer!");
- return NO_INIT;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi != NO_CONNECTED_API) {
- ST_LOGE("connect: already connected (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- } else {
- mConnectedApi = api;
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
- mQueue.size());
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
-
- mBufferHasBeenQueued = false;
-
- return err;
-}
-
-status_t BufferQueue::disconnect(int api) {
- ATRACE_CALL();
- ST_LOGV("disconnect: api=%d", api);
-
- int err = NO_ERROR;
- sp<ConsumerListener> listener;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // it is not really an error to disconnect after the surface
- // has been abandoned, it should just be a no-op.
- return NO_ERROR;
- }
-
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi == api) {
- drainQueueAndFreeBuffersLocked();
- mConnectedApi = NO_CONNECTED_API;
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } else {
- ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- }
- break;
- default:
- ST_LOGE("disconnect: unknown API %d", api);
- err = -EINVAL;
- break;
- }
- }
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return err;
-}
-
-void BufferQueue::dump(String8& result) const
-{
- char buffer[1024];
- BufferQueue::dump(result, "", buffer, 1024);
-}
-
-void BufferQueue::dump(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const
-{
- Mutex::Autolock _l(mMutex);
-
- String8 fifo;
- int fifoSize = 0;
- Fifo::const_iterator i(mQueue.begin());
- while (i != mQueue.end()) {
- snprintf(buffer, SIZE, "%02d ", *i++);
- fifoSize++;
- fifo.append(buffer);
- }
-
- snprintf(buffer, SIZE,
- "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
- "mPixelFormat=%d, FIFO(%d)={%s}\n",
- prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
- mDefaultHeight, mPixelFormat, fifoSize, fifo.string());
- result.append(buffer);
-
-
- struct {
- const char * operator()(int state) const {
- switch (state) {
- case BufferSlot::DEQUEUED: return "DEQUEUED";
- case BufferSlot::QUEUED: return "QUEUED";
- case BufferSlot::FREE: return "FREE";
- case BufferSlot::ACQUIRED: return "ACQUIRED";
- default: return "Unknown";
- }
- }
- } stateName;
-
- for (int i=0 ; i<mBufferCount ; i++) {
- const BufferSlot& slot(mSlots[i]);
- snprintf(buffer, SIZE,
- "%s%s[%02d] "
- "state=%-8s, crop=[%d,%d,%d,%d], "
- "xform=0x%02x, time=%#llx, scale=%s",
- prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
- stateName(slot.mBufferState),
- slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
- slot.mCrop.bottom, slot.mTransform, slot.mTimestamp,
- scalingModeName(slot.mScalingMode)
- );
- result.append(buffer);
-
- const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
- if (buf != NULL) {
- snprintf(buffer, SIZE,
- ", %p [%4ux%4u:%4u,%3X]",
- buf->handle, buf->width, buf->height, buf->stride,
- buf->format);
- result.append(buffer);
- }
- result.append("\n");
- }
-}
-
-void BufferQueue::freeBufferLocked(int i) {
- mSlots[i].mGraphicBuffer = 0;
- if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[i].mNeedsCleanupOnRelease = true;
- }
- mSlots[i].mBufferState = BufferSlot::FREE;
- mSlots[i].mFrameNumber = 0;
- mSlots[i].mAcquireCalled = false;
-
- // destroy fence as BufferQueue now takes ownership
- if (mSlots[i].mFence != EGL_NO_SYNC_KHR) {
- eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
- mSlots[i].mFence = EGL_NO_SYNC_KHR;
- }
-}
-
-void BufferQueue::freeAllBuffersLocked() {
- ALOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersLocked called but mQueue is not empty");
- mQueue.clear();
- mBufferHasBeenQueued = false;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
-}
-
-status_t BufferQueue::acquireBuffer(BufferItem *buffer) {
- ATRACE_CALL();
- Mutex::Autolock _l(mMutex);
- // check if queue is empty
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- int buf = *front;
-
- ATRACE_BUFFER_INDEX(buf);
-
- if (mSlots[buf].mAcquireCalled) {
- buffer->mGraphicBuffer = NULL;
- } else {
- buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
- }
- buffer->mCrop = mSlots[buf].mCrop;
- buffer->mTransform = mSlots[buf].mTransform;
- buffer->mScalingMode = mSlots[buf].mScalingMode;
- buffer->mFrameNumber = mSlots[buf].mFrameNumber;
- buffer->mTimestamp = mSlots[buf].mTimestamp;
- buffer->mBuf = buf;
- mSlots[buf].mAcquireCalled = true;
-
- mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
- mQueue.erase(front);
- mDequeueCondition.broadcast();
-
- ATRACE_INT(mConsumerName.string(), mQueue.size());
- } else {
- return NO_BUFFER_AVAILABLE;
- }
-
- return OK;
-}
-
-status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
- EGLSyncKHR fence) {
- ATRACE_CALL();
- ATRACE_BUFFER_INDEX(buf);
-
- Mutex::Autolock _l(mMutex);
-
- if (buf == INVALID_BUFFER_SLOT) {
- return -EINVAL;
- }
-
- mSlots[buf].mEglDisplay = display;
- mSlots[buf].mFence = fence;
-
- // The buffer can now only be released if its in the acquired state
- if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[buf].mBufferState = BufferSlot::FREE;
- } else if (mSlots[buf].mNeedsCleanupOnRelease) {
- ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
- mSlots[buf].mNeedsCleanupOnRelease = false;
- return STALE_BUFFER_SLOT;
- } else {
- ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- }
-
- mDequeueCondition.broadcast();
- return OK;
-}
-
-status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
- ST_LOGV("consumerConnect");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("consumerConnect: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- mConsumerListener = consumerListener;
-
- return OK;
-}
-
-status_t BufferQueue::consumerDisconnect() {
- ST_LOGV("consumerDisconnect");
- Mutex::Autolock lock(mMutex);
-
- if (mConsumerListener == NULL) {
- ST_LOGE("consumerDisconnect: No consumer is connected!");
- return -EINVAL;
- }
-
- mAbandoned = true;
- mConsumerListener = NULL;
- mQueue.clear();
- freeAllBuffersLocked();
- mDequeueCondition.broadcast();
- return OK;
-}
-
-status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) {
- ST_LOGV("getReleasedBuffers");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("getReleasedBuffers: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- uint32_t mask = 0;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (!mSlots[i].mAcquireCalled) {
- mask |= 1 << i;
- }
- }
- *slotMask = mask;
-
- ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
- return NO_ERROR;
-}
-
-status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
- ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
- if (!w || !h) {
- ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
- w, h);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return OK;
-}
-
-status_t BufferQueue::setBufferCountServer(int bufferCount) {
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
- return setBufferCountServerLocked(bufferCount);
-}
-
-void BufferQueue::freeAllBuffersExceptHeadLocked() {
- int head = -1;
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- head = *front;
- }
- mBufferHasBeenQueued = false;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (i != head) {
- freeBufferLocked(i);
- }
- }
-}
-
-status_t BufferQueue::drainQueueLocked() {
- while (mSynchronousMode && !mQueue.isEmpty()) {
- mDequeueCondition.wait(mMutex);
- if (mAbandoned) {
- ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
- return NO_INIT;
- }
- if (mConnectedApi == NO_CONNECTED_API) {
- ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
- return NO_INIT;
- }
- }
- return NO_ERROR;
-}
-
-status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
- status_t err = drainQueueLocked();
- if (err == NO_ERROR) {
- if (mSynchronousMode) {
- freeAllBuffersLocked();
- } else {
- freeAllBuffersExceptHeadLocked();
- }
- }
- return err;
-}
-
-BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
- const wp<BufferQueue::ConsumerListener>& consumerListener):
- mConsumerListener(consumerListener) {}
-
-BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
-
-void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
- sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable();
- }
-}
-
-void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
- sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
-}; // namespace android
-
-#endif
diff --git a/src/imports/nativemedia/BufferQueue.h b/src/imports/nativemedia/BufferQueue.h
deleted file mode 100644
index 1c80d0c..0000000
--- a/src/imports/nativemedia/BufferQueue.h
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_GUI_BUFFERQUEUE_H
-#define ANDROID_GUI_BUFFERQUEUE_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceTexture.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class BufferQueue : public BnSurfaceTexture {
-public:
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
- enum { NUM_BUFFER_SLOTS = 32 };
- enum { NO_CONNECTED_API = 0 };
- enum { INVALID_BUFFER_SLOT = -1 };
- enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
-
- // ConsumerListener is the interface through which the BufferQueue notifies
- // the consumer of events that the consumer may wish to react to. Because
- // the consumer will generally have a mutex that is locked during calls from
- // teh consumer to the BufferQueue, these calls from the BufferQueue to the
- // consumer *MUST* be called only when the BufferQueue mutex is NOT locked.
- struct ConsumerListener : public virtual RefBase {
- // onFrameAvailable is called from queueBuffer each time an additional
- // frame becomes available for consumption. This means that frames that
- // are queued while in asynchronous mode only trigger the callback if no
- // previous frames are pending. Frames queued while in synchronous mode
- // always trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
-
- // onBuffersReleased is called to notify the buffer consumer that the
- // BufferQueue has released its references to one or more GraphicBuffers
- // contained in its slots. The buffer consumer should then call
- // BufferQueue::getReleasedBuffers to retrieve the list of buffers
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onBuffersReleased() = 0;
- };
-
- // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
- // reference to the actual consumer object. It forwards all calls to that
- // consumer object so long as it exists.
- //
- // This class exists to avoid having a circular reference between the
- // BufferQueue object and the consumer object. The reason this can't be a weak
- // reference in the BufferQueue class is because we're planning to expose the
- // consumer side of a BufferQueue as a binder interface, which doesn't support
- // weak references.
- class ProxyConsumerListener : public BufferQueue::ConsumerListener {
- public:
-
- ProxyConsumerListener(const wp<BufferQueue::ConsumerListener>& consumerListener);
- virtual ~ProxyConsumerListener();
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- private:
-
- // mConsumerListener is a weak reference to the ConsumerListener. This is
- // the raison d'etre of ProxyConsumerListener.
- wp<BufferQueue::ConsumerListener> mConsumerListener;
- };
-
-
- // BufferQueue manages a pool of gralloc memory slots to be used
- // by producers and consumers.
- // allowSynchronousMode specifies whether or not synchronous mode can be
- // enabled.
- // bufferCount sets the minimum number of undequeued buffers for this queue
- BufferQueue( bool allowSynchronousMode = true, int bufferCount = MIN_UNDEQUEUED_BUFFERS);
- virtual ~BufferQueue();
-
- virtual int query(int what, int* value);
-
- // setBufferCount updates the number of available buffer slots. After
- // calling this all buffer slots are both unallocated and owned by the
- // BufferQueue object (i.e. they are not owned by the client).
- virtual status_t setBufferCount(int bufferCount);
-
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-
- // dequeueBuffer gets the next buffer slot index for the client to use. If a
- // buffer slot is available then that slot index is written to the location
- // pointed to by the buf argument and a status of OK is returned. If no
- // slot is available then a status of -EBUSY is returned and buf is
- // unmodified.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
-
- // queueBuffer returns a filled buffer to the BufferQueue. In addition, a
- // timestamp must be provided for the buffer. The timestamp is in
- // nanoseconds, and must be monotonically increasing. Its other semantics
- // (zero point, etc) are client-dependent and should be documented by the
- // client.
- virtual status_t queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output);
-
- virtual void cancelBuffer(int buf);
-
- // setSynchronousMode set whether dequeueBuffer is synchronous or
- // asynchronous. In synchronous mode, dequeueBuffer blocks until
- // a buffer is available, the currently bound buffer can be dequeued and
- // queued buffers will be retired in order.
- // The default mode is asynchronous.
- virtual status_t setSynchronousMode(bool enabled);
-
- // connect attempts to connect a producer client API to the BufferQueue.
- // This must be called before any other ISurfaceTexture methods are called
- // except for getAllocator.
- //
- // This method will fail if the connect was previously called on the
- // BufferQueue and no corresponding disconnect call was made.
- virtual status_t connect(int api, QueueBufferOutput* output);
-
- // disconnect attempts to disconnect a producer client API from the
- // BufferQueue. Calling this method will cause any subsequent calls to other
- // ISurfaceTexture methods to fail except for getAllocator and connect.
- // Successfully calling connect after this will allow the other methods to
- // succeed again.
- //
- // This method will fail if the the BufferQueue is not currently
- // connected to the specified client API.
- virtual status_t disconnect(int api);
-
- // dump our state in a String
- virtual void dump(String8& result) const;
- virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
- // public facing structure for BufferSlot
- struct BufferItem {
-
- BufferItem()
- :
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mBuf(INVALID_BUFFER_SLOT) {
- mCrop.makeInvalid();
- }
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mBuf is the slot index of this buffer
- int mBuf;
- };
-
- // The following public functions is the consumer facing interface
-
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the BufferQueue. If no buffer is pending then it returns -EINVAL. If a
- // buffer is successfully acquired, the information about the buffer is
- // returned in BufferItem. If the buffer returned had previously been
- // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
- // NULL and it is assumed that the consumer still holds a reference to the
- // buffer.
- status_t acquireBuffer(BufferItem *buffer);
-
- // releaseBuffer releases a buffer slot from the consumer back to the
- // BufferQueue pending a fence sync.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
- status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence);
-
- // consumerConnect connects a consumer to the BufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // BufferQueue is placed into the "abandoned" state, causing most
- // interactions with the BufferQueue by the producer to fail.
- status_t consumerConnect(const sp<ConsumerListener>& consumer);
-
- // consumerDisconnect disconnects a consumer from the BufferQueue. All
- // buffers will be freed and the BufferQueue is placed in the "abandoned"
- // state, causing most interactions with the BufferQueue by the producer to
- // fail.
- status_t consumerDisconnect();
-
- // getReleasedBuffers sets the value pointed to by slotMask to a bit mask
- // indicating which buffer slots the have been released by the BufferQueue
- // but have not yet been released by the consumer.
- status_t getReleasedBuffers(uint32_t* slotMask);
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setBufferCountServer set the buffer count. If the client has requested
- // a buffer count using setBufferCount, the server-buffer count will
- // take effect once the client sets the count back to zero.
- status_t setBufferCountServer(int bufferCount);
-
- // isSynchronousMode returns whether the SurfaceTexture is currently in
- // synchronous mode.
- bool isSynchronousMode() const;
-
- // setConsumerName sets the name used in logging
- void setConsumerName(const String8& name);
-
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer
- status_t setConsumerUsageBits(uint32_t usage);
-
- // setTransformHint bakes in rotation to buffers so overlays can be used
- status_t setTransformHint(uint32_t hint);
-
-private:
- // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
- // for the given slot.
- void freeBufferLocked(int index);
-
- // freeAllBuffersLocked frees the resources (both GraphicBuffer and
- // EGLImage) for all slots.
- void freeAllBuffersLocked();
-
- // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer
- // and EGLImage) for all slots except the head of mQueue
- void freeAllBuffersExceptHeadLocked();
-
- // drainQueueLocked drains the buffer queue if we're in synchronous mode
- // returns immediately otherwise. It returns NO_INIT if the BufferQueue
- // became abandoned or disconnected during this call.
- status_t drainQueueLocked();
-
- // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
- // synchronous mode and free all buffers. In asynchronous mode, all buffers
- // are freed except the current buffer.
- status_t drainQueueAndFreeBuffersLocked();
-
- status_t setBufferCountServerLocked(int bufferCount);
-
- struct BufferSlot {
-
- BufferSlot()
- : mEglDisplay(EGL_NO_DISPLAY),
- mBufferState(BufferSlot::FREE),
- mRequestBufferCalled(false),
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mFence(EGL_NO_SYNC_KHR),
- mAcquireCalled(false),
- mNeedsCleanupOnRelease(false) {
- mCrop.makeInvalid();
- }
-
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mEglDisplay is the EGLDisplay used to create mEglImage.
- EGLDisplay mEglDisplay;
-
- // BufferState represents the different states in which a buffer slot
- // can be.
- enum BufferState {
- // FREE indicates that the buffer is not currently being used and
- // will not be used in the future until it gets dequeued and
- // subsequently queued by the client.
- // aka "owned by BufferQueue, ready to be dequeued"
- FREE = 0,
-
- // DEQUEUED indicates that the buffer has been dequeued by the
- // client, but has not yet been queued or canceled. The buffer is
- // considered 'owned' by the client, and the server should not use
- // it for anything.
- //
- // Note that when in synchronous-mode (mSynchronousMode == true),
- // the buffer that's currently attached to the texture may be
- // dequeued by the client. That means that the current buffer can
- // be in either the DEQUEUED or QUEUED state. In asynchronous mode,
- // however, the current buffer is always in the QUEUED state.
- // aka "owned by producer, ready to be queued"
- DEQUEUED = 1,
-
- // QUEUED indicates that the buffer has been queued by the client,
- // and has not since been made available for the client to dequeue.
- // Attaching the buffer to the texture does NOT transition the
- // buffer away from the QUEUED state. However, in Synchronous mode
- // the current buffer may be dequeued by the client under some
- // circumstances. See the note about the current buffer in the
- // documentation for DEQUEUED.
- // aka "owned by BufferQueue, ready to be acquired"
- QUEUED = 2,
-
- // aka "owned by consumer, ready to be released"
- ACQUIRED = 3
- };
-
- // mBufferState is the current state of this buffer slot.
- BufferState mBufferState;
-
- // mRequestBufferCalled is used for validating that the client did
- // call requestBuffer() when told to do so. Technically this is not
- // needed but useful for debugging and catching client bugs.
- bool mRequestBufferCalled;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mFence is the EGL sync object that must signal before the buffer
- // associated with this buffer slot may be dequeued. It is initialized
- // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
- // on a compile-time option) set to a new sync object in updateTexImage.
- EGLSyncKHR mFence;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates whether this buffer needs to be cleaned up by consumer
- bool mNeedsCleanupOnRelease;
- };
-
- // mSlots is the array of buffer slots that must be mirrored on the client
- // side. This allows buffer ownership to be transferred between the client
- // and server without sending a GraphicBuffer over binder. The entire array
- // is initialized to NULL at construction time, and buffers are allocated
- // for a slot when requestBuffer is called with that slot's index.
- BufferSlot mSlots[NUM_BUFFER_SLOTS];
-
- // mDefaultWidth holds the default width of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultWidth;
-
- // mDefaultHeight holds the default height of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultHeight;
-
- // mPixelFormat holds the pixel format of allocated buffers. It is used
- // in requestBuffers() if a format of zero is specified.
- uint32_t mPixelFormat;
-
- // mMinUndequeuedBuffers is a constraint on the number of buffers
- // not dequeued at any time
- int mMinUndequeuedBuffers;
-
- // mMinAsyncBufferSlots is a constraint on the minimum mBufferCount
- // when this BufferQueue is in asynchronous mode
- int mMinAsyncBufferSlots;
-
- // mMinSyncBufferSlots is a constraint on the minimum mBufferCount
- // when this BufferQueue is in synchronous mode
- int mMinSyncBufferSlots;
-
- // mBufferCount is the number of buffer slots that the client and server
- // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
- // by calling setBufferCount or setBufferCountServer
- int mBufferCount;
-
- // mClientBufferCount is the number of buffer slots requested by the client.
- // The default is zero, which means the client doesn't care how many buffers
- // there is.
- int mClientBufferCount;
-
- // mServerBufferCount buffer count requested by the server-side
- int mServerBufferCount;
-
- // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
- // allocate new GraphicBuffer objects.
- sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
-
- // mConsumerListener is used to notify the connected consumer of
- // asynchronous events that it may wish to react to. It is initially set
- // to NULL and is written by consumerConnect and consumerDisconnect.
- sp<ConsumerListener> mConsumerListener;
-
- // mSynchronousMode whether we're in synchronous mode or not
- bool mSynchronousMode;
-
- // mAllowSynchronousMode whether we allow synchronous mode or not
- const bool mAllowSynchronousMode;
-
- // mConnectedApi indicates the API that is currently connected to this
- // BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets updated
- // by the connect and disconnect methods.
- int mConnectedApi;
-
- // mDequeueCondition condition used for dequeueBuffer in synchronous mode
- mutable Condition mDequeueCondition;
-
- // mQueue is a FIFO of queued buffers used in synchronous mode
- typedef Vector<int> Fifo;
- Fifo mQueue;
-
- // mAbandoned indicates that the BufferQueue will no longer be used to
- // consume images buffers pushed to it using the ISurfaceTexture interface.
- // It is initialized to false, and set to true in the abandon method. A
- // BufferQueue that has been abandoned will return the NO_INIT error from
- // all ISurfaceTexture methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the BufferQueue in log messages.
- // It is set by the setName method.
- String8 mConsumerName;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of BufferQueue objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-
- // mFrameCounter is the free running counter, incremented for every buffer queued
- // with the surface Texture.
- uint64_t mFrameCounter;
-
- // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
- // by changing the buffer count.
- bool mBufferHasBeenQueued;
-
- // mDefaultBufferFormat can be set so it will override
- // the buffer format when it isn't specified in dequeueBuffer
- uint32_t mDefaultBufferFormat;
-
- // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
- uint32_t mConsumerUsageBits;
-
- // mTransformHint is used to optimize for screen rotations
- uint32_t mTransformHint;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_BUFFERQUEUE_H
diff --git a/src/imports/nativemedia/SurfaceTexture.cpp b/src/imports/nativemedia/SurfaceTexture.cpp
deleted file mode 100644
index 05207ad..0000000
--- a/src/imports/nativemedia/SurfaceTexture.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1)
-#include "SurfaceTexture_4_1.cpp"
-#else
-#include "SurfaceTexture_4_0.cpp"
-#endif
diff --git a/src/imports/nativemedia/SurfaceTexture.h b/src/imports/nativemedia/SurfaceTexture.h
deleted file mode 100644
index 552d465..0000000
--- a/src/imports/nativemedia/SurfaceTexture.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1)
-#include "SurfaceTexture_4_1.h"
-#else
-#include "SurfaceTexture_4_0.h"
-#endif
diff --git a/src/imports/nativemedia/SurfaceTexture_4_0.cpp b/src/imports/nativemedia/SurfaceTexture_4_0.cpp
deleted file mode 100644
index 1ec08a7..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_0.cpp
+++ /dev/null
@@ -1,1236 +0,0 @@
-/*
- * Copyright (C) 2010 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_TAG "SurfaceTexture"
-//#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <SurfaceTexture.h>
-
-#include <hardware/hardware.h>
-
-#include <surfaceflinger/SurfaceComposerClient.h>
-#include <surfaceflinger/IGraphicBufferAlloc.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include <QtDebug>
-
-// This compile option causes SurfaceTexture to return the buffer that is currently
-// attached to the GL texture from dequeueBuffer when no other buffers are
-// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
-// implicit cross-process synchronization to prevent the buffer from being
-// written to before the buffer has (a) been detached from the GL texture and
-// (b) all GL reads from the buffer have completed.
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
-#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
-#else
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
-#endif
-
-// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
-// to synchronize access to the buffers. It will cause dequeueBuffer to stall,
-// waiting for the GL reads for the buffer being dequeued to complete before
-// allowing the buffer to be dequeued.
-#ifdef USE_FENCE_SYNC
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
-#endif
-#endif
-
-// Macros for including the SurfaceTexture name in log messages
-#if 0
-#define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
-#else
-#define ST_LOGV(x, ...) LOGV("[V/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) LOGD("[D/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) qDebug("[I/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) qDebug("[W/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) qDebug("[E/%s] "x, mName.string(), ##__VA_ARGS__)
-#endif
-
-namespace android {
-
-// Transform matrices
-static float mtxIdentity[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
-};
-static float mtxFlipH[16] = {
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxFlipV[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-static float mtxRot90[16] = {
- 0, 1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxRot180[16] = {
- -1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 1, 1, 0, 1,
-};
-static float mtxRot270[16] = {
- 0, -1, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-
-static void mtxMul(float out[16], const float a[16], const float b[16]);
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
- GLenum texTarget, bool useFenceSync) :
- mDefaultWidth(1),
- mDefaultHeight(1),
- mPixelFormat(PIXEL_FORMAT_RGBA_8888),
- mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
- mClientBufferCount(0),
- mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
- mCurrentTexture(INVALID_BUFFER_SLOT),
- mCurrentTransform(0),
- mCurrentTimestamp(0),
- mNextTransform(0),
- mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTexName(tex),
- mSynchronousMode(false),
- mAllowSynchronousMode(allowSynchronousMode),
- mConnectedApi(NO_CONNECTED_API),
- mAbandoned(false),
-#ifdef USE_FENCE_SYNC
- mUseFenceSync(useFenceSync),
-#else
- mUseFenceSync(false),
-#endif
- mTexTarget(texTarget),
- mFrameCounter(0) {
- // Choose a name using the PID and a process-unique ID.
- mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- ST_LOGV("SurfaceTexture");
-// sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-// mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
- mNextCrop.makeInvalid();
- memcpy(mCurrentTransformMatrix, mtxIdentity,
- sizeof(mCurrentTransformMatrix));
-}
-
-SurfaceTexture::~SurfaceTexture() {
- ST_LOGV("~SurfaceTexture");
- freeAllBuffersLocked();
-}
-
-status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) {
- if (bufferCount > NUM_BUFFER_SLOTS)
- return BAD_VALUE;
-
- // special-case, nothing to do
- if (bufferCount == mBufferCount)
- return OK;
-
- if (!mClientBufferCount &&
- bufferCount >= mBufferCount) {
- // easy, we just have more buffers
- mBufferCount = bufferCount;
- mServerBufferCount = bufferCount;
- mDequeueCondition.signal();
- } else {
- // we're here because we're either
- // - reducing the number of available buffers
- // - or there is a client-buffer-count in effect
-
- // less than 2 buffers is never allowed
- if (bufferCount < 2)
- return BAD_VALUE;
-
- // when there is non client-buffer-count in effect, the client is not
- // allowed to dequeue more than one buffer at a time,
- // so the next time they dequeue a buffer, we know that they don't
- // own one. the actual resizing will happen during the next
- // dequeueBuffer.
-
- mServerBufferCount = bufferCount;
- }
- return OK;
-}
-
-status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
- Mutex::Autolock lock(mMutex);
- return setBufferCountServerLocked(bufferCount);
-}
-
-status_t SurfaceTexture::setBufferCount(int bufferCount) {
- ST_LOGV("setBufferCount: count=%d", bufferCount);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ST_LOGE("setBufferCount: bufferCount larger than slots available");
- return BAD_VALUE;
- }
-
- // Error out if the user has dequeued buffers
- for (int i=0 ; i<mBufferCount ; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ST_LOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
-
- const int minBufferSlots = mSynchronousMode ?
- MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
- if (bufferCount == 0) {
- mClientBufferCount = 0;
- bufferCount = (mServerBufferCount >= minBufferSlots) ?
- mServerBufferCount : minBufferSlots;
- return setBufferCountServerLocked(bufferCount);
- }
-
- if (bufferCount < minBufferSlots) {
- ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
-
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references.
- freeAllBuffersLocked();
- mBufferCount = bufferCount;
- mClientBufferCount = bufferCount;
- mCurrentTexture = INVALID_BUFFER_SLOT;
- mQueue.clear();
- mDequeueCondition.signal();
- return OK;
-}
-
-status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
- ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
- if (!w || !h) {
- ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
- w, h);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return OK;
-}
-
-status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- ST_LOGV("requestBuffer: slot=%d", slot);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (slot < 0 || mBufferCount <= slot) {
- ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, slot);
- return BAD_VALUE;
- }
- mSlots[slot].mRequestBufferCalled = true;
- *buf = mSlots[slot].mGraphicBuffer;
- return NO_ERROR;
-}
-
-status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
- uint32_t format, uint32_t usage) {
- ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
-
- if ((w && !h) || (!w && h)) {
- ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
- return BAD_VALUE;
- }
-
- status_t returnFlags(OK);
- EGLDisplay dpy = EGL_NO_DISPLAY;
- EGLSyncKHR fence = EGL_NO_SYNC_KHR;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- int found = -1;
- int foundSync = -1;
- int dequeuedCount = 0;
- bool tryAgain = true;
- while (tryAgain) {
- if (mAbandoned) {
- ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- // We need to wait for the FIFO to drain if the number of buffer
- // needs to change.
- //
- // The condition "number of buffers needs to change" is true if
- // - the client doesn't care about how many buffers there are
- // - AND the actual number of buffer is different from what was
- // set in the last setBufferCountServer()
- // - OR -
- // setBufferCountServer() was set to a value incompatible with
- // the synchronization mode (for instance because the sync mode
- // changed since)
- //
- // As long as this condition is true AND the FIFO is not empty, we
- // wait on mDequeueCondition.
-
- const int minBufferCountNeeded = mSynchronousMode ?
- MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
-
- const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
- ((mServerBufferCount != mBufferCount) ||
- (mServerBufferCount < minBufferCountNeeded));
-
- if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
- // wait for the FIFO to drain
- mDequeueCondition.wait(mMutex);
- // NOTE: we continue here because we need to reevaluate our
- // whole state (eg: we could be abandoned or disconnected)
- continue;
- }
-
- if (numberOfBuffersNeedsToChange) {
- // here we're guaranteed that mQueue is empty
- freeAllBuffersLocked();
- mBufferCount = mServerBufferCount;
- if (mBufferCount < minBufferCountNeeded)
- mBufferCount = minBufferCountNeeded;
- mCurrentTexture = INVALID_BUFFER_SLOT;
- returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
- }
-
- // look for a free buffer to give to the client
- found = INVALID_BUFFER_SLOT;
- foundSync = INVALID_BUFFER_SLOT;
- dequeuedCount = 0;
- for (int i = 0; i < mBufferCount; i++) {
- const int state = mSlots[i].mBufferState;
- if (state == BufferSlot::DEQUEUED) {
- dequeuedCount++;
- }
-
- // if buffer is FREE it CANNOT be current
- LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
- "dequeueBuffer: buffer %d is both FREE and current!",
- i);
-
- if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
- if (state == BufferSlot::FREE || i == mCurrentTexture) {
- foundSync = i;
- if (i != mCurrentTexture) {
- found = i;
- break;
- }
- }
- } else {
- if (state == BufferSlot::FREE) {
- /* We return the oldest of the free buffers to avoid
- * stalling the producer if possible. This is because
- * the consumer may still have pending reads of the
- * buffers in flight.
- */
- bool isOlder = mSlots[i].mFrameNumber <
- mSlots[found].mFrameNumber;
- if (found < 0 || isOlder) {
- foundSync = i;
- found = i;
- }
- }
- }
- }
-
- // clients are not allowed to dequeue more than one buffer
- // if they didn't set a buffer count.
- if (!mClientBufferCount && dequeuedCount) {
- ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
- "setting the buffer count");
- return -EINVAL;
- }
-
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the
- // MIN_UNDEQUEUED_BUFFERS check below.
- bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
- if (bufferHasBeenQueued) {
- // make sure the client is not trying to dequeue more buffers
- // than allowed.
- const int avail = mBufferCount - (dequeuedCount+1);
- if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
- ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
- "(dequeued=%d)",
- MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
- dequeuedCount);
- return -EBUSY;
- }
- }
-
- // we're in synchronous mode and didn't find a buffer, we need to
- // wait for some buffers to be consumed
- tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
- if (tryAgain) {
- mDequeueCondition.wait(mMutex);
- }
- }
-
- if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
- // foundSync guaranteed to be != INVALID_BUFFER_SLOT
- found = foundSync;
- }
-
- if (found == INVALID_BUFFER_SLOT) {
- // This should not happen.
- ST_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- const int buf = found;
- *outBuf = found;
-
- const bool useDefaultSize = !w && !h;
- if (useDefaultSize) {
- // use the default size
- w = mDefaultWidth;
- h = mDefaultHeight;
- }
-
- const bool updateFormat = (format != 0);
- if (!updateFormat) {
- // keep the current (or default) format
- format = mPixelFormat;
- }
-
- // buffer is now in DEQUEUED (but can also be current at the same time,
- // if we're in synchronous mode)
- mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
- if ((buffer == NULL) ||
- (uint32_t(buffer->width) != w) ||
- (uint32_t(buffer->height) != h) ||
- (uint32_t(buffer->format) != format) ||
- ((uint32_t(buffer->usage) & usage) != usage))
- {
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- status_t error;
- sp<GraphicBuffer> graphicBuffer(
- new GraphicBuffer(w, h, format, usage));
-// mGraphicBufferAlloc->createGraphicBuffer(
-// w, h, format, usage, &error));
- if (graphicBuffer == 0) {
- ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
- "failed");
- return error;
- }
- if (updateFormat) {
- mPixelFormat = format;
- }
- mSlots[buf].mGraphicBuffer = graphicBuffer;
- mSlots[buf].mRequestBufferCalled = false;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mSlots[buf].mEglDisplay,
- mSlots[buf].mEglImage);
- mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
- mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
- }
- if (mCurrentTexture == buf) {
- // The current texture no longer references the buffer in this slot
- // since we just allocated a new buffer.
- mCurrentTexture = INVALID_BUFFER_SLOT;
- }
- returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
- }
-
- dpy = mSlots[buf].mEglDisplay;
- fence = mSlots[buf].mFence;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- }
-
- if (fence != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
- // If something goes wrong, log the error, but return the buffer without
- // synchronizing access to it. It's too late at this point to abort the
- // dequeue operation.
- if (result == EGL_FALSE) {
- LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- LOGE("dequeueBuffer: timeout waiting for fence");
- }
- eglDestroySyncKHR(dpy, fence);
- }
-
- ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
- mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
-
- return returnFlags;
-}
-
-status_t SurfaceTexture::setSynchronousMode(bool enabled) {
- ST_LOGV("setSynchronousMode: enabled=%d", enabled);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- status_t err = OK;
- if (!mAllowSynchronousMode && enabled)
- return err;
-
- if (!enabled) {
- // going to asynchronous mode, drain the queue
- err = drainQueueLocked();
- if (err != NO_ERROR)
- return err;
- }
-
- if (mSynchronousMode != enabled) {
- // - if we're going to asynchronous mode, the queue is guaranteed to be
- // empty here
- // - if the client set the number of buffers, we're guaranteed that
- // we have at least 3 (because we don't allow less)
- mSynchronousMode = enabled;
- mDequeueCondition.signal();
- }
- return err;
-}
-
-status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
- ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
-
- sp<FrameAvailableListener> listener;
-
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return -EINVAL;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("queueBuffer: slot %d is not owned by the client "
- "(state=%d)", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- } else if (buf == mCurrentTexture) {
- ST_LOGE("queueBuffer: slot %d is current!", buf);
- return -EINVAL;
- } else if (!mSlots[buf].mRequestBufferCalled) {
- ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
- "buffer", buf);
- return -EINVAL;
- }
-
- if (mSynchronousMode) {
- // In synchronous mode we queue all buffers in a FIFO.
- mQueue.push_back(buf);
-
- // Synchronous mode always signals that an additional frame should
- // be consumed.
- listener = mFrameAvailableListener;
- } else {
- // In asynchronous mode we only keep the most recent buffer.
- if (mQueue.empty()) {
- mQueue.push_back(buf);
-
- // Asynchronous mode only signals that a frame should be
- // consumed if no previous frame was pending. If a frame were
- // pending then the consumer would have already been notified.
- listener = mFrameAvailableListener;
- } else {
- Fifo::iterator front(mQueue.begin());
- // buffer currently queued is freed
- mSlots[*front].mBufferState = BufferSlot::FREE;
- // and we record the new buffer index in the queued list
- *front = buf;
- }
- }
-
- mSlots[buf].mBufferState = BufferSlot::QUEUED;
- mSlots[buf].mCrop = mNextCrop;
- mSlots[buf].mTransform = mNextTransform;
- mSlots[buf].mScalingMode = mNextScalingMode;
- mSlots[buf].mTimestamp = timestamp;
- mFrameCounter++;
- mSlots[buf].mFrameNumber = mFrameCounter;
-
- mDequeueCondition.signal();
-
- *outWidth = mDefaultWidth;
- *outHeight = mDefaultHeight;
- *outTransform = 0;
- } // scope for the lock
-
- // call back without lock held
- if (listener != 0) {
- listener->onFrameAvailable();
- }
- return OK;
-}
-
-void SurfaceTexture::cancelBuffer(int buf) {
- ST_LOGV("cancelBuffer: slot=%d", buf);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
- return;
- }
-
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
- buf, mSlots[buf].mBufferState);
- return;
- }
- mSlots[buf].mBufferState = BufferSlot::FREE;
- mSlots[buf].mFrameNumber = 0;
- mDequeueCondition.signal();
-}
-
-status_t SurfaceTexture::setCrop(const Rect& crop) {
- ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
- crop.bottom);
-
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("setCrop: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- mNextCrop = crop;
- return OK;
-}
-
-status_t SurfaceTexture::setTransform(uint32_t transform) {
- ST_LOGV("setTransform: xform=%#x", transform);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("setTransform: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- mNextTransform = transform;
- return OK;
-}
-
-status_t SurfaceTexture::connect(int api,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
- ST_LOGV("connect: api=%d", api);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("connect: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi != NO_CONNECTED_API) {
- ST_LOGE("connect: already connected (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- } else {
- mConnectedApi = api;
- *outWidth = mDefaultWidth;
- *outHeight = mDefaultHeight;
- *outTransform = 0;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-status_t SurfaceTexture::disconnect(int api) {
- ST_LOGV("disconnect: api=%d", api);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // it is not really an error to disconnect after the surface
- // has been abandoned, it should just be a no-op.
- return NO_ERROR;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi == api) {
- drainQueueAndFreeBuffersLocked();
- mConnectedApi = NO_CONNECTED_API;
- mNextCrop.makeInvalid();
- mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
- mNextTransform = 0;
- mDequeueCondition.signal();
- } else {
- ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- }
- break;
- default:
- ST_LOGE("disconnect: unknown API %d", api);
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-status_t SurfaceTexture::setScalingMode(int mode) {
- ST_LOGV("setScalingMode: mode=%d", mode);
-
- switch (mode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
- break;
- default:
- ST_LOGE("unknown scaling mode: %d", mode);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mNextScalingMode = mode;
- return OK;
-}
-
-status_t SurfaceTexture::updateTexImage() {
- ST_LOGV("updateTexImage");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- qDebug("calling updateTexImage() on an abandoned SurfaceTexture");
- return NO_INIT;
- }
-
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- int buf = *front;
-
- // Update the GL texture object.
- EGLImageKHR image = mSlots[buf].mEglImage;
- EGLDisplay dpy = eglGetCurrentDisplay();
- if (image == EGL_NO_IMAGE_KHR) {
- if (mSlots[buf].mGraphicBuffer == 0) {
- qDebug("buffer at slot %d is null", buf);
- return BAD_VALUE;
- }
- image = createImage(dpy, mSlots[buf].mGraphicBuffer);
- mSlots[buf].mEglImage = image;
- mSlots[buf].mEglDisplay = dpy;
- if (image == EGL_NO_IMAGE_KHR) {
- // NOTE: if dpy was invalid, createImage() is guaranteed to
- // fail. so we'd end up here.
- qDebug("EGL_NO_IMAGE_KHR: %p", dpy);
- return -EINVAL;
- }
- }
-
- GLint error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
- }
-
- glBindTexture(mTexTarget, mTexName);
- glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
-
- bool failed = false;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("error binding external texture image %p (slot %d): %#04x",
- image, buf, error);
- failed = true;
- }
- if (failed) {
- return -EINVAL;
- }
-
- if (mCurrentTexture != INVALID_BUFFER_SLOT) {
- if (mUseFenceSync) {
- EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR,
- NULL);
- if (fence == EGL_NO_SYNC_KHR) {
- ST_LOGE("updateTexImage: error creating fence: %#x",
- eglGetError());
- return -EINVAL;
- }
- glFlush();
- mSlots[mCurrentTexture].mFence = fence;
- }
- }
-
- ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
- mCurrentTexture,
- mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
- buf, mSlots[buf].mGraphicBuffer->handle);
-
- if (mCurrentTexture != INVALID_BUFFER_SLOT) {
- // The current buffer becomes FREE if it was still in the queued
- // state. If it has already been given to the client
- // (synchronous mode), then it stays in DEQUEUED state.
- if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) {
- mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
- }
- }
-
- // Update the SurfaceTexture state.
- mCurrentTexture = buf;
- mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
- mCurrentCrop = mSlots[buf].mCrop;
- mCurrentTransform = mSlots[buf].mTransform;
- mCurrentScalingMode = mSlots[buf].mScalingMode;
- mCurrentTimestamp = mSlots[buf].mTimestamp;
- computeCurrentTransformMatrix();
-
- // Now that we've passed the point at which failures can happen,
- // it's safe to remove the buffer from the front of the queue.
- mQueue.erase(front);
- mDequeueCondition.signal();
- } else {
- // We always bind the texture even if we don't update its contents.
- glBindTexture(mTexTarget, mTexName);
- }
-
- return OK;
-}
-
-bool SurfaceTexture::isExternalFormat(uint32_t format)
-{
- switch (format) {
- // supported YUV formats
- case HAL_PIXEL_FORMAT_YV12:
- // Legacy/deprecated YUV formats
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return true;
- }
-
- // Any OEM format needs to be considered
- if (format>=0x100 && format<=0x1FF)
- return true;
-
- return false;
-}
-
-GLenum SurfaceTexture::getCurrentTextureTarget() const {
- return mTexTarget;
-}
-
-void SurfaceTexture::getTransformMatrix(float mtx[16]) {
- Mutex::Autolock lock(mMutex);
- memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
-}
-
-void SurfaceTexture::computeCurrentTransformMatrix() {
- ST_LOGV("computeCurrentTransformMatrix");
-
- float xform[16];
- for (int i = 0; i < 16; i++) {
- xform[i] = mtxIdentity[i];
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- float result[16];
- mtxMul(result, xform, mtxFlipH);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- float result[16];
- mtxMul(result, xform, mtxFlipV);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float result[16];
- mtxMul(result, xform, mtxRot90);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
-
- sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
- float tx, ty, sx, sy;
- if (!mCurrentCrop.isEmpty()) {
- // In order to prevent bilinear sampling at the of the crop rectangle we
- // may need to shrink it by 2 texels in each direction. Normally this
- // would just need to take 1/2 a texel off each end, but because the
- // chroma channels will likely be subsampled we need to chop off a whole
- // texel. This will cause artifacts if someone does nearest sampling
- // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
- // accomodate the bilinear and nearest sampling uses.
- //
- // If nearest sampling turns out to be a desirable usage of these
- // textures then we could add the ability to switch a SurfaceTexture to
- // nearest-mode. Preferably, however, the image producers (video
- // decoder, camera, etc.) would simply not use a crop rectangle (or at
- // least not tell the framework about it) so that the GPU can do the
- // correct edge behavior.
- int xshrink = 0, yshrink = 0;
- if (mCurrentCrop.left > 0) {
- tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
- xshrink++;
- } else {
- tx = 0.0f;
- }
- if (mCurrentCrop.right < int32_t(buf->getWidth())) {
- xshrink++;
- }
- if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
- ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
- float(buf->getHeight());
- yshrink++;
- } else {
- ty = 0.0f;
- }
- if (mCurrentCrop.top > 0) {
- yshrink++;
- }
- sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
- sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
- } else {
- tx = 0.0f;
- ty = 0.0f;
- sx = 1.0f;
- sy = 1.0f;
- }
- float crop[16] = {
- sx, 0, 0, 0,
- 0, sy, 0, 0,
- 0, 0, 1, 0,
- tx, ty, 0, 1,
- };
-
- float mtxBeforeFlipV[16];
- mtxMul(mtxBeforeFlipV, crop, xform);
-
- // SurfaceFlinger expects the top of its window textures to be at a Y
- // coordinate of 0, so SurfaceTexture must behave the same way. We don't
- // want to expose this to applications, however, so we must add an
- // additional vertical flip to the transform after all the other transforms.
- mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
-}
-
-nsecs_t SurfaceTexture::getTimestamp() {
- ST_LOGV("getTimestamp");
- Mutex::Autolock lock(mMutex);
- return mCurrentTimestamp;
-}
-
-void SurfaceTexture::setFrameAvailableListener(
- const sp<FrameAvailableListener>& listener) {
- ST_LOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-void SurfaceTexture::freeBufferLocked(int i) {
- mSlots[i].mGraphicBuffer = 0;
- mSlots[i].mBufferState = BufferSlot::FREE;
- mSlots[i].mFrameNumber = 0;
- if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
- mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
- mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
- }
-}
-
-void SurfaceTexture::freeAllBuffersLocked() {
- LOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersLocked called but mQueue is not empty");
- mCurrentTexture = INVALID_BUFFER_SLOT;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
-}
-
-void SurfaceTexture::freeAllBuffersExceptHeadLocked() {
- LOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
- int head = -1;
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- head = *front;
- }
- mCurrentTexture = INVALID_BUFFER_SLOT;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (i != head) {
- freeBufferLocked(i);
- }
- }
-}
-
-status_t SurfaceTexture::drainQueueLocked() {
- while (mSynchronousMode && !mQueue.isEmpty()) {
- mDequeueCondition.wait(mMutex);
- if (mAbandoned) {
- ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (mConnectedApi == NO_CONNECTED_API) {
- ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!");
- return NO_INIT;
- }
- }
- return NO_ERROR;
-}
-
-status_t SurfaceTexture::drainQueueAndFreeBuffersLocked() {
- status_t err = drainQueueLocked();
- if (err == NO_ERROR) {
- if (mSynchronousMode) {
- freeAllBuffersLocked();
- } else {
- freeAllBuffersExceptHeadLocked();
- }
- }
- return err;
-}
-
-EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer) {
- EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
- EGLint attrs[] = {
- EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE,
- };
- EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
- if (image == EGL_NO_IMAGE_KHR) {
- EGLint error = eglGetError();
- ST_LOGE("error creating EGLImage: %#x", error);
- }
- return image;
-}
-
-sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTextureBuf;
-}
-
-Rect SurfaceTexture::getCurrentCrop() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentCrop;
-}
-
-uint32_t SurfaceTexture::getCurrentTransform() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTransform;
-}
-
-uint32_t SurfaceTexture::getCurrentScalingMode() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentScalingMode;
-}
-
-bool SurfaceTexture::isSynchronousMode() const {
- Mutex::Autolock lock(mMutex);
- return mSynchronousMode;
-}
-
-int SurfaceTexture::query(int what, int* outValue)
-{
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("query: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mPixelFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = mSynchronousMode ?
- (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
- break;
- default:
- return BAD_VALUE;
- }
- outValue[0] = value;
- return NO_ERROR;
-}
-
-void SurfaceTexture::abandon() {
- Mutex::Autolock lock(mMutex);
- mQueue.clear();
- mAbandoned = true;
- mCurrentTextureBuf.clear();
- freeAllBuffersLocked();
- mDequeueCondition.signal();
-}
-
-void SurfaceTexture::setName(const String8& name) {
- mName = name;
-}
-
-void SurfaceTexture::dump(String8& result) const
-{
- char buffer[1024];
- dump(result, "", buffer, 1024);
-}
-
-void SurfaceTexture::dump(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const
-{
- Mutex::Autolock _l(mMutex);
- snprintf(buffer, SIZE,
- "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
- "mPixelFormat=%d, mTexName=%d\n",
- prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
- mDefaultHeight, mPixelFormat, mTexName);
- result.append(buffer);
-
- String8 fifo;
- int fifoSize = 0;
- Fifo::const_iterator i(mQueue.begin());
- while (i != mQueue.end()) {
- snprintf(buffer, SIZE, "%02d ", *i++);
- fifoSize++;
- fifo.append(buffer);
- }
-
- snprintf(buffer, SIZE,
- "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
- "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
- ,
- prefix, mCurrentCrop.left,
- mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
- mCurrentTransform, mCurrentTexture,
- prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
- mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
- );
- result.append(buffer);
-
- struct {
- const char * operator()(int state) const {
- switch (state) {
- case BufferSlot::DEQUEUED: return "DEQUEUED";
- case BufferSlot::QUEUED: return "QUEUED";
- case BufferSlot::FREE: return "FREE";
- default: return "Unknown";
- }
- }
- } stateName;
-
- for (int i=0 ; i<mBufferCount ; i++) {
- const BufferSlot& slot(mSlots[i]);
- snprintf(buffer, SIZE,
- "%s%s[%02d] "
- "state=%-8s, crop=[%d,%d,%d,%d], "
- "transform=0x%02x, timestamp=%lld",
- prefix, (i==mCurrentTexture)?">":" ", i,
- stateName(slot.mBufferState),
- slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
- slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
- );
- result.append(buffer);
-
- const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
- if (buf != NULL) {
- snprintf(buffer, SIZE,
- ", %p [%4ux%4u:%4u,%3X]",
- buf->handle, buf->width, buf->height, buf->stride,
- buf->format);
- result.append(buffer);
- }
- result.append("\n");
- }
-}
-
-static void mtxMul(float out[16], const float a[16], const float b[16]) {
- out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
- out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
- out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
- out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
-
- out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
- out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
- out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
- out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
-
- out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
- out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
- out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
- out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
-
- out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
- out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
- out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
- out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
-}
-
-}; // namespace android
diff --git a/src/imports/nativemedia/SurfaceTexture_4_0.h b/src/imports/nativemedia/SurfaceTexture_4_0.h
deleted file mode 100644
index 53cc852..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_0.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_GUI_SURFACETEXTURE_H
-#define ANDROID_GUI_SURFACETEXTURE_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <gui/ISurfaceTexture.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class IGraphicBufferAlloc;
-class String8;
-
-class SurfaceTexture : public BnSurfaceTexture {
-public:
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
- enum {
- MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1,
- MIN_SYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS
- };
- enum { NUM_BUFFER_SLOTS = 32 };
- enum { NO_CONNECTED_API = 0 };
-
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called from queueBuffer() each time an
- // additional frame becomes available for consumption. This means that
- // frames that are queued while in asynchronous mode only trigger the
- // callback if no previous frames are pending. Frames queued while in
- // synchronous mode always trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
- // name of the OpenGL ES texture to which images are to be streamed. This
- // texture name cannot be changed once the SurfaceTexture is created.
- // allowSynchronousMode specifies whether or not synchronous mode can be
- // enabled. texTarget specifies the OpenGL ES texture target to which the
- // texture will be bound in updateTexImage. useFenceSync specifies whether
- // fences should be used to synchronize access to buffers if that behavior
- // is enabled at compile-time.
- SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
- GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true);
-
- virtual ~SurfaceTexture();
-
- // setBufferCount updates the number of available buffer slots. After
- // calling this all buffer slots are both unallocated and owned by the
- // SurfaceTexture object (i.e. they are not owned by the client).
- virtual status_t setBufferCount(int bufferCount);
-
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-
- // dequeueBuffer gets the next buffer slot index for the client to use. If a
- // buffer slot is available then that slot index is written to the location
- // pointed to by the buf argument and a status of OK is returned. If no
- // slot is available then a status of -EBUSY is returned and buf is
- // unmodified.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
-
- // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
- // timestamp must be provided for the buffer. The timestamp is in
- // nanoseconds, and must be monotonically increasing. Its other semantics
- // (zero point, etc) are client-dependent and should be documented by the
- // client.
- virtual status_t queueBuffer(int buf, int64_t timestamp,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
- virtual void cancelBuffer(int buf);
- virtual status_t setCrop(const Rect& reg);
- virtual status_t setTransform(uint32_t transform);
- virtual status_t setScalingMode(int mode);
-
- virtual int query(int what, int* value);
-
- // setSynchronousMode set whether dequeueBuffer is synchronous or
- // asynchronous. In synchronous mode, dequeueBuffer blocks until
- // a buffer is available, the currently bound buffer can be dequeued and
- // queued buffers will be retired in order.
- // The default mode is asynchronous.
- virtual status_t setSynchronousMode(bool enabled);
-
- // connect attempts to connect a client API to the SurfaceTexture. This
- // must be called before any other ISurfaceTexture methods are called except
- // for getAllocator.
- //
- // This method will fail if the connect was previously called on the
- // SurfaceTexture and no corresponding disconnect call was made.
- virtual status_t connect(int api,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
-
- // disconnect attempts to disconnect a client API from the SurfaceTexture.
- // Calling this method will cause any subsequent calls to other
- // ISurfaceTexture methods to fail except for getAllocator and connect.
- // Successfully calling connect after this will allow the other methods to
- // succeed again.
- //
- // This method will fail if the the SurfaceTexture is not currently
- // connected to the specified client API.
- virtual status_t disconnect(int api);
-
- // updateTexImage sets the image contents of the target texture to that of
- // the most recently queued buffer.
- //
- // This call may only be made while the OpenGL ES context to which the
- // target texture belongs is bound to the calling thread.
- status_t updateTexImage();
-
- // setBufferCountServer set the buffer count. If the client has requested
- // a buffer count using setBufferCount, the server-buffer count will
- // take effect once the client sets the count back to zero.
- status_t setBufferCountServer(int bufferCount);
-
- // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
- // associated with the texture image set by the most recent call to
- // updateTexImage.
- //
- // This transform matrix maps 2D homogeneous texture coordinates of the form
- // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
- // coordinate that should be used to sample that location from the texture.
- // Sampling the texture outside of the range of this transform is undefined.
- //
- // This transform is necessary to compensate for transforms that the stream
- // content producer may implicitly apply to the content. By forcing users of
- // a SurfaceTexture to apply this transform we avoid performing an extra
- // copy of the data that would be needed to hide the transform from the
- // user.
- //
- // The matrix is stored in column-major order so that it may be passed
- // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
- // functions.
- void getTransformMatrix(float mtx[16]);
-
- // getTimestamp retrieves the timestamp associated with the texture image
- // set by the most recent call to updateTexImage.
- //
- // The timestamp is in nanoseconds, and is monotonically increasing. Its
- // other semantics (zero point, etc) are source-dependent and should be
- // documented by the source.
- int64_t getTimestamp();
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
- void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
-
- // getAllocator retrieves the binder object that must be referenced as long
- // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
- // Holding this binder reference prevents SurfaceFlinger from freeing the
- // buffers before the client is done with them.
- sp<IBinder> getAllocator();
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- // A call to setDefaultBufferSize() may trigger requestBuffers() to
- // be called from the client.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- status_t setDefaultBufferSize(uint32_t width, uint32_t height);
-
- // getCurrentBuffer returns the buffer associated with the current image.
- sp<GraphicBuffer> getCurrentBuffer() const;
-
- // getCurrentTextureTarget returns the texture target of the current
- // texture as returned by updateTexImage().
- GLenum getCurrentTextureTarget() const;
-
- // getCurrentCrop returns the cropping rectangle of the current buffer
- Rect getCurrentCrop() const;
-
- // getCurrentTransform returns the transform of the current buffer
- uint32_t getCurrentTransform() const;
-
- // getCurrentScalingMode returns the scaling mode of the current buffer
- uint32_t getCurrentScalingMode() const;
-
- // isSynchronousMode returns whether the SurfaceTexture is currently in
- // synchronous mode.
- bool isSynchronousMode() const;
-
- // abandon frees all the buffers and puts the SurfaceTexture into the
- // 'abandoned' state. Once put in this state the SurfaceTexture can never
- // leave it. When in the 'abandoned' state, all methods of the
- // ISurfaceTexture interface will fail with the NO_INIT error.
- //
- // Note that while calling this method causes all the buffers to be freed
- // from the perspective of the the SurfaceTexture, if there are additional
- // references on the buffers (e.g. if a buffer is referenced by a client or
- // by OpenGL ES as a texture) then those buffer will remain allocated.
- void abandon();
-
- // set the name of the SurfaceTexture that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // dump our state in a String
- void dump(String8& result) const;
- void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
-protected:
-
- // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
- // for the given slot.
- void freeBufferLocked(int index);
-
- // freeAllBuffersLocked frees the resources (both GraphicBuffer and
- // EGLImage) for all slots.
- void freeAllBuffersLocked();
-
- // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer
- // and EGLImage) for all slots except the head of mQueue
- void freeAllBuffersExceptHeadLocked();
-
- // drainQueueLocked drains the buffer queue if we're in synchronous mode
- // returns immediately otherwise. return NO_INIT if SurfaceTexture
- // became abandoned or disconnected during this call.
- status_t drainQueueLocked();
-
- // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
- // synchronous mode and free all buffers. In asynchronous mode, all buffers
- // are freed except the current buffer.
- status_t drainQueueAndFreeBuffersLocked();
-
- static bool isExternalFormat(uint32_t format);
-
-private:
-
- // createImage creates a new EGLImage from a GraphicBuffer.
- EGLImageKHR createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer);
-
- status_t setBufferCountServerLocked(int bufferCount);
-
- // computeCurrentTransformMatrix computes the transform matrix for the
- // current texture. It uses mCurrentTransform and the current GraphicBuffer
- // to compute this matrix and stores it in mCurrentTransformMatrix.
- void computeCurrentTransformMatrix();
-
- enum { INVALID_BUFFER_SLOT = -1 };
-
- struct BufferSlot {
-
- BufferSlot()
- : mEglImage(EGL_NO_IMAGE_KHR),
- mEglDisplay(EGL_NO_DISPLAY),
- mBufferState(BufferSlot::FREE),
- mRequestBufferCalled(false),
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mFence(EGL_NO_SYNC_KHR) {
- mCrop.makeInvalid();
- }
-
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mEglImage is the EGLImage created from mGraphicBuffer.
- EGLImageKHR mEglImage;
-
- // mEglDisplay is the EGLDisplay used to create mEglImage.
- EGLDisplay mEglDisplay;
-
- // BufferState represents the different states in which a buffer slot
- // can be.
- enum BufferState {
- // FREE indicates that the buffer is not currently being used and
- // will not be used in the future until it gets dequeued and
- // subsequently queued by the client.
- FREE = 0,
-
- // DEQUEUED indicates that the buffer has been dequeued by the
- // client, but has not yet been queued or canceled. The buffer is
- // considered 'owned' by the client, and the server should not use
- // it for anything.
- //
- // Note that when in synchronous-mode (mSynchronousMode == true),
- // the buffer that's currently attached to the texture may be
- // dequeued by the client. That means that the current buffer can
- // be in either the DEQUEUED or QUEUED state. In asynchronous mode,
- // however, the current buffer is always in the QUEUED state.
- DEQUEUED = 1,
-
- // QUEUED indicates that the buffer has been queued by the client,
- // and has not since been made available for the client to dequeue.
- // Attaching the buffer to the texture does NOT transition the
- // buffer away from the QUEUED state. However, in Synchronous mode
- // the current buffer may be dequeued by the client under some
- // circumstances. See the note about the current buffer in the
- // documentation for DEQUEUED.
- QUEUED = 2,
- };
-
- // mBufferState is the current state of this buffer slot.
- BufferState mBufferState;
-
- // mRequestBufferCalled is used for validating that the client did
- // call requestBuffer() when told to do so. Technically this is not
- // needed but useful for debugging and catching client bugs.
- bool mRequestBufferCalled;
-
- // mCrop is the current crop rectangle for this buffer slot. This gets
- // set to mNextCrop each time queueBuffer gets called for this buffer.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot. This
- // gets set to mNextTransform each time queueBuffer gets called for this
- // slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot. This
- // gets set to mNextScalingMode each time queueBuffer gets called for
- // this slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mFence is the EGL sync object that must signal before the buffer
- // associated with this buffer slot may be dequeued. It is initialized
- // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
- // on a compile-time option) set to a new sync object in updateTexImage.
- EGLSyncKHR mFence;
- };
-
- // mSlots is the array of buffer slots that must be mirrored on the client
- // side. This allows buffer ownership to be transferred between the client
- // and server without sending a GraphicBuffer over binder. The entire array
- // is initialized to NULL at construction time, and buffers are allocated
- // for a slot when requestBuffer is called with that slot's index.
- BufferSlot mSlots[NUM_BUFFER_SLOTS];
-
- // mDefaultWidth holds the default width of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultWidth;
-
- // mDefaultHeight holds the default height of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultHeight;
-
- // mPixelFormat holds the pixel format of allocated buffers. It is used
- // in requestBuffers() if a format of zero is specified.
- uint32_t mPixelFormat;
-
- // mBufferCount is the number of buffer slots that the client and server
- // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
- // by calling setBufferCount or setBufferCountServer
- int mBufferCount;
-
- // mClientBufferCount is the number of buffer slots requested by the client.
- // The default is zero, which means the client doesn't care how many buffers
- // there is.
- int mClientBufferCount;
-
- // mServerBufferCount buffer count requested by the server-side
- int mServerBufferCount;
-
- // mCurrentTexture is the buffer slot index of the buffer that is currently
- // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
- // indicating that no buffer slot is currently bound to the texture. Note,
- // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
- // that no buffer is bound to the texture. A call to setBufferCount will
- // reset mCurrentTexture to INVALID_BUFFER_SLOT.
- int mCurrentTexture;
-
- // mCurrentTextureBuf is the graphic buffer of the current texture. It's
- // possible that this buffer is not associated with any buffer slot, so we
- // must track it separately in order to support the getCurrentBuffer method.
- sp<GraphicBuffer> mCurrentTextureBuf;
-
- // mCurrentCrop is the crop rectangle that applies to the current texture.
- // It gets set each time updateTexImage is called.
- Rect mCurrentCrop;
-
- // mCurrentTransform is the transform identifier for the current texture. It
- // gets set each time updateTexImage is called.
- uint32_t mCurrentTransform;
-
- // mCurrentScalingMode is the scaling mode for the current texture. It gets
- // set to each time updateTexImage is called.
- uint32_t mCurrentScalingMode;
-
- // mCurrentTransformMatrix is the transform matrix for the current texture.
- // It gets computed by computeTransformMatrix each time updateTexImage is
- // called.
- float mCurrentTransformMatrix[16];
-
- // mCurrentTimestamp is the timestamp for the current texture. It
- // gets set each time updateTexImage is called.
- int64_t mCurrentTimestamp;
-
- // mNextCrop is the crop rectangle that will be used for the next buffer
- // that gets queued. It is set by calling setCrop.
- Rect mNextCrop;
-
- // mNextTransform is the transform identifier that will be used for the next
- // buffer that gets queued. It is set by calling setTransform.
- uint32_t mNextTransform;
-
- // mNextScalingMode is the scaling mode that will be used for the next
- // buffers that get queued. It is set by calling setScalingMode.
- int mNextScalingMode;
-
- // mTexName is the name of the OpenGL texture to which streamed images will
- // be bound when updateTexImage is called. It is set at construction time
- // changed with a call to setTexName.
- const GLuint mTexName;
-
- // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
- // allocate new GraphicBuffer objects.
- //sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
- sp<FrameAvailableListener> mFrameAvailableListener;
-
- // mSynchronousMode whether we're in synchronous mode or not
- bool mSynchronousMode;
-
- // mAllowSynchronousMode whether we allow synchronous mode or not
- const bool mAllowSynchronousMode;
-
- // mConnectedApi indicates the API that is currently connected to this
- // SurfaceTexture. It defaults to NO_CONNECTED_API (= 0), and gets updated
- // by the connect and disconnect methods.
- int mConnectedApi;
-
- // mDequeueCondition condition used for dequeueBuffer in synchronous mode
- mutable Condition mDequeueCondition;
-
- // mQueue is a FIFO of queued buffers used in synchronous mode
- typedef Vector<int> Fifo;
- Fifo mQueue;
-
- // mAbandoned indicates that the SurfaceTexture will no longer be used to
- // consume images buffers pushed to it using the ISurfaceTexture interface.
- // It is initialized to false, and set to true in the abandon method. A
- // SurfaceTexture that has been abandoned will return the NO_INIT error from
- // all ISurfaceTexture methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the SurfaceTexture in log messages.
- // It is set by the setName method.
- String8 mName;
-
- // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
- // extension should be used to prevent buffers from being dequeued before
- // it's safe for them to be written. It gets set at construction time and
- // never changes.
- const bool mUseFenceSync;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of SurfaceTexture objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-
- // mTexTarget is the GL texture target with which the GL texture object is
- // associated. It is set in the constructor and never changed. It is
- // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
- // Browser. In that case it is set to GL_TEXTURE_2D to allow
- // glCopyTexSubImage to read from the texture. This is a hack to work
- // around a GL driver limitation on the number of FBO attachments, which the
- // browser's tile cache exceeds.
- const GLenum mTexTarget;
-
- // mFrameCounter is the free running counter, incremented for every buffer queued
- // with the surface Texture.
- uint64_t mFrameCounter;
-
-
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_SURFACETEXTURE_H
diff --git a/src/imports/nativemedia/SurfaceTexture_4_1.cpp b/src/imports/nativemedia/SurfaceTexture_4_1.cpp
deleted file mode 100644
index 9f8fd84..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_1.cpp
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * Copyright (C) 2010 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_TAG "SurfaceTexture"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <QtDebug>
-
-#include <hardware/hardware.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <SurfaceTexture.h>
-
-#include <private/gui/ComposerService.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-
-// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
-// to synchronize access to the buffers. It will cause dequeueBuffer to stall,
-// waiting for the GL reads for the buffer being dequeued to complete before
-// allowing the buffer to be dequeued.
-#ifdef USE_FENCE_SYNC
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
-#endif
-#endif
-
-// Macros for including the SurfaceTexture name in log messages
-#define ST_LOGV(x, ...) qDebug("[V/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) qDebug("[D/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) qDebug("[I/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) qDebug("[W/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) qDebug("[E/%s] "x, mName.string(), ##__VA_ARGS__)
-
-namespace android {
-
-// Transform matrices
-static float mtxIdentity[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
-};
-static float mtxFlipH[16] = {
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxFlipV[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-static float mtxRot90[16] = {
- 0, 1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxRot180[16] = {
- -1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 1, 1, 0, 1,
-};
-static float mtxRot270[16] = {
- 0, -1, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-
-static void mtxMul(float out[16], const float a[16], const float b[16]);
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
- GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
- mCurrentTransform(0),
- mCurrentTimestamp(0),
- mFilteringEnabled(true),
- mTexName(tex),
-#ifdef USE_FENCE_SYNC
- mUseFenceSync(useFenceSync),
-#else
- mUseFenceSync(false),
-#endif
- mTexTarget(texTarget),
- mEglDisplay(EGL_NO_DISPLAY),
- mEglContext(EGL_NO_CONTEXT),
- mAbandoned(false),
- mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
- mAttached(true)
-{
- // Choose a name using the PID and a process-unique ID.
- mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
- ST_LOGV("SurfaceTexture");
- if (bufferQueue == 0) {
- ST_LOGV("Creating a new BufferQueue");
- mBufferQueue = new BufferQueue(allowSynchronousMode);
- }
- else {
- mBufferQueue = bufferQueue;
- }
-
- memcpy(mCurrentTransformMatrix, mtxIdentity,
- sizeof(mCurrentTransformMatrix));
-
- // Note that we can't create an sp<...>(this) in a ctor that will not keep a
- // reference once the ctor ends, as that would cause the refcount of 'this'
- // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
- // that's what we create.
- wp<BufferQueue::ConsumerListener> listener;
- sp<BufferQueue::ConsumerListener> proxy;
- listener = static_cast<BufferQueue::ConsumerListener*>(this);
- proxy = new BufferQueue::ProxyConsumerListener(listener);
-
- status_t err = mBufferQueue->consumerConnect(proxy);
- if (err != NO_ERROR) {
- ST_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)",
- strerror(-err), err);
- } else {
- mBufferQueue->setConsumerName(mName);
- mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
- }
-}
-
-SurfaceTexture::~SurfaceTexture() {
- ST_LOGV("~SurfaceTexture");
-
- abandon();
-}
-
-status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setBufferCountServer(bufferCount);
-}
-
-
-status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return mBufferQueue->setDefaultBufferSize(w, h);
-}
-
-status_t SurfaceTexture::updateTexImage() {
- return SurfaceTexture::updateTexImage(NULL);
-}
-
-status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
- ATRACE_CALL();
- ST_LOGV("updateTexImage");
- Mutex::Autolock lock(mMutex);
-
- status_t err = NO_ERROR;
-
- if (mAbandoned) {
- ST_LOGE("updateTexImage: SurfaceTexture is abandoned!");
- return NO_INIT;
- }
-
- if (!mAttached) {
- ST_LOGE("updateTexImage: SurfaceTexture is not attached to an OpenGL "
- "ES context");
- return INVALID_OPERATION;
- }
-
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
- dpy == EGL_NO_DISPLAY) {
- ST_LOGE("updateTexImage: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
- ctx == EGL_NO_CONTEXT) {
- ST_LOGE("updateTexImage: invalid current EGLContext");
- return INVALID_OPERATION;
- }
-
- mEglDisplay = dpy;
- mEglContext = ctx;
-
- BufferQueue::BufferItem item;
-
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- err = mBufferQueue->acquireBuffer(&item);
- if (err == NO_ERROR) {
- int buf = item.mBuf;
- // This buffer was newly allocated, so we need to clean up on our side
- if (item.mGraphicBuffer != NULL) {
- mEGLSlots[buf].mGraphicBuffer = 0;
- if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(dpy, mEGLSlots[buf].mEglImage);
- mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
- }
- mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
- }
-
- // we call the rejecter here, in case the caller has a reason to
- // not accept this buffer. this is used by SurfaceFlinger to
- // reject buffers which have the wrong size
- if (rejecter && rejecter->reject(mEGLSlots[buf].mGraphicBuffer, item)) {
- mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
- mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR;
- glBindTexture(mTexTarget, mTexName);
- return NO_ERROR;
- }
-
- // Update the GL texture object. We may have to do this even when
- // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
- // detaching from a context but the buffer has not been re-allocated.
- EGLImageKHR image = mEGLSlots[buf].mEglImage;
- if (image == EGL_NO_IMAGE_KHR) {
- if (mEGLSlots[buf].mGraphicBuffer == NULL) {
- ST_LOGE("updateTexImage: buffer at slot %d is null", buf);
- err = BAD_VALUE;
- } else {
- image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer);
- mEGLSlots[buf].mEglImage = image;
- if (image == EGL_NO_IMAGE_KHR) {
- // NOTE: if dpy was invalid, createImage() is guaranteed to
- // fail. so we'd end up here.
- err = UNKNOWN_ERROR;
- }
- }
- }
-
- if (err == NO_ERROR) {
- GLint error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
- }
-
- glBindTexture(mTexTarget, mTexName);
- glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
-
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("updateTexImage: error binding external texture image %p "
- "(slot %d): %#04x", image, buf, error);
- err = UNKNOWN_ERROR;
- }
-
- if (err == NO_ERROR) {
- err = syncForReleaseLocked(dpy);
- }
- }
-
- if (err != NO_ERROR) {
- // Release the buffer we just acquired. It's not safe to
- // release the old buffer, so instead we just drop the new frame.
- mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
- mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR;
- return err;
- }
-
- ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
- mCurrentTexture,
- mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
- buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0);
-
- // release old buffer
- if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy,
- mEGLSlots[mCurrentTexture].mFence);
-
- mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR;
- if (status == BufferQueue::STALE_BUFFER_SLOT) {
- freeBufferLocked(mCurrentTexture);
- } else if (status != NO_ERROR) {
- ST_LOGE("updateTexImage: released invalid buffer");
- err = status;
- }
- }
-
- // Update the SurfaceTexture state.
- mCurrentTexture = buf;
- mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
- mCurrentCrop = item.mCrop;
- mCurrentTransform = item.mTransform;
- mCurrentScalingMode = item.mScalingMode;
- mCurrentTimestamp = item.mTimestamp;
- computeCurrentTransformMatrix();
- } else {
- if (err < 0) {
- ALOGE("updateTexImage failed on acquire %d", err);
- }
- // We always bind the texture even if we don't update its contents.
- glBindTexture(mTexTarget, mTexName);
- return OK;
- }
-
- return err;
-}
-
-status_t SurfaceTexture::detachFromContext() {
- ATRACE_CALL();
- ST_LOGV("detachFromContext");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("detachFromContext: abandoned SurfaceTexture");
- return NO_INIT;
- }
-
- if (!mAttached) {
- ST_LOGE("detachFromContext: SurfaceTexture is not attached to a "
- "context");
- return INVALID_OPERATION;
- }
-
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
- ST_LOGE("detachFromContext: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
- ST_LOGE("detachFromContext: invalid current EGLContext");
- return INVALID_OPERATION;
- }
-
- if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
- status_t err = syncForReleaseLocked(dpy);
- if (err != OK) {
- return err;
- }
-
- glDeleteTextures(1, &mTexName);
- }
-
- // Because we're giving up the EGLDisplay we need to free all the EGLImages
- // that are associated with it. They'll be recreated when the
- // SurfaceTexture gets attached to a new OpenGL ES context (and thus gets a
- // new EGLDisplay).
- for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- EGLImageKHR img = mEGLSlots[i].mEglImage;
- if (img != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mEglDisplay, img);
- mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
- }
- }
-
- mEglDisplay = EGL_NO_DISPLAY;
- mEglContext = EGL_NO_CONTEXT;
- mAttached = false;
-
- return OK;
-}
-
-status_t SurfaceTexture::attachToContext(GLuint tex) {
- ATRACE_CALL();
- ST_LOGV("attachToContext");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("attachToContext: abandoned SurfaceTexture");
- return NO_INIT;
- }
-
- if (mAttached) {
- ST_LOGE("attachToContext: SurfaceTexture is already attached to a "
- "context");
- return INVALID_OPERATION;
- }
-
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- if (dpy == EGL_NO_DISPLAY) {
- ST_LOGE("attachToContext: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if (ctx == EGL_NO_CONTEXT) {
- ST_LOGE("attachToContext: invalid current EGLContext");
- return INVALID_OPERATION;
- }
-
- // We need to bind the texture regardless of whether there's a current
- // buffer.
- glBindTexture(mTexTarget, tex);
-
- if (mCurrentTextureBuf != NULL) {
- // The EGLImageKHR that was associated with the slot was destroyed when
- // the SurfaceTexture was detached from the old context, so we need to
- // recreate it here.
- EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
- if (image == EGL_NO_IMAGE_KHR) {
- return UNKNOWN_ERROR;
- }
-
- // Attach the current buffer to the GL texture.
- glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
-
- GLint error;
- status_t err = OK;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("attachToContext: error binding external texture image %p "
- "(slot %d): %#04x", image, mCurrentTexture, error);
- err = UNKNOWN_ERROR;
- }
-
- // We destroy the EGLImageKHR here because the current buffer may no
- // longer be associated with one of the buffer slots, so we have
- // nowhere to to store it. If the buffer is still associated with a
- // slot then another EGLImageKHR will be created next time that buffer
- // gets acquired in updateTexImage.
- eglDestroyImageKHR(dpy, image);
-
- if (err != OK) {
- return err;
- }
- }
-
- mEglDisplay = dpy;
- mEglContext = ctx;
- mTexName = tex;
- mAttached = true;
-
- return OK;
-}
-
-status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {
- ST_LOGV("syncForReleaseLocked");
-
- if (mUseFenceSync && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- EGLSyncKHR fence = mEGLSlots[mCurrentTexture].mFence;
- if (fence != EGL_NO_SYNC_KHR) {
- // There is already a fence for the current slot. We need to wait
- // on that before replacing it with another fence to ensure that all
- // outstanding buffer accesses have completed before the producer
- // accesses it.
- EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
- if (result == EGL_FALSE) {
- ST_LOGE("syncForReleaseLocked: error waiting for previous "
- "fence: %#x", eglGetError());
- return UNKNOWN_ERROR;
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
- "fence");
- return TIMED_OUT;
- }
- eglDestroySyncKHR(dpy, fence);
- }
-
- // Create a fence for the outstanding accesses in the current OpenGL ES
- // context.
- fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
- if (fence == EGL_NO_SYNC_KHR) {
- ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
- eglGetError());
- return UNKNOWN_ERROR;
- }
- glFlush();
- mEGLSlots[mCurrentTexture].mFence = fence;
- }
-
- return OK;
-}
-
-bool SurfaceTexture::isExternalFormat(uint32_t format)
-{
- switch (format) {
- // supported YUV formats
- case HAL_PIXEL_FORMAT_YV12:
- // Legacy/deprecated YUV formats
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return true;
- }
-
- // Any OEM format needs to be considered
- if (format>=0x100 && format<=0x1FF)
- return true;
-
- return false;
-}
-
-GLenum SurfaceTexture::getCurrentTextureTarget() const {
- return mTexTarget;
-}
-
-void SurfaceTexture::getTransformMatrix(float mtx[16]) {
- Mutex::Autolock lock(mMutex);
- memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
-}
-
-void SurfaceTexture::setFilteringEnabled(bool enabled) {
- Mutex::Autolock lock(mMutex);
- bool needsRecompute = mFilteringEnabled != enabled;
- mFilteringEnabled = enabled;
- if (needsRecompute) {
- computeCurrentTransformMatrix();
- }
-}
-
-void SurfaceTexture::computeCurrentTransformMatrix() {
- ST_LOGV("computeCurrentTransformMatrix");
-
- float xform[16];
- for (int i = 0; i < 16; i++) {
- xform[i] = mtxIdentity[i];
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- float result[16];
- mtxMul(result, xform, mtxFlipH);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- float result[16];
- mtxMul(result, xform, mtxFlipV);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float result[16];
- mtxMul(result, xform, mtxRot90);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
-
- sp<GraphicBuffer>& buf(mCurrentTextureBuf);
- Rect cropRect = mCurrentCrop;
- float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
- float bufferWidth = buf->getWidth();
- float bufferHeight = buf->getHeight();
- if (!cropRect.isEmpty()) {
- float shrinkAmount = 0.0f;
- if (mFilteringEnabled) {
- // In order to prevent bilinear sampling beyond the edge of the
- // crop rectangle we may need to shrink it by 2 texels in each
- // dimension. Normally this would just need to take 1/2 a texel
- // off each end, but because the chroma channels of YUV420 images
- // are subsampled we may need to shrink the crop region by a whole
- // texel on each side.
- switch (buf->getPixelFormat()) {
- case PIXEL_FORMAT_RGBA_8888:
- case PIXEL_FORMAT_RGBX_8888:
- case PIXEL_FORMAT_RGB_888:
- case PIXEL_FORMAT_RGB_565:
- case PIXEL_FORMAT_BGRA_8888:
- case PIXEL_FORMAT_RGBA_5551:
- case PIXEL_FORMAT_RGBA_4444:
- // We know there's no subsampling of any channels, so we
- // only need to shrink by a half a pixel.
- shrinkAmount = 0.5;
-
- default:
- // If we don't recognize the format, we must assume the
- // worst case (that we care about), which is YUV420.
- shrinkAmount = 1.0;
- }
- }
-
- // Only shrink the dimensions that are not the size of the buffer.
- if (cropRect.width() < bufferWidth) {
- tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
- sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
- bufferWidth;
- }
- if (cropRect.height() < bufferHeight) {
- ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
- bufferHeight;
- sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
- bufferHeight;
- }
- }
- float crop[16] = {
- sx, 0, 0, 0,
- 0, sy, 0, 0,
- 0, 0, 1, 0,
- tx, ty, 0, 1,
- };
-
- float mtxBeforeFlipV[16];
- mtxMul(mtxBeforeFlipV, crop, xform);
-
- // SurfaceFlinger expects the top of its window textures to be at a Y
- // coordinate of 0, so SurfaceTexture must behave the same way. We don't
- // want to expose this to applications, however, so we must add an
- // additional vertical flip to the transform after all the other transforms.
- mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
-}
-
-nsecs_t SurfaceTexture::getTimestamp() {
- ST_LOGV("getTimestamp");
- Mutex::Autolock lock(mMutex);
- return mCurrentTimestamp;
-}
-
-void SurfaceTexture::setFrameAvailableListener(
- const sp<FrameAvailableListener>& listener) {
- ST_LOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer) {
- EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
- EGLint attrs[] = {
- EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE,
- };
- EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
- if (image == EGL_NO_IMAGE_KHR) {
- EGLint error = eglGetError();
- ST_LOGE("error creating EGLImage: %#x", error);
- }
- return image;
-}
-
-sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTextureBuf;
-}
-
-Rect SurfaceTexture::getCurrentCrop() const {
- Mutex::Autolock lock(mMutex);
-
- Rect outCrop = mCurrentCrop;
- if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
- int32_t newWidth = mCurrentCrop.width();
- int32_t newHeight = mCurrentCrop.height();
-
- if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
- newWidth = newHeight * mDefaultWidth / mDefaultHeight;
- ST_LOGV("too wide: newWidth = %d", newWidth);
- } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
- newHeight = newWidth * mDefaultHeight / mDefaultWidth;
- ST_LOGV("too tall: newHeight = %d", newHeight);
- }
-
- // The crop is too wide
- if (newWidth < mCurrentCrop.width()) {
- int32_t dw = (newWidth - mCurrentCrop.width())/2;
- outCrop.left -=dw;
- outCrop.right += dw;
- // The crop is too tall
- } else if (newHeight < mCurrentCrop.height()) {
- int32_t dh = (newHeight - mCurrentCrop.height())/2;
- outCrop.top -= dh;
- outCrop.bottom += dh;
- }
-
- ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
- outCrop.left, outCrop.top,
- outCrop.right,outCrop.bottom);
- }
-
- return outCrop;
-}
-
-uint32_t SurfaceTexture::getCurrentTransform() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTransform;
-}
-
-uint32_t SurfaceTexture::getCurrentScalingMode() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentScalingMode;
-}
-
-bool SurfaceTexture::isSynchronousMode() const {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->isSynchronousMode();
-}
-
-void SurfaceTexture::freeBufferLocked(int slotIndex) {
- ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- mEGLSlots[slotIndex].mGraphicBuffer = 0;
- if (slotIndex == mCurrentTexture) {
- mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
- }
- EGLImageKHR img = mEGLSlots[slotIndex].mEglImage;
- if (img != EGL_NO_IMAGE_KHR) {
- ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
- eglDestroyImageKHR(mEglDisplay, img);
- }
- mEGLSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
-}
-
-void SurfaceTexture::abandon() {
- ST_LOGV("abandon");
- Mutex::Autolock lock(mMutex);
-
- if (!mAbandoned) {
- mAbandoned = true;
- mCurrentTextureBuf.clear();
-
- // destroy all egl buffers
- for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
-
- // disconnect from the BufferQueue
- mBufferQueue->consumerDisconnect();
- mBufferQueue.clear();
- }
-}
-
-void SurfaceTexture::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- mName = name;
- mBufferQueue->setConsumerName(name);
-}
-
-status_t SurfaceTexture::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setDefaultBufferFormat(defaultFormat);
-}
-
-status_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
- Mutex::Autolock lock(mMutex);
- usage |= DEFAULT_USAGE_FLAGS;
- return mBufferQueue->setConsumerUsageBits(usage);
-}
-
-status_t SurfaceTexture::setTransformHint(uint32_t hint) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setTransformHint(hint);
-}
-
-// Used for refactoring BufferQueue from SurfaceTexture
-// Should not be in final interface once users of SurfaceTexture are clean up.
-status_t SurfaceTexture::setSynchronousMode(bool enabled) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setSynchronousMode(enabled);
-}
-
-// Used for refactoring, should not be in final interface
-sp<BufferQueue> SurfaceTexture::getBufferQueue() const {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue;
-}
-
-void SurfaceTexture::onFrameAvailable() {
- ST_LOGV("onFrameAvailable");
-
- sp<FrameAvailableListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- listener = mFrameAvailableListener;
- }
-
- if (listener != NULL) {
- ST_LOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
- }
-}
-
-void SurfaceTexture::onBuffersReleased() {
- ST_LOGV("onBuffersReleased");
-
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // Nothing to do if we're already abandoned.
- return;
- }
-
- uint32_t mask = 0;
- mBufferQueue->getReleasedBuffers(&mask);
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- if (mask & (1 << i)) {
- freeBufferLocked(i);
- }
- }
-}
-
-void SurfaceTexture::dump(String8& result) const
-{
- char buffer[1024];
- dump(result, "", buffer, 1024);
-}
-
-void SurfaceTexture::dump(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const
-{
- Mutex::Autolock _l(mMutex);
- snprintf(buffer, SIZE, "%smTexName=%d, mAbandoned=%d\n", prefix, mTexName,
- int(mAbandoned));
- result.append(buffer);
-
- snprintf(buffer, SIZE,
- "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n",
- prefix, mCurrentCrop.left,
- mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
- mCurrentTransform, mCurrentTexture
- );
- result.append(buffer);
-
- if (!mAbandoned) {
- mBufferQueue->dump(result, prefix, buffer, SIZE);
- }
-}
-
-static void mtxMul(float out[16], const float a[16], const float b[16]) {
- out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
- out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
- out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
- out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
-
- out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
- out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
- out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
- out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
-
- out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
- out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
- out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
- out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
-
- out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
- out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
- out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
- out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
-}
-
-}; // namespace android
diff --git a/src/imports/nativemedia/SurfaceTexture_4_1.h b/src/imports/nativemedia/SurfaceTexture_4_1.h
deleted file mode 100644
index 33aac7f..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_1.h
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_GUI_SURFACETEXTURE_H
-#define ANDROID_GUI_SURFACETEXTURE_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <gui/ISurfaceTexture.h>
-#include <BufferQueue.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-
-class String8;
-
-class SurfaceTexture : public virtual RefBase,
- protected BufferQueue::ConsumerListener {
-public:
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called each time an additional frame becomes
- // available for consumption. This means that frames that are queued
- // while in asynchronous mode only trigger the callback if no previous
- // frames are pending. Frames queued while in synchronous mode always
- // trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
- // name of the OpenGL ES texture to which images are to be streamed.
- // allowSynchronousMode specifies whether or not synchronous mode can be
- // enabled. texTarget specifies the OpenGL ES texture target to which the
- // texture will be bound in updateTexImage. useFenceSync specifies whether
- // fences should be used to synchronize access to buffers if that behavior
- // is enabled at compile-time. A custom bufferQueue can be specified
- // if behavior for queue/dequeue/connect etc needs to be customized.
- // Otherwise a default BufferQueue will be created and used.
- //
- // For legacy reasons, the SurfaceTexture is created in a state where it is
- // considered attached to an OpenGL ES context for the purposes of the
- // attachToContext and detachFromContext methods. However, despite being
- // considered "attached" to a context, the specific OpenGL ES context
- // doesn't get latched until the first call to updateTexImage. After that
- // point, all calls to updateTexImage must be made with the same OpenGL ES
- // context current.
- //
- // A SurfaceTexture may be detached from one OpenGL ES context and then
- // attached to a different context using the detachFromContext and
- // attachToContext methods, respectively. The intention of these methods is
- // purely to allow a SurfaceTexture to be transferred from one consumer
- // context to another. If such a transfer is not needed there is no
- // requirement that either of these methods be called.
- SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
- GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
- const sp<BufferQueue> &bufferQueue = 0);
-
- virtual ~SurfaceTexture();
-
- // updateTexImage sets the image contents of the target texture to that of
- // the most recently queued buffer.
- //
- // This call may only be made while the OpenGL ES context to which the
- // target texture belongs is bound to the calling thread.
- status_t updateTexImage();
-
- // setBufferCountServer set the buffer count. If the client has requested
- // a buffer count using setBufferCount, the server-buffer count will
- // take effect once the client sets the count back to zero.
- status_t setBufferCountServer(int bufferCount);
-
- // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
- // associated with the texture image set by the most recent call to
- // updateTexImage.
- //
- // This transform matrix maps 2D homogeneous texture coordinates of the form
- // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
- // coordinate that should be used to sample that location from the texture.
- // Sampling the texture outside of the range of this transform is undefined.
- //
- // This transform is necessary to compensate for transforms that the stream
- // content producer may implicitly apply to the content. By forcing users of
- // a SurfaceTexture to apply this transform we avoid performing an extra
- // copy of the data that would be needed to hide the transform from the
- // user.
- //
- // The matrix is stored in column-major order so that it may be passed
- // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
- // functions.
- void getTransformMatrix(float mtx[16]);
-
- // getTimestamp retrieves the timestamp associated with the texture image
- // set by the most recent call to updateTexImage.
- //
- // The timestamp is in nanoseconds, and is monotonically increasing. Its
- // other semantics (zero point, etc) are source-dependent and should be
- // documented by the source.
- int64_t getTimestamp();
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
- void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
-
- // getAllocator retrieves the binder object that must be referenced as long
- // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
- // Holding this binder reference prevents SurfaceFlinger from freeing the
- // buffers before the client is done with them.
- sp<IBinder> getAllocator();
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- // A call to setDefaultBufferSize() may trigger requestBuffers() to
- // be called from the client.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- status_t setDefaultBufferSize(uint32_t width, uint32_t height);
-
- // setFilteringEnabled sets whether the transform matrix should be computed
- // for use with bilinear filtering.
- void setFilteringEnabled(bool enabled);
-
- // getCurrentBuffer returns the buffer associated with the current image.
- sp<GraphicBuffer> getCurrentBuffer() const;
-
- // getCurrentTextureTarget returns the texture target of the current
- // texture as returned by updateTexImage().
- GLenum getCurrentTextureTarget() const;
-
- // getCurrentCrop returns the cropping rectangle of the current buffer.
- Rect getCurrentCrop() const;
-
- // getCurrentTransform returns the transform of the current buffer.
- uint32_t getCurrentTransform() const;
-
- // getCurrentScalingMode returns the scaling mode of the current buffer.
- uint32_t getCurrentScalingMode() const;
-
- // isSynchronousMode returns whether the SurfaceTexture is currently in
- // synchronous mode.
- bool isSynchronousMode() const;
-
- // abandon frees all the buffers and puts the SurfaceTexture into the
- // 'abandoned' state. Once put in this state the SurfaceTexture can never
- // leave it. When in the 'abandoned' state, all methods of the
- // ISurfaceTexture interface will fail with the NO_INIT error.
- //
- // Note that while calling this method causes all the buffers to be freed
- // from the perspective of the the SurfaceTexture, if there are additional
- // references on the buffers (e.g. if a buffer is referenced by a client or
- // by OpenGL ES as a texture) then those buffer will remain allocated.
- void abandon();
-
- // set the name of the SurfaceTexture that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // These functions call the corresponding BufferQueue implementation
- // so the refactoring can proceed smoothly
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
- status_t setConsumerUsageBits(uint32_t usage);
- status_t setTransformHint(uint32_t hint);
- virtual status_t setSynchronousMode(bool enabled);
-
- // getBufferQueue returns the BufferQueue object to which this
- // SurfaceTexture is connected.
- sp<BufferQueue> getBufferQueue() const;
-
- // detachFromContext detaches the SurfaceTexture from the calling thread's
- // current OpenGL ES context. This context must be the same as the context
- // that was current for previous calls to updateTexImage.
- //
- // Detaching a SurfaceTexture from an OpenGL ES context will result in the
- // deletion of the OpenGL ES texture object into which the images were being
- // streamed. After a SurfaceTexture has been detached from the OpenGL ES
- // context calls to updateTexImage will fail returning INVALID_OPERATION
- // until the SurfaceTexture is attached to a new OpenGL ES context using the
- // attachToContext method.
- status_t detachFromContext();
-
- // attachToContext attaches a SurfaceTexture that is currently in the
- // 'detached' state to the current OpenGL ES context. A SurfaceTexture is
- // in the 'detached' state iff detachFromContext has successfully been
- // called and no calls to attachToContext have succeeded since the last
- // detachFromContext call. Calls to attachToContext made on a
- // SurfaceTexture that is not in the 'detached' state will result in an
- // INVALID_OPERATION error.
- //
- // The tex argument specifies the OpenGL ES texture object name in the
- // new context into which the image contents will be streamed. A successful
- // call to attachToContext will result in this texture object being bound to
- // the texture target and populated with the image contents that were
- // current at the time of the last call to detachFromContext.
- status_t attachToContext(GLuint tex);
-
- // dump our state in a String
- virtual void dump(String8& result) const;
- virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
-protected:
-
- // Implementation of the BufferQueue::ConsumerListener interface. These
- // calls are used to notify the SurfaceTexture of asynchronous events in the
- // BufferQueue.
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- static bool isExternalFormat(uint32_t format);
-
-private:
- // this version of updateTexImage() takes a functor used to reject or not
- // the newly acquired buffer.
- // this API is TEMPORARY and intended to be used by SurfaceFlinger only,
- // which is why class Layer is made a friend of SurfaceTexture below.
- class BufferRejecter {
- friend class SurfaceTexture;
- virtual bool reject(const sp<GraphicBuffer>& buf,
- const BufferQueue::BufferItem& item) = 0;
- protected:
- virtual ~BufferRejecter() { }
- };
- friend class Layer;
- status_t updateTexImage(BufferRejecter* rejecter);
-
- // createImage creates a new EGLImage from a GraphicBuffer.
- EGLImageKHR createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer);
-
- // freeBufferLocked frees up the given buffer slot. If the slot has been
- // initialized this will release the reference to the GraphicBuffer in that
- // slot and destroy the EGLImage in that slot. Otherwise it has no effect.
- //
- // This method must be called with mMutex locked.
- void freeBufferLocked(int slotIndex);
-
- // computeCurrentTransformMatrix computes the transform matrix for the
- // current texture. It uses mCurrentTransform and the current GraphicBuffer
- // to compute this matrix and stores it in mCurrentTransformMatrix.
- void computeCurrentTransformMatrix();
-
- // syncForReleaseLocked performs the synchronization needed to release the
- // current slot from an OpenGL ES context. If needed it will set the
- // current slot's fence to guard against a producer accessing the buffer
- // before the outstanding accesses have completed.
- status_t syncForReleaseLocked(EGLDisplay dpy);
-
- // The default consumer usage flags that SurfaceTexture always sets on its
- // BufferQueue instance; these will be OR:d with any additional flags passed
- // from the SurfaceTexture user. In particular, SurfaceTexture will always
- // consume buffers as hardware textures.
- static const uint32_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
-
- // mCurrentTextureBuf is the graphic buffer of the current texture. It's
- // possible that this buffer is not associated with any buffer slot, so we
- // must track it separately in order to support the getCurrentBuffer method.
- sp<GraphicBuffer> mCurrentTextureBuf;
-
- // mCurrentCrop is the crop rectangle that applies to the current texture.
- // It gets set each time updateTexImage is called.
- Rect mCurrentCrop;
-
- // mCurrentTransform is the transform identifier for the current texture. It
- // gets set each time updateTexImage is called.
- uint32_t mCurrentTransform;
-
- // mCurrentScalingMode is the scaling mode for the current texture. It gets
- // set to each time updateTexImage is called.
- uint32_t mCurrentScalingMode;
-
- // mCurrentTransformMatrix is the transform matrix for the current texture.
- // It gets computed by computeTransformMatrix each time updateTexImage is
- // called.
- float mCurrentTransformMatrix[16];
-
- // mCurrentTimestamp is the timestamp for the current texture. It
- // gets set each time updateTexImage is called.
- int64_t mCurrentTimestamp;
-
- uint32_t mDefaultWidth, mDefaultHeight;
-
- // mFilteringEnabled indicates whether the transform matrix is computed for
- // use with bilinear filtering. It defaults to true and is changed by
- // setFilteringEnabled().
- bool mFilteringEnabled;
-
- // mTexName is the name of the OpenGL texture to which streamed images will
- // be bound when updateTexImage is called. It is set at construction time
- // and can be changed with a call to attachToContext.
- GLuint mTexName;
-
- // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
- // extension should be used to prevent buffers from being dequeued before
- // it's safe for them to be written. It gets set at construction time and
- // never changes.
- const bool mUseFenceSync;
-
- // mTexTarget is the GL texture target with which the GL texture object is
- // associated. It is set in the constructor and never changed. It is
- // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
- // Browser. In that case it is set to GL_TEXTURE_2D to allow
- // glCopyTexSubImage to read from the texture. This is a hack to work
- // around a GL driver limitation on the number of FBO attachments, which the
- // browser's tile cache exceeds.
- const GLenum mTexTarget;
-
- // EGLSlot contains the information and object references that
- // SurfaceTexture maintains about a BufferQueue buffer slot.
- struct EGLSlot {
- EGLSlot()
- : mEglImage(EGL_NO_IMAGE_KHR),
- mFence(EGL_NO_SYNC_KHR) {
- }
-
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mEglImage is the EGLImage created from mGraphicBuffer.
- EGLImageKHR mEglImage;
-
- // mFence is the EGL sync object that must signal before the buffer
- // associated with this buffer slot may be dequeued. It is initialized
- // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
- // on a compile-time option) set to a new sync object in updateTexImage.
- EGLSyncKHR mFence;
- };
-
- // mEglDisplay is the EGLDisplay with which this SurfaceTexture is currently
- // associated. It is intialized to EGL_NO_DISPLAY and gets set to the
- // current display when updateTexImage is called for the first time and when
- // attachToContext is called.
- EGLDisplay mEglDisplay;
-
- // mEglContext is the OpenGL ES context with which this SurfaceTexture is
- // currently associated. It is initialized to EGL_NO_CONTEXT and gets set
- // to the current GL context when updateTexImage is called for the first
- // time and when attachToContext is called.
- EGLContext mEglContext;
-
- // mEGLSlots stores the buffers that have been allocated by the BufferQueue
- // for each buffer slot. It is initialized to null pointers, and gets
- // filled in with the result of BufferQueue::acquire when the
- // client dequeues a buffer from a
- // slot that has not yet been used. The buffer allocated to a slot will also
- // be replaced if the requested buffer usage or geometry differs from that
- // of the buffer allocated to a slot.
- EGLSlot mEGLSlots[BufferQueue::NUM_BUFFER_SLOTS];
-
- // mAbandoned indicates that the BufferQueue will no longer be used to
- // consume images buffers pushed to it using the ISurfaceTexture interface.
- // It is initialized to false, and set to true in the abandon method. A
- // BufferQueue that has been abandoned will return the NO_INIT error from
- // all ISurfaceTexture methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the SurfaceTexture in log messages.
- // It can be set by the setName method.
- String8 mName;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
- sp<FrameAvailableListener> mFrameAvailableListener;
-
- // mCurrentTexture is the buffer slot index of the buffer that is currently
- // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
- // indicating that no buffer slot is currently bound to the texture. Note,
- // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
- // that no buffer is bound to the texture. A call to setBufferCount will
- // reset mCurrentTexture to INVALID_BUFFER_SLOT.
- int mCurrentTexture;
-
- // The SurfaceTexture has-a BufferQueue and is responsible for creating this object
- // if none is supplied
- sp<BufferQueue> mBufferQueue;
-
- // mAttached indicates whether the SurfaceTexture is currently attached to
- // an OpenGL ES context. For legacy reasons, this is initialized to true,
- // indicating that the SurfaceTexture is considered to be attached to
- // whatever context is current at the time of the first updateTexImage call.
- // It is set to false by detachFromContext, and then set to true again by
- // attachToContext.
- bool mAttached;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of SurfaceTexture objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_SURFACETEXTURE_H
diff --git a/src/imports/nativemedia/main.cpp b/src/imports/nativemedia/main.cpp
deleted file mode 100644
index b14b3d0..0000000
--- a/src/imports/nativemedia/main.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <QtGui>
-
-void initializeOMX();
-void render(QOpenGLContext *context, QWindow *surface);
-
-class Renderer : public QObject
-{
- Q_OBJECT
-public:
- Renderer(QWindow *surface)
- : surface(surface)
- {
- context = new QOpenGLContext;
-
- context->create();
- context->makeCurrent(surface);
-
- initializeOMX();
- qDebug() << "OMX initialized";
- }
-
-public slots:
- void render() {
- ::render(context, surface);
- }
-
-public:
- QWindow *surface;
- QOpenGLContext *context;
-} *renderer;
-
-void triggerRender()
-{
- QTimer::singleShot(0, renderer, SLOT(render()));
-}
-
-int main(int argc, char *argv[])
-{
- QGuiApplication app(argc, argv);
-
- QScreen *screen = QGuiApplication::primaryScreen();
-
- qDebug() << "Screen geometry:" << screen->geometry();
-
- QWindow window;
- window.setSurfaceType(QWindow::OpenGLSurface);
- window.setGeometry(screen->geometry());
- window.show();
-
- renderer = new Renderer(&window);
-
- return app.exec();
-}
-
-#include "main.moc"
diff --git a/src/imports/nativemedia/nativemedia.pro b/src/imports/nativemedia/nativemedia.pro
deleted file mode 100644
index 027608d..0000000
--- a/src/imports/nativemedia/nativemedia.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-######################################################################
-# Automatically generated by qmake (3.0) Thu Mar 7 13:00:32 2013
-######################################################################
-
-CXX_MODULE = qml
-TARGET = android_omx
-TARGETPATH = QtAndroidOmx
-IMPORT_VERSION = 1.0
-
-INCLUDEPATH += $$ANDROID_BUILD_TOP/development/ndk/platforms/android-14/include/
-
-LIBS += -lOpenMAXAL -lui -lgui -lutils -lcutils -lbinder
-
-QT += qml quick
-
-# Input
-HEADERS += omxnode.h omxplayer.h
-SOURCES += omx.cpp SurfaceTexture.cpp BufferQueue.cpp omxnode.cpp omxmodule.cpp
-
-load(qml_plugin)
-
diff --git a/src/imports/nativemedia/omx.cpp b/src/imports/nativemedia/omx.cpp
deleted file mode 100644
index b2ad4bc..0000000
--- a/src/imports/nativemedia/omx.cpp
+++ /dev/null
@@ -1,666 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <OMXAL/OpenMAXAL.h>
-#include <OMXAL/OpenMAXAL_Android.h>
-
-#include <SurfaceTexture.h>
-#include <gui/SurfaceTextureClient.h>
-
-#include "omxplayer.h"
-
-#include <QtGui>
-
-#include <cassert>
-
-// number of required interfaces for the MediaPlayer creation
-#define NB_MAXAL_INTERFACES 3 // XAAndroidBufferQueueItf, XAStreamInformationItf and XAPlayItf
-
-// number of buffers in our buffer queue, an arbitrary number
-#define NB_BUFFERS 8
-
-// we're streaming MPEG-2 transport stream data, operate on transport stream block size
-#define MPEG2_TS_PACKET_SIZE 188
-
-// number of MPEG-2 transport stream blocks per buffer, an arbitrary number
-#define PACKETS_PER_BUFFER 10
-
-// determines how much memory we're dedicating to memory caching
-#define BUFFER_SIZE (PACKETS_PER_BUFFER*MPEG2_TS_PACKET_SIZE)
-
-using namespace android;
-
-// constant to identify a buffer context which is the end of the stream to decode
-static const int kEosBufferCntxt = 1980; // a magic value we can compare against
-
-OmxPlayer::~OmxPlayer()
-{
-}
-
-struct OmxContext : public OmxPlayer {
- // engine interfaces
- XAObjectItf engineObject;
- XAEngineItf engineEngine;
-
- // output mix interfaces
- XAObjectItf outputMixObject;
-
- // streaming media player interfaces
- XAObjectItf playerObj;
- XAPlayItf playerPlayItf;
- XAAndroidBufferQueueItf playerBQItf;
- XAStreamInformationItf playerStreamInfoItf;
- XAVolumeItf playerVolItf;
-
- // where we cache in memory the data to play
- // note this memory is re-used by the buffer queue callback
- char dataCache[BUFFER_SIZE * NB_BUFFERS];
-
- // handle of the file to play
- FILE *file;
-
- // has the app reached the end of the file
- bool reachedEof;
-
- // For mutual exclusion between callback thread and application thread(s).
- // The mutex protects reachedEof, discontinuity,
- // The condition is signalled when a discontinuity is acknowledged.
-
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-
- sp<SurfaceTexture> surfaceTexture;
- sp<SurfaceTexture> surfaceTextureClient;
-
- int currentFrame;
- GLuint textureId;
-
- // for render, useful for debugging
- QOpenGLShaderProgram *program;
-
- int vertexLocation;
- int texCoordLocation;
- int textureLocation;
-
- OmxContext()
- : engineObject(0)
- , engineEngine(0)
- , outputMixObject(0)
- , playerObj(0)
- , playerPlayItf(0)
- , playerBQItf(0)
- , playerStreamInfoItf(0)
- , playerVolItf(0)
- , file(0)
- , reachedEof(false)
- , mutex(PTHREAD_MUTEX_INITIALIZER)
- , cond(PTHREAD_COND_INITIALIZER)
- , currentFrame(-1)
- , textureId(0)
- , program(0)
- , vertexLocation(0)
- , texCoordLocation(0)
- , textureLocation(0)
- {
- }
-
- ~OmxContext();
-
- void updateTexture()
- {
- if (surfaceTexture.get())
- surfaceTexture->updateTexImage();
- }
-
- bool hasFrame()
- {
- return currentFrame >= 0;
- }
-
- void setPaused(bool paused);
-
- bool initialize(const QByteArray &filename);
- bool enqueueInitialBuffers(bool discontinuity);
-
- XAresult AndroidBufferQueueCallback(
- XAAndroidBufferQueueItf caller,
- void *pCallbackContext,
- void *pBufferContext,
- void *pBufferData,
- XAuint32 dataSize,
- XAuint32 dataUsed,
- const XAAndroidBufferItem *pItems,
- XAuint32 itemsLength);
-
- void StreamChangeCallback(XAStreamInformationItf caller,
- XAuint32 eventId,
- XAuint32 streamIndex,
- void * pEventData,
- void * pContext );
-
- void render(QOpenGLContext *context, QWindow *surface);
-};
-
-static XAresult AndroidBufferQueueCallback(
- XAAndroidBufferQueueItf caller,
- void *pCallbackContext, /* input */
- void *pBufferContext, /* input */
- void *pBufferData, /* input */
- XAuint32 dataSize, /* input */
- XAuint32 dataUsed, /* input */
- const XAAndroidBufferItem *pItems,/* input */
- XAuint32 itemsLength /* input */)
-{
- return static_cast<OmxContext *>(pCallbackContext)->AndroidBufferQueueCallback(
- caller, pCallbackContext, pBufferContext, pBufferData, dataSize, dataUsed, pItems, itemsLength);
-}
-
-// AndroidBufferQueueItf callback to supply MPEG-2 TS packets to the media player
-XAresult OmxContext::AndroidBufferQueueCallback(
- XAAndroidBufferQueueItf caller,
- void *pCallbackContext, /* input */
- void *pBufferContext, /* input */
- void *pBufferData, /* input */
- XAuint32 dataSize, /* input */
- XAuint32 dataUsed, /* input */
- const XAAndroidBufferItem *pItems,/* input */
- XAuint32 itemsLength /* input */)
-{
- XAresult res;
- int ok;
-
- // note there is never any contention on this mutex unless a discontinuity request is active
- ok = pthread_mutex_lock(&mutex);
- assert(0 == ok);
-
-#if 0
- // was a discontinuity requested?
- if (discontinuity) {
- // Note: can't rewind after EOS, which we send when reaching EOF
- // (don't send EOS if you plan to play more content through the same player)
- if (!reachedEof) {
- // clear the buffer queue
- res = (*playerBQItf)->Clear(playerBQItf);
- assert(XA_RESULT_SUCCESS == res);
- // rewind the data source so we are guaranteed to be at an appropriate point
- rewind(file);
- // Enqueue the initial buffers, with a discontinuity indicator on first buffer
- (void) enqueueInitialBuffers(JNI_TRUE);
- }
- // acknowledge the discontinuity request
- discontinuity = JNI_FALSE;
- ok = pthread_cond_signal(&cond);
- assert(0 == ok);
- goto exit;
- }
-#endif
-
- if ((pBufferData == NULL) && (pBufferContext != NULL)) {
- const int processedCommand = *(int *)pBufferContext;
- if (kEosBufferCntxt == processedCommand) {
- qDebug("EOS was processed\n");
- // our buffer with the EOS message has been consumed
- assert(0 == dataSize);
- goto exit;
- }
- }
-
- // pBufferData is a pointer to a buffer that we previously Enqueued
- assert((dataSize > 0) && ((dataSize % MPEG2_TS_PACKET_SIZE) == 0));
- assert(dataCache <= (char *) pBufferData && (char *) pBufferData <
- &dataCache[BUFFER_SIZE * NB_BUFFERS]);
- assert(0 == (((char *) pBufferData - dataCache) % BUFFER_SIZE));
-
- // don't bother trying to read more data once we've hit EOF
- if (reachedEof) {
- goto exit;
- }
-
- size_t nbRead;
- // note we do call fread from multiple threads, but never concurrently
- size_t bytesRead;
- bytesRead = fread(pBufferData, 1, BUFFER_SIZE, file);
- if (bytesRead > 0) {
- if ((bytesRead % MPEG2_TS_PACKET_SIZE) != 0) {
- qDebug("Dropping last packet because it is not whole");
- }
- size_t packetsRead = bytesRead / MPEG2_TS_PACKET_SIZE;
- size_t bufferSize = packetsRead * MPEG2_TS_PACKET_SIZE;
- res = (*caller)->Enqueue(caller, NULL /*pBufferContext*/,
- pBufferData /*pData*/,
- bufferSize /*dataLength*/,
- NULL /*pMsg*/,
- 0 /*msgLength*/);
- assert(XA_RESULT_SUCCESS == res);
- } else {
- // EOF or I/O error, signal EOS
- XAAndroidBufferItem msgEos[1];
- msgEos[0].itemKey = XA_ANDROID_ITEMKEY_EOS;
- msgEos[0].itemSize = 0;
- // EOS message has no parameters, so the total size of the message is the size of the key
- // plus the size if itemSize, both XAuint32
- res = (*caller)->Enqueue(caller, (void *)&kEosBufferCntxt /*pBufferContext*/,
- NULL /*pData*/, 0 /*dataLength*/,
- msgEos /*pMsg*/,
- sizeof(XAuint32)*2 /*msgLength*/);
- assert(XA_RESULT_SUCCESS == res);
- reachedEof = true;
- }
-
-exit:
- ok = pthread_mutex_unlock(&mutex);
- assert(0 == ok);
- return XA_RESULT_SUCCESS;
-}
-
-// callback invoked whenever there is new or changed stream information
-static void StreamChangeCallback(XAStreamInformationItf caller,
- XAuint32 eventId,
- XAuint32 streamIndex,
- void * pEventData,
- void * pContext )
-{
- static_cast<OmxContext *>(pContext)->StreamChangeCallback(
- caller, eventId, streamIndex, pEventData, pContext);
-}
-
-// callback invoked whenever there is new or changed stream information
-void OmxContext::StreamChangeCallback(XAStreamInformationItf caller,
- XAuint32 eventId,
- XAuint32 streamIndex,
- void * pEventData,
- void * pContext )
-{
- qDebug("StreamChangeCallback called for stream %u", streamIndex);
-
- switch (eventId) {
- case XA_STREAMCBEVENT_PROPERTYCHANGE: {
- /** From spec 1.0.1:
- "This event indicates that stream property change has occurred.
- The streamIndex parameter identifies the stream with the property change.
- The pEventData parameter for this event is not used and shall be ignored."
- */
-
- XAresult res;
- XAuint32 domain;
- res = (*caller)->QueryStreamType(caller, streamIndex, &domain);
- assert(XA_RESULT_SUCCESS == res);
- switch (domain) {
- case XA_DOMAINTYPE_VIDEO: {
- XAVideoStreamInformation videoInfo;
- res = (*caller)->QueryStreamInformation(caller, streamIndex, &videoInfo);
- assert(XA_RESULT_SUCCESS == res);
- qDebug("Found video size %u x %u, codec ID=%u, frameRate=%u, bitRate=%u, duration=%u ms",
- videoInfo.width, videoInfo.height, videoInfo.codecId, videoInfo.frameRate,
- videoInfo.bitRate, videoInfo.duration);
- emit videoSize(videoInfo.width, videoInfo.height);
- } break;
- default:
- fprintf(stderr, "Unexpected domain %u\n", domain);
- break;
- }
- } break;
- default:
- fprintf(stderr, "Unexpected stream event ID %u\n", eventId);
- break;
- }
-}
-
-// Enqueue the initial buffers, and optionally signal a discontinuity in the first buffer
-bool OmxContext::enqueueInitialBuffers(bool discontinuity)
-{
-
- /* Fill our cache.
- * We want to read whole packets (integral multiples of MPEG2_TS_PACKET_SIZE).
- * fread returns units of "elements" not bytes, so we ask for 1-byte elements
- * and then check that the number of elements is a multiple of the packet size.
- */
- size_t bytesRead;
- bytesRead = fread(dataCache, 1, BUFFER_SIZE * NB_BUFFERS, file);
- if (bytesRead <= 0) {
- // could be premature EOF or I/O error
- return false;
- }
- if ((bytesRead % MPEG2_TS_PACKET_SIZE) != 0) {
- qDebug("Dropping last packet because it is not whole");
- }
- size_t packetsRead = bytesRead / MPEG2_TS_PACKET_SIZE;
- qDebug("Initially queueing %u packets", packetsRead);
-
- /* Enqueue the content of our cache before starting to play,
- we don't want to starve the player */
- size_t i;
- for (i = 0; i < NB_BUFFERS && packetsRead > 0; i++) {
- // compute size of this buffer
- size_t packetsThisBuffer = packetsRead;
- if (packetsThisBuffer > PACKETS_PER_BUFFER) {
- packetsThisBuffer = PACKETS_PER_BUFFER;
- }
- size_t bufferSize = packetsThisBuffer * MPEG2_TS_PACKET_SIZE;
- XAresult res;
- if (discontinuity) {
- // signal discontinuity
- XAAndroidBufferItem items[1];
- items[0].itemKey = XA_ANDROID_ITEMKEY_DISCONTINUITY;
- items[0].itemSize = 0;
- // DISCONTINUITY message has no parameters,
- // so the total size of the message is the size of the key
- // plus the size if itemSize, both XAuint32
- res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/,
- dataCache + i*BUFFER_SIZE, bufferSize, items /*pMsg*/,
- sizeof(XAuint32)*2 /*msgLength*/);
- //discontinuity = false;
- } else {
- res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/,
- dataCache + i*BUFFER_SIZE, bufferSize, NULL, 0);
- }
- assert(XA_RESULT_SUCCESS == res);
- packetsRead -= packetsThisBuffer;
- }
-
- return true;
-}
-
-class FrameCallback : public SurfaceTexture::FrameAvailableListener
-{
-public:
- FrameCallback(OmxContext *ctx)
- : context(ctx)
- {
- }
-
- void onFrameAvailable()
- {
- emit context->frameAvailable();
- ++context->currentFrame;
- }
-
-private:
- OmxContext *context;
-};
-
-OmxPlayer *OmxPlayer::create()
-{
- return new OmxContext;
-}
-
-bool OmxContext::initialize(const QByteArray &filename)
-{
- file = fopen(filename.data(), "rb");
- if (!file) {
- qWarning("Failed to open %s", filename.data());
- return false;
- }
-
- XAresult res;
-
- qDebug() << "Creating engine object";
-
- // create engine
- res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Creating engine object succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // realize the engine
- res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Realizing engine object succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the engine interface, which is needed in order to create other objects
- res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Getting engine interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // create output mix
- res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Creating output mix succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // realize the output mix
- res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Realizing output mix succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // configure data source
- XADataLocator_AndroidBufferQueue loc_abq = { XA_DATALOCATOR_ANDROIDBUFFERQUEUE, NB_BUFFERS };
- XADataFormat_MIME format_mime = {
- XA_DATAFORMAT_MIME, XA_ANDROID_MIME_MP2TS, XA_CONTAINERTYPE_MPEG_TS };
- XADataSource dataSrc = {&loc_abq, &format_mime};
-
- // configure audio sink
- XADataLocator_OutputMix loc_outmix = { XA_DATALOCATOR_OUTPUTMIX, outputMixObject };
- XADataSink audioSnk = { &loc_outmix, 0 };
-
- qDebug() << "Creating SurfaceTexture";
-
- glGenTextures(1, &textureId);
- surfaceTexture = new android::SurfaceTexture(textureId);
-
- qDebug() << "Creating SurfaceTextureClient";
-
- android::sp<android::SurfaceTextureClient> surfaceTextureClient = new android::SurfaceTextureClient(surfaceTexture);
-
- sp<SurfaceTexture::FrameAvailableListener> listener = new FrameCallback(this);
-
- surfaceTexture->setFrameAvailableListener(listener);
-
- // configure image video sink
- XADataLocator_NativeDisplay loc_nd = {
- XA_DATALOCATOR_NATIVEDISPLAY, // locatorType
- // the video sink must be an ANativeWindow created from a Surface or SurfaceTexture
- static_cast<ANativeWindow *>(surfaceTextureClient.get()), // hWindow
- // must be 0
- 0 // hDisplay
- };
- XADataSink imageVideoSink = {&loc_nd, 0};
-
- // declare interfaces to use
- XAboolean required[NB_MAXAL_INTERFACES]
- = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE};
- XAInterfaceID iidArray[NB_MAXAL_INTERFACES]
- = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUESOURCE,
- XA_IID_STREAMINFORMATION};
-
-
- qDebug() << "Creating media player for engine" << engineEngine;
-
- // create media player
- res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc,
- 0, &audioSnk, &imageVideoSink, 0, 0,
- NB_MAXAL_INTERFACES /*XAuint32 numInterfaces*/,
- iidArray /*const XAInterfaceID *pInterfaceIds*/,
- required /*const XAboolean *pInterfaceRequired*/);
-
- qDebug() << "CreateMediaPlayer succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // realize the player
- res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE);
-
- qDebug() << "Realize media player succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the play interface
- res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf);
-
- qDebug() << "Get play interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the stream information interface (for video size)
- res = (*playerObj)->GetInterface(playerObj, XA_IID_STREAMINFORMATION, &playerStreamInfoItf);
-
- qDebug() << "Get stream information interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the volume interface
- res = (*playerObj)->GetInterface(playerObj, XA_IID_VOLUME, &playerVolItf);
-
- qDebug() << "Get volume interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the Android buffer queue interface
- res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUESOURCE, &playerBQItf);
-
- qDebug() << "Get buffer queue interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // specify which events we want to be notified of
- res = (*playerBQItf)->SetCallbackEventsMask(playerBQItf, XA_ANDROIDBUFFERQUEUEEVENT_PROCESSED);
-
- qDebug() << "Setting callback events mask succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // register the callback from which OpenMAX AL can retrieve the data to play
- res = (*playerBQItf)->RegisterCallback(playerBQItf, ::AndroidBufferQueueCallback, this);
-
- qDebug() << "Registering buffer queue callback succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // we want to be notified of the video size once it's found, so we register a callback for that
- res = (*playerStreamInfoItf)->RegisterStreamChangeCallback(playerStreamInfoItf,
- ::StreamChangeCallback, this);
-
- qDebug() << "Registering stream change callback succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // enqueue the initial buffers
- if (!enqueueInitialBuffers(false))
- return false;
-
- qDebug() << "Enqueued initial buffers";
-
- // prepare the player
- res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED);
-
- qDebug() << "Preparing player (setting play state paused) succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // set the volume
- res = (*playerVolItf)->SetVolumeLevel(playerVolItf, 0);
-
- qDebug() << "Setting volume level succeeded?" << (res == XA_RESULT_SUCCESS);
-
- return true;
-}
-
-OmxContext::~OmxContext()
-{
- if (!file)
- return;
-
- // destroy streaming media player object, and invalidate all associated interfaces
- if (playerObj != NULL) {
- (*playerObj)->Destroy(playerObj);
- playerObj = NULL;
- playerPlayItf = NULL;
- playerBQItf = NULL;
- playerStreamInfoItf = NULL;
- playerVolItf = NULL;
- }
-
- // destroy output mix object, and invalidate all associated interfaces
- if (outputMixObject != NULL) {
- (*outputMixObject)->Destroy(outputMixObject);
- outputMixObject = NULL;
- }
-
- // destroy engine object, and invalidate all associated interfaces
- if (engineObject != NULL) {
- (*engineObject)->Destroy(engineObject);
- engineObject = NULL;
- engineEngine = NULL;
- }
-}
-
-void OmxContext::setPaused(bool paused)
-{
- XAresult res;
-
- // make sure the streaming media player was created
- if (NULL != playerPlayItf) {
- // set the player's state
- res = (*playerPlayItf)->SetPlayState(playerPlayItf, paused ?
- XA_PLAYSTATE_PAUSED : XA_PLAYSTATE_PLAYING);
- }
-}
-
-void OmxContext::render(QOpenGLContext *context, QWindow *surface)
-{
- context->makeCurrent(surface);
-
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT);
-
- if (currentFrame >= 0) {
- surfaceTexture->updateTexImage();
-
- if (!program) {
- qDebug() << "Received first video frame, starting to render";
-
- program = new QOpenGLShaderProgram;
-
- program->addShaderFromSourceCode(QOpenGLShader::Vertex,
- "attribute highp vec4 vertex;\n"
- "attribute highp vec2 texCoord;\n"
- "varying highp vec2 coord;\n"
- "void main(void)\n"
- "{\n"
- " coord = texCoord;\n"
- " gl_Position = vertex;\n"
- "}");
- program->addShaderFromSourceCode(QOpenGLShader::Fragment,
- "#extension GL_OES_EGL_image_external : require\n"
- "uniform samplerExternalOES tex;\n"
- "varying highp vec2 coord;\n"
- "void main(void)\n"
- "{\n"
- " gl_FragColor = texture2D(tex, coord);\n"
- "}");
-
- program->link();
-
- vertexLocation = program->attributeLocation("vertex");
- texCoordLocation = program->attributeLocation("texCoord");
- textureLocation = program->uniformLocation("tex");
-
- qDebug() << "attribute locations" << vertexLocation << texCoordLocation;
- qDebug() << "uniform location" << textureLocation;
- }
-
- program->bind();
-
- static GLfloat const triangleVertices[] = {
- -1, -3,
- 3, 1,
- -1, 1
- };
-
- static GLfloat const triangleTexCoords[] = {
- 0, 2,
- 2, 0,
- 0, 0
- };
-
- program->enableAttributeArray(vertexLocation);
- program->setAttributeArray(vertexLocation, triangleVertices, 2);
- program->enableAttributeArray(texCoordLocation);
- program->setAttributeArray(texCoordLocation, triangleTexCoords, 2);
-
- glDrawArrays(GL_TRIANGLES, 0, 3);
-
- program->disableAttributeArray(vertexLocation);
- program->disableAttributeArray(texCoordLocation);
- }
-
- context->swapBuffers(surface);
-}
diff --git a/src/imports/nativemedia/omxmodule.cpp b/src/imports/nativemedia/omxmodule.cpp
deleted file mode 100644
index 2daa154..0000000
--- a/src/imports/nativemedia/omxmodule.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "omxnode.h"
-#include <QtQml/QQmlExtensionPlugin>
-
-class QAndroidOmxModule : public QQmlExtensionPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
-
-public:
- virtual void registerTypes(const char *uri)
- {
- Q_ASSERT(QLatin1String(uri) == QLatin1String("QtAndroidOmx"));
-
- qmlRegisterType<OmxItem>(uri, 1, 0, "OmxItem");
- }
-};
-
-#include "omxmodule.moc"
-
diff --git a/src/imports/nativemedia/omxnode.cpp b/src/imports/nativemedia/omxnode.cpp
deleted file mode 100644
index 27ec1da..0000000
--- a/src/imports/nativemedia/omxnode.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "omxnode.h"
-
-#include <QtGui/QOpenGLContext>
-#include <QtQuick/qsgtexture.h>
-#include <QtQuick/qquickwindow.h>
-
-#include <QTimer>
-
-static const char omx_texture_material_vertex[] =
- "uniform highp mat4 qt_Matrix; \n"
- "attribute highp vec4 qt_VertexPosition; \n"
- "attribute highp vec2 qt_VertexTexCoord; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() { \n"
- " qt_TexCoord = qt_VertexTexCoord; \n"
- " gl_Position = qt_Matrix * qt_VertexPosition; \n"
- "}";
-
-
-static const char omx_texture_material_fragment[] =
- "#extension GL_OES_EGL_image_external : require \n"
- "varying highp vec2 qt_TexCoord; \n"
- "uniform samplerExternalOES qt_Texture; \n"
- "uniform lowp float qt_Opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(qt_Texture, qt_TexCoord) * qt_Opacity; \n"
- "}";
-
-QList<QByteArray> OmxTextureMaterial::attributes() const
-{
- QList<QByteArray> attributeList;
- attributeList << "qt_VertexPosition";
- attributeList << "qt_VertexTexCoord";
- return attributeList;
-}
-
-void OmxTextureMaterial::updateState(const OmxTextureState *newState, const OmxTextureState *oldState)
-{
- Q_UNUSED(oldState);
- newState->player->updateTexture();
-}
-
-const char *OmxTextureMaterial::vertexShader() const
-{
- return omx_texture_material_vertex;
-}
-
-const char *OmxTextureMaterial::fragmentShader() const
-{
- return omx_texture_material_fragment;
-}
-
-OmxNode::OmxNode(OmxPlayer *player)
- : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
- , m_player(player)
- , m_initialized(false)
-{
- m_textureMaterial = OmxTextureMaterial::createMaterial();
- m_textureMaterial->state()->player = player;
-
- setGeometry(&m_geometry);
- setMaterial(m_textureMaterial);
-
- setFlag(UsePreprocess, true);
-}
-
-OmxNode::~OmxNode()
-{
- delete m_textureMaterial;
-}
-
-void OmxNode::preprocess()
-{
-}
-
-void OmxNode::setRect(const QRectF &rect)
-{
- if (m_rect == rect)
- return;
-
- printf("OmxNode::setRect(%f %f %f %f)\n", rect.x(), rect.y(), rect.width(), rect.height());
- m_rect = rect;
-
- QRectF sourceRect(0, 0, 1, 1);
- QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, sourceRect);
-}
-
-OmxItem::OmxItem()
- : m_player(OmxPlayer::create())
- , m_hasFrame(false)
- , m_initialized(false)
- , m_paused(false)
- , m_sourceWidth(0)
- , m_sourceHeight(0)
-{
- connect(m_player, SIGNAL(frameAvailable()), this, SLOT(triggerRender()));
- connect(m_player, SIGNAL(videoSize(int, int)), this, SLOT(videoSize(int, int)));
-
- setFlag(ItemHasContents, true);
-}
-
-void OmxItem::itemChange(ItemChange change, const ItemChangeData &)
-{
- if (change == ItemSceneChange) {
- QQuickWindow *win = window();
- if (!win)
- return;
-
- // Connect the beforeRendering signal to our paint function.
- // Since this call is executed on the rendering thread it must be
- // a Qt::DirectConnection
- connect(win, SIGNAL(beforeRendering()), this, SLOT(beforeRendering()), Qt::DirectConnection);
- }
-}
-
-
-OmxItem::~OmxItem()
-{
- delete m_player;
-}
-
-void OmxItem::triggerRender()
-{
- m_hasFrame = true;
- update();
-}
-
-void OmxItem::videoSize(int w, int h)
-{
- m_sourceWidth = w;
- m_sourceHeight = h;
-
- emit sourceWidthChanged();
- emit sourceHeightChanged();
-}
-
-void OmxItem::setSource(const QString &source)
-{
- if (m_initialized || source == m_source)
- return;
-
- m_source = source;
- emit sourceChanged();
- update();
-}
-
-void OmxItem::beforeRendering()
-{
- if (m_initialized || m_source.isNull())
- return;
-
- m_initialized = m_player->initialize(m_source.toLocal8Bit());
-
- GLuint tid;
- glGenTextures(1, &tid);
-
- // start playing if not paused
- if (m_initialized && !paused())
- m_player->setPaused(false);
-}
-
-QSGNode *OmxItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- if (!m_hasFrame)
- return 0;
-
- OmxNode *node;
- if (oldNode)
- node = static_cast<OmxNode *>(oldNode);
- else
- node = new OmxNode(m_player);
-
- node->setRect(boundingRect());
- node->markDirty(QSGNode::DirtyMaterial);
-
- return node;
-}
-
-void OmxItem::setPaused(bool p)
-{
- if (p == m_paused)
- return;
- m_player->setPaused(p);
- m_paused = p;
- emit pausedChanged();
-}
diff --git a/src/imports/nativemedia/omxnode.h b/src/imports/nativemedia/omxnode.h
deleted file mode 100644
index e658378..0000000
--- a/src/imports/nativemedia/omxnode.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef OMXNODE_H
-#define OMXNODE_H
-
-#include <QtQuick/qquickitem.h>
-
-#include <QtQuick/qsgnode.h>
-#include <QtQuick/qsgsimplematerial.h>
-
-#include "SurfaceTexture.h"
-
-#include "omxplayer.h"
-
-class QSGTexture;
-
-struct OmxTextureState {
- OmxPlayer *player;
-};
-
-class OmxNode : public QSGGeometryNode
-{
-public:
- OmxNode(OmxPlayer *player);
- ~OmxNode();
-
- void preprocess();
-
- void setRect(const QRectF &rect);
- inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
-
- bool isTextureUpdated() const { return m_textureUpdated; }
- void setTextureUpdated(bool textureUpdated) { m_textureUpdated = textureUpdated; }
-
-private:
- bool m_textureUpdated;
-
- QSGGeometry m_geometry;
- QSGSimpleMaterial<OmxTextureState> *m_textureMaterial;
-
- QRectF m_rect;
- OmxPlayer *m_player;
- bool m_initialized;
-};
-
-class OmxTextureMaterial : public QSGSimpleMaterialShader<OmxTextureState>
-{
- QSG_DECLARE_SIMPLE_SHADER(OmxTextureMaterial, OmxTextureState)
-public:
- QList<QByteArray> attributes() const;
-
- void updateState(const OmxTextureState *newState, const OmxTextureState *oldState);
-
-protected:
- const char *vertexShader() const;
- const char *fragmentShader() const;
-};
-
-class OmxItem : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged FINAL)
- Q_PROPERTY(int sourceWidth READ sourceWidth NOTIFY sourceWidthChanged FINAL)
- Q_PROPERTY(int sourceHeight READ sourceHeight NOTIFY sourceHeightChanged FINAL)
- Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged FINAL)
-public:
- OmxItem();
- virtual ~OmxItem();
-
- QString source() {
- return m_source;
- }
-
- int sourceWidth() {
- return m_sourceWidth;
- }
-
- int sourceHeight() {
- return m_sourceHeight;
- }
-
- bool paused() { return m_paused; }
- void setPaused(bool p);
-
- void setSource(const QString &source);
-
-signals:
- void sourceChanged();
- void sourceWidthChanged();
- void sourceHeightChanged();
- void pausedChanged();
-
-protected:
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- void itemChange(ItemChange change, const ItemChangeData &);
-
-private slots:
- void triggerRender();
- void videoSize(int w, int h);
- void beforeRendering();
-
-private:
- OmxPlayer *m_player;
- bool m_hasFrame;
- bool m_initialized;
- bool m_paused;
- QString m_source;
- int m_sourceWidth;
- int m_sourceHeight;
-};
-
-#endif // OMXNODE_H
-
diff --git a/src/imports/nativemedia/omxplayer.h b/src/imports/nativemedia/omxplayer.h
deleted file mode 100644
index 05bb224..0000000
--- a/src/imports/nativemedia/omxplayer.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef OMXPLAYER_H
-#define OMXPLAYER_H
-
-#include <QObject>
-
-class OmxPlayer : public QObject
-{
- Q_OBJECT
-public:
- virtual ~OmxPlayer() = 0;
-
- virtual void updateTexture() = 0;
- virtual bool initialize(const QByteArray &filename) = 0;
- virtual bool hasFrame() = 0;
- virtual void setPaused(bool paused) = 0;
-
- static OmxPlayer *create();
-
-signals:
- void frameAvailable();
- void videoSize(int w, int h);
-};
-
-#endif
diff --git a/src/imports/nativemedia/qmldir b/src/imports/nativemedia/qmldir
deleted file mode 100644
index 6c14ce6..0000000
--- a/src/imports/nativemedia/qmldir
+++ /dev/null
@@ -1,2 +0,0 @@
-module QtAndroidOmx
-plugin android_omx
diff --git a/src/imports/nativemedia/test.qml b/src/imports/nativemedia/test.qml
deleted file mode 100644
index 01a1bfd..0000000
--- a/src/imports/nativemedia/test.qml
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-import QtQuick 2.0
-import QtAndroidOmx 1.0
-
-Rectangle {
- id: root
- color: "white"
-
- Column {
- width: parent.width
- anchors.verticalCenter: parent.verticalCenter
-
- OmxItem {
- id: omx
-
- width: root.width * 0.5
- height: width / aspect
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.margins: 40
- source: "NativeMedia.ts"
-
- property real aspect: sourceWidth / (sourceHeight > 0 ? sourceHeight : 1)
-
- MouseArea {
- anchors.fill: parent
- onClicked: parent.paused = !parent.paused
- }
- }
-
- Text {
- anchors.horizontalCenter: parent.horizontalCenter
- text: "Video size: " + omx.sourceWidth + "x" + omx.sourceHeight
- }
- }
-}
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
deleted file mode 100644
index cb74ee6..0000000
--- a/src/plugins/plugins.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS += sensors
-
diff --git a/src/plugins/sensors/eandroid/eandroid.pro b/src/plugins/sensors/eandroid/eandroid.pro
deleted file mode 100644
index 3b15f74..0000000
--- a/src/plugins/sensors/eandroid/eandroid.pro
+++ /dev/null
@@ -1,30 +0,0 @@
-TARGET = qtsensors_eandroid
-QT = core sensors
-
-PLUGIN_TYPE = sensors
-load(qt_plugin)
-
-LIBS += -lhardware
-
-HEADERS += \
- eandroidambientlightsensor.h \
- eandroidsensordevice.h \
- eandroidbasesensor.h \
- eandroidaccelerometer.h \
- eandroidlight.h \
- eandroidgyroscope.h \
- eandroidmagnetometer.h \
- eandroidrotationsensor.h
-
-SOURCES += \
- main.cpp \
- eandroidambientlightsensor.cpp \
- eandroidsensordevice.cpp \
- eandroidbasesensor.cpp \
- eandroidaccelerometer.cpp \
- eandroidlight.cpp \
- eandroidgyroscope.cpp \
- eandroidmagnetometer.cpp \
- eandroidrotationsensor.cpp
-
-OTHER_FILES = plugin.json
diff --git a/src/plugins/sensors/eandroid/eandroidaccelerometer.cpp b/src/plugins/sensors/eandroid/eandroidaccelerometer.cpp
deleted file mode 100644
index 0d4fa62..0000000
--- a/src/plugins/sensors/eandroid/eandroidaccelerometer.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidaccelerometer.h>
-
-EAndroidAccelerometer::EAndroidAccelerometer(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QAccelerometerReading>(&m_reading);
-}
-
-EAndroidAccelerometer::~EAndroidAccelerometer()
-{
-}
-
-void EAndroidAccelerometer::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- m_reading.setX(event.data[0]);
- m_reading.setY(event.data[1]);
- m_reading.setZ(event.data[2]);
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidaccelerometer.h b/src/plugins/sensors/eandroid/eandroidaccelerometer.h
deleted file mode 100644
index 0062c2c..0000000
--- a/src/plugins/sensors/eandroid/eandroidaccelerometer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDACCELEROMETER_H
-#define EANDROIDACCELEROMETER_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QAccelerometerReading>
-
-class EAndroidAccelerometer : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidAccelerometer(int type, QSensor *sensor);
- ~EAndroidAccelerometer();
- void processEvent(sensors_event_t &event);
-
-private:
- QAccelerometerReading m_reading;
-};
-
-#endif // EANDROIDACCELEROMETER_H
diff --git a/src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp b/src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp
deleted file mode 100644
index 10e4bc3..0000000
--- a/src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidambientlightsensor.h"
-
-EAndroidAmbientLightSensor::EAndroidAmbientLightSensor(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QAmbientLightReading>(&m_reading);
-}
-
-EAndroidAmbientLightSensor::~EAndroidAmbientLightSensor()
-{
-}
-
-void EAndroidAmbientLightSensor::processEvent(sensors_event_t &event)
-{
- const int lightLevelLux = event.light;
-
- if (lightLevelLux < 10)
- m_reading.setLightLevel(QAmbientLightReading::Dark);
- else if (lightLevelLux < 80)
- m_reading.setLightLevel(QAmbientLightReading::Twilight);
- else if (lightLevelLux < 400)
- m_reading.setLightLevel(QAmbientLightReading::Light);
- else if (lightLevelLux < 2500)
- m_reading.setLightLevel(QAmbientLightReading::Bright);
- else
- m_reading.setLightLevel(QAmbientLightReading::Sunny);
-
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidambientlightsensor.h b/src/plugins/sensors/eandroid/eandroidambientlightsensor.h
deleted file mode 100644
index dba24ea..0000000
--- a/src/plugins/sensors/eandroid/eandroidambientlightsensor.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDAMBIENTLIGHTSENSOR_H
-#define EANDROIDAMBIENTLIGHTSENSOR_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QAmbientLightReading>
-
-class EAndroidAmbientLightSensor : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidAmbientLightSensor(int type, QSensor *sensor);
- ~EAndroidAmbientLightSensor();
- void processEvent(sensors_event_t &event);
-
-private:
- QAmbientLightReading m_reading;
-};
-
-#endif // EANDROIDAMBIENTLIGHTSENSOR_H
diff --git a/src/plugins/sensors/eandroid/eandroidbasesensor.cpp b/src/plugins/sensors/eandroid/eandroidbasesensor.cpp
deleted file mode 100644
index 49ec5e4..0000000
--- a/src/plugins/sensors/eandroid/eandroidbasesensor.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidbasesensor.h>
-#include <eandroidsensordevice.h>
-
-EAndroidBaseSensor::EAndroidBaseSensor(int sensorType, QSensor *sensor)
- : QSensorBackend(sensor)
-{
- m_type = sensorType;
- m_isStarted = false;
- EAndroidSensorDevice *device = EAndroidSensorDevice::instance();
- setDescription(device->description(sensorType));
-#if 0 // #### TODO - QTBUG-33293
- qint32 maxRate = device->maxDataRate(sensorType); // convert to Hz
- addDataRate(1, 70);
- addOutputRange(1,55,6);
-#endif
-}
-
-EAndroidBaseSensor::~EAndroidBaseSensor()
-{
- if (m_isStarted)
- stop();
-}
-
-void EAndroidBaseSensor::start()
-{
- EAndroidSensorDevice::instance()->registerListener(m_type, this, sensor()->dataRate());
- m_isStarted = true;
-}
-
-void EAndroidBaseSensor::stop()
-{
- if (m_isStarted) {
- m_isStarted = false;
- EAndroidSensorDevice::instance()->unregisterListener(m_type, this);
- }
-}
-
-void EAndroidBaseSensor::processEvent(sensors_event_t &event)
-{
- Q_UNUSED(event)
-}
diff --git a/src/plugins/sensors/eandroid/eandroidbasesensor.h b/src/plugins/sensors/eandroid/eandroidbasesensor.h
deleted file mode 100644
index 16afebf..0000000
--- a/src/plugins/sensors/eandroid/eandroidbasesensor.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDBASESENSOR_H
-#define EANDROIDBASESENSOR_H
-
-#include <qsensorbackend.h>
-#include <hardware/sensors.h>
-
-class EAndroidBaseSensor : public QSensorBackend
-{
- Q_OBJECT
-public:
- EAndroidBaseSensor(int sensorType, QSensor *sensor);
- virtual ~EAndroidBaseSensor();
- virtual void start();
- virtual void stop();
- virtual void processEvent(sensors_event_t &event);
-
-private:
- int m_type;
- bool m_isStarted;
-};
-
-#endif // EANDROIDBASESENSOR_H
diff --git a/src/plugins/sensors/eandroid/eandroidgyroscope.cpp b/src/plugins/sensors/eandroid/eandroidgyroscope.cpp
deleted file mode 100644
index 783933f..0000000
--- a/src/plugins/sensors/eandroid/eandroidgyroscope.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidgyroscope.h"
-#include <math.h>
-
-EAndroidGyroscope::EAndroidGyroscope(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QGyroscopeReading>(&m_reading);
-}
-
-EAndroidGyroscope::~EAndroidGyroscope()
-{
-}
-
-void EAndroidGyroscope::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- m_reading.setX(event.gyro.x *180/M_PI);
- m_reading.setY(event.gyro.y *180/M_PI);
- m_reading.setZ(event.gyro.z *180/M_PI);
- newReadingAvailable();
-}
-
diff --git a/src/plugins/sensors/eandroid/eandroidgyroscope.h b/src/plugins/sensors/eandroid/eandroidgyroscope.h
deleted file mode 100644
index 96a8005..0000000
--- a/src/plugins/sensors/eandroid/eandroidgyroscope.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDGYROSCOPE_H
-#define EANDROIDGYROSCOPE_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QGyroscopeReading>
-
-class EAndroidGyroscope : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidGyroscope(int type, QSensor *sensor);
- ~EAndroidGyroscope();
- void processEvent(sensors_event_t &event);
-
-private:
- QGyroscopeReading m_reading;
-};
-
-#endif // EANDROIDGYROSCOPE_H
diff --git a/src/plugins/sensors/eandroid/eandroidlight.cpp b/src/plugins/sensors/eandroid/eandroidlight.cpp
deleted file mode 100644
index a7e9243..0000000
--- a/src/plugins/sensors/eandroid/eandroidlight.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidlight.h>
-
-EAndroidLight::EAndroidLight(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QLightReading>(&m_reading);
-}
-
-EAndroidLight::~EAndroidLight()
-{
-}
-
-void EAndroidLight::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- m_reading.setLux(event.light);
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidlight.h b/src/plugins/sensors/eandroid/eandroidlight.h
deleted file mode 100644
index 75ce1ac..0000000
--- a/src/plugins/sensors/eandroid/eandroidlight.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDLIGHT_H
-#define EANDROIDLIGHT_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QLightReading>
-
-class EAndroidLight : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidLight(int type, QSensor *sensor);
- ~EAndroidLight();
- void processEvent(sensors_event_t &ev);
-
-private:
- QLightReading m_reading;
-};
-
-#endif // EANDROIDLIGHT_H
diff --git a/src/plugins/sensors/eandroid/eandroidmagnetometer.cpp b/src/plugins/sensors/eandroid/eandroidmagnetometer.cpp
deleted file mode 100644
index 73597b2..0000000
--- a/src/plugins/sensors/eandroid/eandroidmagnetometer.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidmagnetometer.h"
-
-EAndroidMagnetometer::EAndroidMagnetometer(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QMagnetometerReading>(&m_reading);
-}
-
-EAndroidMagnetometer::~EAndroidMagnetometer()
-{
-}
-
-void EAndroidMagnetometer::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- // convect micro-Tesla to tesla
- m_reading.setX(event.magnetic.x / 1e6);
- m_reading.setY(event.magnetic.y / 1e6);
- m_reading.setZ(event.magnetic.z / 1e6);
-
- switch (event.magnetic.status) {
- case SENSOR_STATUS_UNRELIABLE:
- m_reading.setCalibrationLevel(0.0);
- break;
- case SENSOR_STATUS_ACCURACY_LOW:
- m_reading.setCalibrationLevel(0.3);
- break;
- case SENSOR_STATUS_ACCURACY_MEDIUM:
- m_reading.setCalibrationLevel(0.6);
- break;
- case SENSOR_STATUS_ACCURACY_HIGH:
- m_reading.setCalibrationLevel(1.0);
- break;
- default:
- break;
- }
-
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidmagnetometer.h b/src/plugins/sensors/eandroid/eandroidmagnetometer.h
deleted file mode 100644
index 92838b5..0000000
--- a/src/plugins/sensors/eandroid/eandroidmagnetometer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDMAGNETOMETER_H
-#define EANDROIDMAGNETOMETER_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QMagnetometerReading>
-
-class EAndroidMagnetometer : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidMagnetometer(int type, QSensor *sensor);
- ~EAndroidMagnetometer();
- void processEvent(sensors_event_t &event);
-
-private:
- QMagnetometerReading m_reading;
-};
-
-#endif // EANDROIDMAGNETOMETER_H
diff --git a/src/plugins/sensors/eandroid/eandroidrotationsensor.cpp b/src/plugins/sensors/eandroid/eandroidrotationsensor.cpp
deleted file mode 100644
index ee0ab7a..0000000
--- a/src/plugins/sensors/eandroid/eandroidrotationsensor.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidrotationsensor.h"
-#include <math.h>
-
-EAndroidRotationSensor::EAndroidRotationSensor(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QRotationReading>(&m_reading);
-}
-
-EAndroidRotationSensor::~EAndroidRotationSensor()
-{
-}
-
-void EAndroidRotationSensor::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
-
- float rz = -event.data[0] * 180 / M_PI;
- float rx = -event.data[1] * 180 / M_PI;
- float ry = event.data[2] * 180 / M_PI;
-
- m_reading.setFromEuler(rx, ry, rz);
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidrotationsensor.h b/src/plugins/sensors/eandroid/eandroidrotationsensor.h
deleted file mode 100644
index 79ac239..0000000
--- a/src/plugins/sensors/eandroid/eandroidrotationsensor.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDROTATIONSENSOR_H
-#define EANDROIDROTATIONSENSOR_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QRotationReading>
-
-class EAndroidRotationSensor : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidRotationSensor(int type, QSensor *sensor);
- ~EAndroidRotationSensor();
- void processEvent(sensors_event_t &event);
-
-private:
- QRotationReading m_reading;
-};
-
-#endif // EANDROIDROTATIONSENSOR_H
diff --git a/src/plugins/sensors/eandroid/eandroidsensordevice.cpp b/src/plugins/sensors/eandroid/eandroidsensordevice.cpp
deleted file mode 100644
index 9b9e03e..0000000
--- a/src/plugins/sensors/eandroid/eandroidsensordevice.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidsensordevice.h>
-
-EventReaderThread::EventReaderThread(EAndroidSensorDevice *device) :
- m_device(device)
-{
-}
-
-SensorEventArray* EventReaderThread::lock()
-{
- m_mutex.lock();
- return &m_events;
-}
-
-void EventReaderThread::run()
-{
- static const size_t numEvents = 16;
- sensors_event_t buffer[numEvents];
- int err = 0;
- int n;
- do {
- n = m_device->m_sensorDevice->poll(m_device->m_sensorDevice, buffer, numEvents);
- if (n < 0) {
- qWarning("poll() failed (%s)\n", strerror(-err));
- break;
- }
- m_mutex.lock();
- for (int i = 0 ; i < n ; i++) {
- sensors_event_t& event = buffer[i];
- if (event.version != sizeof(sensors_event_t)) {
- qWarning("incorrect event version (version=%d, expected=%d",
- event.version, sizeof(sensors_event_t));
- break;
- }
- m_events.append(event);
- }
- m_mutex.unlock();
- eventPending();
- } while (true);
-}
-
-EAndroidSensorDevice::EAndroidSensorDevice()
- : m_eventThread(0),
- m_sensorModule(0),
- m_sensorDevice(0),
- m_availableSensorsList(0),
- m_initSuccess(true)
-{
- m_initSuccess = initSensorDevice();
- if (m_initSuccess) {
- m_eventThread = new EventReaderThread(this);
- connect(m_eventThread, SIGNAL(eventPending()), this,
- SLOT(processSensorEvents()), Qt::QueuedConnection);
- } else {
- qWarning("Failed to initialize sensor module. Possibly a missing sensor driver?");
- }
-}
-
-EAndroidSensorDevice* EAndroidSensorDevice::m_instance = 0;
-EAndroidSensorDevice* EAndroidSensorDevice::instance()
-{
- if (!m_instance)
- m_instance = new EAndroidSensorDevice();
- return m_instance;
-}
-
-void EAndroidSensorDevice::registerListener(int type, EAndroidBaseSensor *sensor, int dataRateHz)
-{
- bool startReaderThread = m_listenersHash.isEmpty();
- bool enableSensor = m_listenersHash[type].isEmpty();
- m_listenersHash[type].push_back(sensor);
- if (startReaderThread)
- m_eventThread->start();
- if (enableSensor) {
- setActive(type, true);
- setDelay(type, dataRateHz);
- }
-}
-
-void EAndroidSensorDevice::unregisterListener(int type, EAndroidBaseSensor *sensor)
-{
- m_listenersHash[type].removeOne(sensor);
- bool disableSensor = m_listenersHash[type].isEmpty();
- if (disableSensor)
- m_listenersHash.remove(type);
- bool stopReaderThread = m_listenersHash.isEmpty();
- if (stopReaderThread)
- m_eventThread->quit();
- if (disableSensor)
- setActive(type, false);
-}
-
-int EAndroidSensorDevice::indexForType(int type) const
-{
- for (int i = 0; i < m_availableSensors; ++i)
- if (m_availableSensorsList[i].type == type)
- return i;
- qWarning() << "invalid sensor type: " << type;
- return -1;
-}
-
-void EAndroidSensorDevice::setActive(int type, bool enable)
-{
- for (int i = 0; i < m_availableSensors; i++) {
- if (m_availableSensorsList[i].type == type) {
- int err = m_sensorDevice->activate(m_sensorDevice,
- m_availableSensorsList[i].handle, enable);
- if (err != 0)
- qWarning("activate() for '%s'failed (%s)\n",
- m_availableSensorsList[i].name, strerror(-err));
- }
- }
-}
-
-void EAndroidSensorDevice::setDelay(int type, int dataRateHz) const
-{
- qint64 ns;
- // convert microseconds to nanoseconds
- qint32 maxRateNs = maxDataRate(type) * 1000;
- if (dataRateHz == 0) {
- // if dataRateHz is not set, then we use maxRateNs
- ns = maxRateNs;
- } else {
- // convert Hz to nanoseconds
- ns = 1000000000LL / dataRateHz;
- if (ns > maxRateNs)
- ns = maxRateNs;
- }
- int index = indexForType(type);
- if (index != -1)
- m_sensorDevice->setDelay(m_sensorDevice,
- m_availableSensorsList[index].handle, ns);
-
-}
-
-qint32 EAndroidSensorDevice::maxDataRate(int type) const
-{
- // minDelay - minimum delay allowed between events in microseconds
- int index = indexForType(type);
- if (index != -1)
- return m_availableSensorsList[index].minDelay;
- return 0;
-}
-
-QString EAndroidSensorDevice::description(int type) const
-{
- int index = indexForType(type);
- if (index != -1) {
- QString desc;
- desc.append(m_availableSensorsList[index].name);
- desc.append(QString(" (Vendor:%1) ").arg(m_availableSensorsList[index].vendor));
- return desc;
- }
- return QString();
-}
-
-int EAndroidSensorDevice::availableSensors(sensor_t const** list) const
-{
- if (m_initSuccess)
- return m_sensorModule->get_sensors_list(m_sensorModule, list);
- return 0;
-}
-
-bool EAndroidSensorDevice::initSensorDevice()
-{
- int err = 0;
- err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
- (hw_module_t const**)&m_sensorModule);
- if (err != 0 || !m_sensorModule) {
- qWarning("hw_get_module() failed (%s)\n", strerror(-err));
- return false;
- }
-
- err = sensors_open(&m_sensorModule->common, &m_sensorDevice);
- if (err != 0 || !m_sensorDevice) {
- qWarning("sensors_open() failed (%s)\n", strerror(-err));
- return false;
- }
-
- m_availableSensors = m_sensorModule->get_sensors_list(m_sensorModule,
- &m_availableSensorsList);
- return true;
-}
-
-void EAndroidSensorDevice::processSensorEvents() const
-{
- SensorEventArray *eventqueue = m_eventThread->lock();
- for (int i = 0; i < eventqueue->size(); i++) {
- sensors_event_t event = eventqueue->at(i);
- foreach (EAndroidBaseSensor *sensorListener, m_listenersHash[event.type])
- sensorListener->processEvent(event);
- }
- eventqueue->clear();
- m_eventThread->unlock();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidsensordevice.h b/src/plugins/sensors/eandroid/eandroidsensordevice.h
deleted file mode 100644
index db4e0f4..0000000
--- a/src/plugins/sensors/eandroid/eandroidsensordevice.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDSENSORDEVICE_H
-#define EANDROIDSENSORDEVICE_H
-
-#include <eandroidaccelerometer.h>
-#include <eandroidlight.h>
-#include <eandroidambientlightsensor.h>
-#include <eandroidgyroscope.h>
-#include <eandroidmagnetometer.h>
-#include <eandroidrotationsensor.h>
-
-#include <QtCore/QThread>
-#include <QtCore/QMutex>
-#include <QtCore/QReadWriteLock>
-#include <QtCore/QVarLengthArray>
-#include <QtCore/QHash>
-#include <QtCore/QList>
-#include <QtCore/QDebug>
-
-typedef QVarLengthArray<sensors_event_t, 16> SensorEventArray;
-typedef QHash<int, QList<EAndroidBaseSensor *> > ListenersHash;
-
-class EAndroidSensorDevice;
-
-class EventReaderThread : public QThread
-{
- Q_OBJECT
-public:
- EventReaderThread(EAndroidSensorDevice *manager);
- void run();
- SensorEventArray* lock();
- inline void unlock() { m_mutex.unlock(); }
-
-signals:
- void eventPending();
-
-private:
- EAndroidSensorDevice *m_device;
- SensorEventArray m_events;
- QMutex m_mutex;
-};
-
-class EAndroidSensorDevice : public QObject
-{
- Q_OBJECT
-public:
- static EAndroidSensorDevice* instance();
-
- void registerListener(int type, EAndroidBaseSensor *sensor, int dataRateHz);
- void unregisterListener(int type, EAndroidBaseSensor *sensor);
- int availableSensors(sensor_t const** list) const;
- qint32 maxDataRate(int type) const;
- QString description(int type) const;
-
-protected:
- bool initSensorDevice();
- int indexForType(int type) const;
- void setActive(int type, bool enable);
- void setDelay(int type, int dataRateHz) const;
-
-public slots:
- void processSensorEvents() const;
-
-private:
- static EAndroidSensorDevice* m_instance;
- EAndroidSensorDevice();
- EAndroidSensorDevice(const EAndroidSensorDevice &);
- EAndroidSensorDevice& operator=(const EAndroidSensorDevice &);
-
- friend class EventReaderThread;
- EventReaderThread *m_eventThread;
-
- sensors_module_t* m_sensorModule;
- sensors_poll_device_t* m_sensorDevice;
- sensor_t const* m_availableSensorsList;
- int m_availableSensors;
- bool m_initSuccess;
-
- ListenersHash m_listenersHash;
-};
-
-#endif // EANDROIDSENSORDEVICE_H
diff --git a/src/plugins/sensors/eandroid/main.cpp b/src/plugins/sensors/eandroid/main.cpp
deleted file mode 100644
index 8b62a18..0000000
--- a/src/plugins/sensors/eandroid/main.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtSensors module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://www.qt.io/licensing. For further information
-** use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include <qsensorplugin.h>
-#include <qsensorbackend.h>
-#include <qsensormanager.h>
-#include <qsensor.h>
-
-#include <eandroidsensordevice.h>
-
-class EAndroidSensorPlugin : public QObject, public QSensorPluginInterface, public QSensorBackendFactory
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "com.qt-project.Qt.QSensorPluginInterface/1.0" FILE "plugin.json")
- Q_INTERFACES(QSensorPluginInterface)
-public:
- void registerSensors()
- {
-#define REGISTER_BACKEND(type, id) \
- QSensorManager::registerBackend(type, id, this); \
-
- sensor_t const* sensors;
- QByteArray id;
- int count = EAndroidSensorDevice::instance()->availableSensors(&sensors);
- for (int i = 0; i < count; i++) {
- id = QByteArray::number(sensors[i].type);
- switch (sensors[i].type) {
- case SENSOR_TYPE_ACCELEROMETER:
- REGISTER_BACKEND(QAccelerometer::type, id)
- break;
- case SENSOR_TYPE_MAGNETIC_FIELD:
- REGISTER_BACKEND(QMagnetometer::type, id)
- break;
- case SENSOR_TYPE_ORIENTATION:
- break;
- case SENSOR_TYPE_GYROSCOPE:
- REGISTER_BACKEND(QGyroscope::type, id)
- break;
- case SENSOR_TYPE_LIGHT:
- REGISTER_BACKEND(QLightSensor::type, id);
- REGISTER_BACKEND(QAmbientLightSensor::type, id);
- break;
- case SENSOR_TYPE_PRESSURE:
- break;
- case SENSOR_TYPE_TEMPERATURE:
- break;
- case SENSOR_TYPE_PROXIMITY:
- break;
- case SENSOR_TYPE_GRAVITY:
- break;
- case SENSOR_TYPE_LINEAR_ACCELERATION:
- break;
- case SENSOR_TYPE_ROTATION_VECTOR:
- REGISTER_BACKEND(QRotationSensor::type, id);
- break;
- case SENSOR_TYPE_RELATIVE_HUMIDITY:
- break;
- case SENSOR_TYPE_AMBIENT_TEMPERATURE:
- break;
- }
- }
-#undef REGISTER_BACKEND
- }
-
- QSensorBackend *createBackend(QSensor *sensor)
- {
- int sensorType = sensor->identifier().toInt();
- switch (sensorType) {
- case SENSOR_TYPE_ACCELEROMETER:
- return new EAndroidAccelerometer(sensorType, sensor);
- case SENSOR_TYPE_MAGNETIC_FIELD:
- return new EAndroidMagnetometer(sensorType, sensor);
- case SENSOR_TYPE_ORIENTATION:
- break;
- case SENSOR_TYPE_GYROSCOPE:
- return new EAndroidGyroscope(sensorType, sensor);
- case SENSOR_TYPE_LIGHT:
- if (sensor->type() == QAmbientLightSensor::type)
- return new EAndroidAmbientLightSensor(sensorType, sensor);
- else if (sensor->type() == QLightSensor::type)
- return new EAndroidLight(sensorType, sensor);
- case SENSOR_TYPE_PRESSURE:
- break;
- case SENSOR_TYPE_TEMPERATURE:
- break;
- case SENSOR_TYPE_PROXIMITY:
- break;
- case SENSOR_TYPE_GRAVITY:
- break;
- case SENSOR_TYPE_LINEAR_ACCELERATION:
- break;
- case SENSOR_TYPE_ROTATION_VECTOR:
- return new EAndroidRotationSensor(sensorType, sensor);
- case SENSOR_TYPE_RELATIVE_HUMIDITY:
- break;
- case SENSOR_TYPE_AMBIENT_TEMPERATURE:
- break;
- default:
- break;
- }
- return 0;
- }
-};
-
-#include "main.moc"
diff --git a/src/plugins/sensors/eandroid/plugin.json b/src/plugins/sensors/eandroid/plugin.json
deleted file mode 100644
index 8a55b3a..0000000
--- a/src/plugins/sensors/eandroid/plugin.json
+++ /dev/null
@@ -1 +0,0 @@
-{ "Keys": [ "notused" ] }
diff --git a/src/plugins/sensors/sensors.pro b/src/plugins/sensors/sensors.pro
deleted file mode 100644
index d02cc99..0000000
--- a/src/plugins/sensors/sensors.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-android: SUBDIRS += eandroid
-
diff --git a/src/qconnectivity/main.cpp b/src/qconnectivity/main.cpp
deleted file mode 100644
index d25c42e..0000000
--- a/src/qconnectivity/main.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <QtCore>
-#include <QtNetwork/QLocalSocket>
-#include <QtNetwork/QLocalServer>
-
-#include <unistd.h>
-#include <cutils/properties.h>
-#include <cutils/sockets.h>
-#include <netutils/dhcp.h>
-#include <netutils/ifc.h>
-
-Q_LOGGING_CATEGORY(B2QT_QCONNECTIVITY, "qt.b2qt.qconnectivity")
-
-// Code values come from android/system/netd/ResponseCode.h
-const int InterfaceChange = 600;
-const char UNIQUE_HOSTNAME[] = "net.hostname";
-// sanity check a renewal time, lower value than
-// this might indicate a badly configured DHCP server
-const int MIN_RENEWAL_TIME_SECS = 300; // 5 min
-
-#define ETH_INTERFACE_HW "eth0"
-#define ETH_INTERFACE_EMULATOR "eth1"
-
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
-// this function is defined in android/system/core/libnetutils/dhcp_utils.c
-extern "C" {
-int dhcp_do_request_renew(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char *vendorInfo);
-}
-#endif
-
-static int q_dhcp_do_request(bool renew,
- const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char *vendorInfo,
- char *domain)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
- if (!renew)
- return dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns1, dns2, server, lease, vendorInfo);
- return dhcp_do_request_renew(ifname, ipaddr, gateway, prefixLength, dns1, dns2, server, lease, vendorInfo);
-#else
- char *dns[3] = {dns1, dns2, 0};
- char mtu[PROPERTY_VALUE_MAX];
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 4
- if (!renew)
- return dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo);
- return dhcp_do_request_renew(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo);
-#else
- if (!renew)
- return dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo, domain, mtu);
- return dhcp_do_request_renew(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo, domain, mtu);
-#endif
-#endif
-}
-
-
-class LeaseTimer;
-class QConnectivityDaemon : public QObject
-{
- Q_OBJECT
-public:
- QConnectivityDaemon();
-
-protected:
- void setHostnamePropery(const char *interface) const;
- void sendCommand(const char *command) const;
- void handleInterfaceChange(const QList<QByteArray> &message);
- bool startDhcp(bool renew, const char *interface);
- void stopDhcp(const char *interface);
- bool ethernetSupported() const;
- bool isEmulator() const;
-
-protected slots:
- void initNetdConnection();
- void handleNetdEvent();
- void handleRequest();
- void handleNewConnection();
- void sendReply(QLocalSocket *requester, const QByteArray &reply) const;
- void updateLease();
- void handleError(QLocalSocket::LocalSocketError /*socketError*/) const;
-
-private:
- friend class LeaseTimer;
- QLocalSocket *m_netdSocket;
- // currently used to listen for requests from Qt Wifi library,
- // in future can be used also for Bluetooth and etc.
- QLocalServer *m_serverSocket;
- bool m_linkUp;
- LeaseTimer *m_leaseTimer;
- bool m_isEmulator;
- QByteArray m_ethInterface;
- // android initializes services in a separate threads, therefore it is
- // not guaranteed that the netd socket will be ready at the time when qconnectivity
- // is starting up - we try to reconnect again after 2 second intervals. This
- // variable holds the maximum attempt count (chosen arbitrarily).
- int m_attemptCount;
-};
-
-class LeaseTimer : public QTimer
-{
- Q_OBJECT
-public:
- LeaseTimer(QConnectivityDaemon *daemon) : m_daemon(daemon) {}
-
- void setInterface(const QByteArray &interface)
- {
- if (m_ifc.isEmpty()) {
- m_ifc = interface;
- } else {
- // for example when user switches from eth0 to wlan0, we
- // stop DHCP on the previous interface
- if (m_ifc != interface) {
- m_daemon->stopDhcp(m_ifc.constData());
- m_ifc = interface;
- }
- }
- }
-
- QByteArray interface() const { return m_ifc; }
-
-private:
- QConnectivityDaemon *m_daemon;
- QByteArray m_ifc;
-};
-
-QConnectivityDaemon::QConnectivityDaemon()
- : m_netdSocket(0),
- m_serverSocket(0),
- m_linkUp(false),
- m_leaseTimer(0),
- m_isEmulator(isEmulator()),
- m_attemptCount(50)
-{
- QLoggingCategory::setFilterRules(QStringLiteral("qt.b2qt.qconnectivity=true"));
- qCDebug(B2QT_QCONNECTIVITY) << "starting QConnectivityDaemon...";
-
- if (!m_isEmulator) {
- m_ethInterface = ETH_INTERFACE_HW;
- m_leaseTimer = new LeaseTimer(this);
- m_leaseTimer->setSingleShot(true);
- connect(m_leaseTimer, SIGNAL(timeout()), this, SLOT(updateLease()));
-
- int serverFd = socket_local_server("qconnectivity", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
- if (serverFd != -1) {
- m_serverSocket = new QLocalServer(this);
- if (m_serverSocket->listen(serverFd))
- connect(m_serverSocket, SIGNAL(newConnection()), this, SLOT(handleNewConnection()));
- else
- qCWarning(B2QT_QCONNECTIVITY) << "not able to listen on the server socket...";
- } else {
- qCWarning(B2QT_QCONNECTIVITY) << "failed to open qconnectivity server socket";
- }
- } else {
- m_ethInterface = ETH_INTERFACE_EMULATOR;
- }
- initNetdConnection();
-}
-
-bool QConnectivityDaemon::isEmulator() const
-{
- bool isEmulator = false;
- QFile conf("/system/bin/appcontroller.conf");
- if (conf.open(QIODevice::ReadOnly)) {
- QByteArray content = conf.readAll();
- isEmulator = content.contains("platform=emulator");
- conf.close();
- } else {
- qCWarning(B2QT_QCONNECTIVITY) << "Failed to read appcontroller.conf";
- }
- return isEmulator;
-}
-
-void QConnectivityDaemon::initNetdConnection()
-{
- int netdFd = socket_local_client("netd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
- if (netdFd != -1) {
- qCDebug(B2QT_QCONNECTIVITY) << "connected to netd socket";
- m_netdSocket = new QLocalSocket(this);
- m_netdSocket->setSocketDescriptor(netdFd);
- connect(m_netdSocket, SIGNAL(readyRead()), this, SLOT(handleNetdEvent()));
- connect(m_netdSocket, SIGNAL(error(QLocalSocket::LocalSocketError)),
- this, SLOT(handleError(QLocalSocket::LocalSocketError)));
- } else {
- if (--m_attemptCount != 0)
- QTimer::singleShot(200, this, SLOT(initNetdConnection()));
- else
- qCWarning(B2QT_QCONNECTIVITY) << "failed to connect to netd socket!";
- return;
- }
- if (ethernetSupported()) {
- // down-up sequence generates "linkstate" events, which we can use to setup
- // our daemon on initial startup (device boot) or on daemon restarts
- sendCommand(QByteArray("0 interface setcfg ").append(m_ethInterface).append(" down").constData());
- sendCommand(QByteArray("0 interface setcfg ").append(m_ethInterface).append(" up").constData());
- }
- // disable firewall - this setting seems to be enabled only when using "Always-on VPN"
- // mode on Android phones, see setLockdownTracker() in ConnectivityService.java
- sendCommand("0 firewall disable");
-}
-
-void QConnectivityDaemon::setHostnamePropery(const char *interface) const
-{
- // Setup our unique device name (used as a host name argument for dhcpcd call in
- // dhcp_do_request). On Android device name is set in ConnectivityService.java and
- // the id is generated with the help of SecureRandom.java class. We will use Mac
- // address as a unique hostname.
- char prop_value[PROPERTY_VALUE_MAX];
- property_get(UNIQUE_HOSTNAME, prop_value, NULL);
- if ((prop_value[0] == '\0')) {
- char hwaddr[6];
- memset(hwaddr, 0, sizeof(hwaddr));
- ifc_init();
- if (ifc_get_hwaddr(interface, (void *)hwaddr) == 0) {
- QByteArray macAddress(hwaddr, sizeof(hwaddr));
- property_set(UNIQUE_HOSTNAME, macAddress.toHex().prepend("b2qt-").constData());
- } else {
- qCWarning(B2QT_QCONNECTIVITY) << "failed to get MAC address";
- }
- ifc_close();
- }
-}
-
-void QConnectivityDaemon::sendCommand(const char *command) const
-{
- if (!m_netdSocket) {
- qCDebug(B2QT_QCONNECTIVITY) << "netd socket is not ready!";
- return;
- }
- qCDebug(B2QT_QCONNECTIVITY) << "sending command - " << command;
- // netd expects "\0" terminated commands...
- m_netdSocket->write(command, qstrlen(command) + 1);
- m_netdSocket->flush();
-}
-
-void QConnectivityDaemon::handleInterfaceChange(const QList<QByteArray> &message)
-{
- // Format: "Code Iface linkstate <name> <up/down>"
- if (message.size() < 5)
- return;
-
- if (message.at(2) == "linkstate" && message.at(3) == m_ethInterface) {
- if (message.at(4) == "up") {
- // ethernet cable has been plugged in
- if (!m_linkUp) {
- m_linkUp = true;
- startDhcp(false, m_ethInterface);
- }
- } else {
- // .. plugged out
- if (m_linkUp) {
- m_linkUp = false;
- stopDhcp(m_ethInterface);
- }
- }
- }
-}
-
-bool QConnectivityDaemon::startDhcp(bool renew, const char *interface)
-{
- qCDebug(B2QT_QCONNECTIVITY) << "startDhcp [ renew" << renew << "] "
- << "interface: " << interface;
- setHostnamePropery(interface);
-
- int result = 0;
- char ipaddr[PROPERTY_VALUE_MAX];
- quint32 prefixLength = 0;
- char gateway[PROPERTY_VALUE_MAX];
- char dns1[PROPERTY_VALUE_MAX];
- char dns2[PROPERTY_VALUE_MAX];
- char server[PROPERTY_VALUE_MAX];
- quint32 lease = 0;
- char vendorInfo[PROPERTY_VALUE_MAX];
- char domain[PROPERTY_VALUE_MAX] = {0};
-
- if (renew) {
- result = q_dhcp_do_request(true, interface, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease, vendorInfo, domain);
- } else {
- // stop any existing DHCP daemon before starting new
- dhcp_stop(interface);
- // this uses "ctl.start.*" mechanism to start "dhcpcd" daemon as defined by
- // the device init.rc. Android starts dhcpcd with argument -B which means that
- // we are responsible for renewing a lease before it expires
- ifc_clear_addresses(interface);
- result = q_dhcp_do_request(false, interface, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease, vendorInfo, domain);
- }
-
- bool success = (result == 0) ? true : false;
- if (success) {
- qCDebug(B2QT_QCONNECTIVITY) << "\nipaddr: " << ipaddr << "\nprefixLength: " << prefixLength
- << "\ngateway: " << gateway << "\ndns1: " << dns1 << "\ndns2: " << dns2;
-
- if (!renew) {
- in_addr _ipaddr, _gateway, _dns1, _dns2;
- inet_aton(ipaddr, &_ipaddr);
- inet_aton(gateway, &_gateway);
- inet_aton(dns1, &_dns1);
- inet_aton(dns2, &_dns2);
-
- ifc_configure(interface, _ipaddr.s_addr, prefixLength,
- _gateway.s_addr, _dns1.s_addr, _dns2.s_addr);
-
- // set DNS servers and domain for interface - see NetworkManagementService.java
- QByteArray dnsForInterface("0 resolver setifdns ");
- dnsForInterface.append(interface).append(" ");
- if (domain[0])
- dnsForInterface.append(domain);
- else
- dnsForInterface.append(" ");
- dnsForInterface.append(" ");
- dnsForInterface.append(dns1).append(" ").append(dns2);
- sendCommand(dnsForInterface.constData());
-
- // set default interface for DNS - see NetworkManagementService.java
- sendCommand(QByteArray("0 resolver setdefaultif ").append(interface).constData());
-
- property_set("net.dns1", dns1);
- property_set("net.dns2", dns2);
- }
-
- if (!m_isEmulator && lease >= 0) {
- if (lease < MIN_RENEWAL_TIME_SECS) {
- qCWarning(B2QT_QCONNECTIVITY) << "DHCP server proposes lease time " << lease
- << "seconds. We will use" << MIN_RENEWAL_TIME_SECS << " seconds instead.";
- lease = MIN_RENEWAL_TIME_SECS;
- }
- // update lease when 48% of lease time has elapsed
- if (m_leaseTimer->isActive())
- m_leaseTimer->stop();
- m_leaseTimer->setInterface(interface);
- m_leaseTimer->start(lease * 480);
- }
- } else {
- qCWarning(B2QT_QCONNECTIVITY, "DHCP request failed - %s", dhcp_get_errmsg());
- if (renew) {
- // If it fails to renew a lease (faulty server, proxy?) we re-connect.
- // Some users might prefer to use expired lease over having interrupt
- // in network connection
- if (qEnvironmentVariableIsSet("QT_USE_EXPIRED_LEASE"))
- return true;
- qCDebug(B2QT_QCONNECTIVITY) << "attempting to re-connect...";
- stopDhcp(interface);
- startDhcp(false, interface);
- }
- }
- return success;
-}
-
-void QConnectivityDaemon::stopDhcp(const char *interface)
-{
- qCDebug(B2QT_QCONNECTIVITY) << "stopDhcp: " << interface;
- ifc_clear_addresses(interface);
- dhcp_stop(interface);
- if (!m_isEmulator && m_leaseTimer->isActive())
- m_leaseTimer->stop();
-}
-
-bool QConnectivityDaemon::ethernetSupported() const
-{
- // standard linux kernel path
- return QDir().exists(QString("/sys/class/net/").append(m_ethInterface));
-}
-
-void QConnectivityDaemon::handleNetdEvent()
-{
- QByteArray data = m_netdSocket->readAll();
- qCDebug(B2QT_QCONNECTIVITY) << "netd event: " << data;
- if (data.endsWith('\0'))
- data.chop(1);
-
- QList<QByteArray> message = data.split(' ');
- int code = message.at(0).toInt();
- switch (code) {
- case InterfaceChange:
- handleInterfaceChange(message);
- break;
- default:
- break;
- }
-}
-
-void QConnectivityDaemon::handleRequest()
-{
- // Format: "interface <connect/disconnect>"
- QLocalSocket *requester = qobject_cast<QLocalSocket *>(QObject::sender());
- if (requester->canReadLine()) {
- QByteArray request = requester->readLine(requester->bytesAvailable());
-
- qCDebug(B2QT_QCONNECTIVITY) << "received a request: " << request;
- QList<QByteArray> cmd = request.split(' ');
- if (cmd.size() < 2)
- return;
-
- QByteArray interface = cmd.at(0);
- if (cmd.at(1) == "connect") {
- QByteArray reply;
- if (startDhcp(false, interface.constData()))
- reply = "success";
- else
- reply = "failed";
- sendReply(requester, reply);
- } else {
- stopDhcp(interface.constData());
- }
- }
-}
-
-void QConnectivityDaemon::handleNewConnection()
-{
- QLocalSocket *requester = m_serverSocket->nextPendingConnection();
- connect(requester, SIGNAL(readyRead()), this, SLOT(handleRequest()));
- connect(requester, SIGNAL(disconnected()), requester, SLOT(deleteLater()));
-}
-
-void QConnectivityDaemon::sendReply(QLocalSocket *requester, const QByteArray &reply) const
-{
- QByteArray r = reply;
- r.append("\n");
- requester->write(r.constData(), r.length());
- requester->flush();
- requester->disconnectFromServer();
-}
-
-void QConnectivityDaemon::updateLease()
-{
- qCDebug(B2QT_QCONNECTIVITY) << "updating lease";
- startDhcp(true, m_leaseTimer->interface().constData());
-}
-
-void QConnectivityDaemon::handleError(QLocalSocket::LocalSocketError /*socketError*/) const
-{
- qCWarning(B2QT_QCONNECTIVITY) << "QLocalSocket::LocalSocketError";
-}
-
-int main(int argc, char *argv[])
-{
- QCoreApplication a(argc, argv);
-
- QConnectivityDaemon connectivityDaemon;
-
- return a.exec();
-}
-
-#include "main.moc"
diff --git a/src/qconnectivity/qconnectivity.pro b/src/qconnectivity/qconnectivity.pro
deleted file mode 100644
index df3b366..0000000
--- a/src/qconnectivity/qconnectivity.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-QT += core network
-QT -= gui
-
-TARGET = qconnectivity
-CONFIG += console
-CONFIG -= app_bundle
-
-TEMPLATE = app
-
-LIBS += -lcutils -lnetutils
-SOURCES += main.cpp
-
-load(qt_tool)
diff --git a/src/qt_hw_init/main.cpp b/src/qt_hw_init/main.cpp
deleted file mode 100644
index 15cc807..0000000
--- a/src/qt_hw_init/main.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "b2qtdevice.h"
-
-int main(int, char *[])
-{
- B2QtDevice device;
-
- device.initAudio();
-
- device.setDisplayBrightness(255);
-
- return 0;
-}
diff --git a/src/qt_hw_init/qt_hw_init.pro b/src/qt_hw_init/qt_hw_init.pro
deleted file mode 100644
index 4784926..0000000
--- a/src/qt_hw_init/qt_hw_init.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = app
-TARGET = qt_hw_init
-QT -= gui
-QT += b2qtutils
-
-SOURCES += main.cpp
-
-load(qt_tool)
diff --git a/src/src.pro b/src/src.pro
index a0e42dd..7ddc9ca 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -5,8 +5,4 @@ SUBDIRS += \
wifi \
imports \
doc \
- plugins \
b2qt-update-util
-
-
-android: SUBDIRS += doppelganger qt_hw_init qconnectivity