Merge "SoftVideoDecoderOMXComponent: max-size can be less than size"
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index de0167a..bc32bbe 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -78,7 +78,7 @@
static bool gWantFrameTime = false; // do we want times on each frame?
static uint32_t gVideoWidth = 0; // default width+height
static uint32_t gVideoHeight = 0;
-static uint32_t gBitRate = 4000000; // 4Mbps
+static uint32_t gBitRate = 20000000; // 20Mbps
static uint32_t gTimeLimitSec = kMaxTimeLimitSec;
// Set by signal handler to stop recording.
diff --git a/include/OWNERS b/include/OWNERS
index 3cb6d9c..d6bd998 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,5 +1,5 @@
elaurent@google.com
-gkasten@android.com
+gkasten@google.com
hunga@google.com
jtinker@google.com
lajos@google.com
diff --git a/include/common_time/OWNERS b/include/common_time/OWNERS
new file mode 100644
index 0000000..f9cb567
--- /dev/null
+++ b/include/common_time/OWNERS
@@ -0,0 +1 @@
+gkasten@google.com
diff --git a/include/private/media/OWNERS b/include/private/media/OWNERS
new file mode 100644
index 0000000..21723ba
--- /dev/null
+++ b/include/private/media/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+gkasten@google.com
+hunga@google.com
diff --git a/include/soundtrigger/OWNERS b/include/soundtrigger/OWNERS
new file mode 100644
index 0000000..e83f6b9
--- /dev/null
+++ b/include/soundtrigger/OWNERS
@@ -0,0 +1,2 @@
+elaurent@google.com
+thorntonc@google.com
diff --git a/media/audioserver/OWNERS b/media/audioserver/OWNERS
new file mode 100644
index 0000000..f9cb567
--- /dev/null
+++ b/media/audioserver/OWNERS
@@ -0,0 +1 @@
+gkasten@google.com
diff --git a/media/common_time/OWNERS b/media/common_time/OWNERS
new file mode 100644
index 0000000..f9cb567
--- /dev/null
+++ b/media/common_time/OWNERS
@@ -0,0 +1 @@
+gkasten@google.com
diff --git a/media/libaaudio/src/client/AudioEndpoint.cpp b/media/libaaudio/src/client/AudioEndpoint.cpp
index 6ae5379..3ee450a 100644
--- a/media/libaaudio/src/client/AudioEndpoint.cpp
+++ b/media/libaaudio/src/client/AudioEndpoint.cpp
@@ -32,14 +32,17 @@
#define RIDICULOUSLY_LARGE_FRAME_SIZE 4096
AudioEndpoint::AudioEndpoint()
- : mFreeRunning(false)
+ : mUpCommandQueue(nullptr)
+ , mDataQueue(nullptr)
+ , mFreeRunning(false)
, mDataReadCounter(0)
, mDataWriteCounter(0)
{
}
-AudioEndpoint::~AudioEndpoint()
-{
+AudioEndpoint::~AudioEndpoint() {
+ delete mDataQueue;
+ delete mUpCommandQueue;
}
static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 48d3a32..61fb6bab 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -40,7 +40,7 @@
namespace android {
EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
- : mEffect(effect), mEffectId(effectId), mBuffersChanged(true) {
+ : mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
}
EffectHalHidl::~EffectHalHidl() {
diff --git a/media/libaudioprocessing/OWNERS b/media/libaudioprocessing/OWNERS
new file mode 100644
index 0000000..96d0ea0
--- /dev/null
+++ b/media/libaudioprocessing/OWNERS
@@ -0,0 +1,3 @@
+gkasten@google.com
+hunga@google.com
+rago@google.com
diff --git a/media/libcpustats/OWNERS b/media/libcpustats/OWNERS
new file mode 100644
index 0000000..f9cb567
--- /dev/null
+++ b/media/libcpustats/OWNERS
@@ -0,0 +1 @@
+gkasten@google.com
diff --git a/media/libeffects/OWNERS b/media/libeffects/OWNERS
index 7e3de13..7f9ae81 100644
--- a/media/libeffects/OWNERS
+++ b/media/libeffects/OWNERS
@@ -1,3 +1,4 @@
+hunga@google.com
krocard@google.com
mnaganov@google.com
rago@google.com
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index 519f4a8..b4a1d77 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -563,6 +563,10 @@
return -EINVAL;
}
effect_param_t *cmd = (effect_param_t *) pCmdData;
+ if (cmd->psize != sizeof(int32_t)) {
+ android_errorWriteLog(0x534e4554, "63662938");
+ return -EINVAL;
+ }
*(int *)pReplyData = Downmix_setParameter(pDownmixer, *(int32_t *)cmd->data,
cmd->vsize, cmd->data + sizeof(int32_t));
break;
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index ab6b63c..1717b49 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -188,12 +188,13 @@
void Reverb_free (ReverbContext *pContext);
int Reverb_setConfig (ReverbContext *pContext, effect_config_t *pConfig);
void Reverb_getConfig (ReverbContext *pContext, effect_config_t *pConfig);
-int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue);
+int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue, int vsize);
int Reverb_getParameter (ReverbContext *pContext,
void *pParam,
uint32_t *pValueSize,
void *pValue);
int Reverb_LoadPreset (ReverbContext *pContext);
+int Reverb_paramValueSize (int32_t param);
/* Effect Library Interface Implementation */
@@ -1870,12 +1871,13 @@
// pContext - handle to instance data
// pParam - pointer to parameter
// pValue - pointer to value
+// vsize - value size
//
// Outputs:
//
//----------------------------------------------------------------------------
-int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){
+int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue, int vsize){
int status = 0;
int16_t level;
int16_t ratio;
@@ -1899,6 +1901,11 @@
return 0;
}
+ if (vsize < Reverb_paramValueSize(param)) {
+ android_errorWriteLog(0x534e4554, "63526567");
+ return -EINVAL;
+ }
+
switch (param){
case REVERB_PARAM_PROPERTIES:
ALOGV("\tReverb_setParameter() REVERB_PARAM_PROPERTIES");
@@ -1974,6 +1981,31 @@
return status;
} /* end Reverb_setParameter */
+
+/**
+ * returns the size in bytes of the value of each environmental reverb parameter
+ */
+int Reverb_paramValueSize(int32_t param) {
+ switch (param) {
+ case REVERB_PARAM_ROOM_LEVEL:
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ case REVERB_PARAM_REVERB_LEVEL:
+ return sizeof(int16_t); // millibel
+ case REVERB_PARAM_DECAY_TIME:
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ case REVERB_PARAM_REVERB_DELAY:
+ return sizeof(uint32_t); // milliseconds
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ case REVERB_PARAM_DIFFUSION:
+ case REVERB_PARAM_DENSITY:
+ return sizeof(int16_t); // permille
+ case REVERB_PARAM_PROPERTIES:
+ return sizeof(s_reverb_settings); // struct of all reverb properties
+ }
+ return sizeof(int32_t);
+}
+
} // namespace
} // namespace
@@ -2144,7 +2176,8 @@
*(int *)pReplyData = android::Reverb_setParameter(pContext,
(void *)p->data,
- p->data + p->psize);
+ p->data + p->psize,
+ p->vsize);
} break;
case EFFECT_CMD_ENABLE:
diff --git a/media/libheif/Android.bp b/media/libheif/Android.bp
new file mode 100644
index 0000000..7d5a4eb
--- /dev/null
+++ b/media/libheif/Android.bp
@@ -0,0 +1,23 @@
+cc_library_shared {
+ name: "libheif",
+
+ srcs: [
+ "HeifDecoderImpl.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libutils",
+ "libmedia",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ include_dirs: [],
+
+ export_include_dirs: ["include"],
+}
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
new file mode 100644
index 0000000..8b846be
--- /dev/null
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HeifDecoderImpl"
+
+#include "HeifDecoderImpl.h"
+
+#include <stdio.h>
+
+#include <binder/IMemory.h>
+#include <drm/drm_framework_common.h>
+#include <media/IDataSource.h>
+#include <media/mediametadataretriever.h>
+#include <media/stagefright/MediaSource.h>
+#include <private/media/VideoFrame.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+HeifDecoder* createHeifDecoder() {
+ return new android::HeifDecoderImpl();
+}
+
+namespace android {
+
+/*
+ * HeifDataSource
+ *
+ * Proxies data requests over IDataSource interface from MediaMetadataRetriever
+ * to the HeifStream interface we received from the heif decoder client.
+ */
+class HeifDataSource : public BnDataSource {
+public:
+ /*
+ * Constructs HeifDataSource; will take ownership of |stream|.
+ */
+ HeifDataSource(HeifStream* stream)
+ : mStream(stream), mReadPos(0), mEOS(false) {}
+
+ ~HeifDataSource() override {}
+
+ /*
+ * Initializes internal resources.
+ */
+ bool init();
+
+ sp<IMemory> getIMemory() override { return mMemory; }
+ ssize_t readAt(off64_t offset, size_t size) override;
+ status_t getSize(off64_t* size) override ;
+ void close() {}
+ uint32_t getFlags() override { return 0; }
+ String8 toString() override { return String8("HeifDataSource"); }
+ sp<DecryptHandle> DrmInitialization(const char*) override {
+ return nullptr;
+ }
+
+private:
+ /*
+ * Buffer size for passing the read data to mediaserver. Set to 64K
+ * (which is what MediaDataSource Java API's jni implementation uses).
+ */
+ enum {
+ kBufferSize = 64 * 1024,
+ };
+ sp<IMemory> mMemory;
+ std::unique_ptr<HeifStream> mStream;
+ off64_t mReadPos;
+ bool mEOS;
+};
+
+bool HeifDataSource::init() {
+ sp<MemoryDealer> memoryDealer =
+ new MemoryDealer(kBufferSize, "HeifDataSource");
+ mMemory = memoryDealer->allocate(kBufferSize);
+ if (mMemory == nullptr) {
+ ALOGE("Failed to allocate shared memory!");
+ return false;
+ }
+ return true;
+}
+
+ssize_t HeifDataSource::readAt(off64_t offset, size_t size) {
+ ALOGV("readAt: offset=%lld, size=%zu", (long long)offset, size);
+
+ if (size == 0) {
+ return mEOS ? ERROR_END_OF_STREAM : 0;
+ }
+
+ if (offset < mReadPos) {
+ // try seek, then rewind/skip, fail if none worked
+ if (mStream->seek(offset)) {
+ ALOGV("readAt: seek to offset=%lld", (long long)offset);
+ mReadPos = offset;
+ mEOS = false;
+ } else if (mStream->rewind()) {
+ ALOGV("readAt: rewind to offset=0");
+ mReadPos = 0;
+ mEOS = false;
+ } else {
+ ALOGE("readAt: couldn't seek or rewind!");
+ mEOS = true;
+ }
+ }
+
+ if (mEOS) {
+ ALOGV("readAt: EOS");
+ return ERROR_END_OF_STREAM;
+ }
+
+ if (offset > mReadPos) {
+ // skipping
+ size_t skipSize = offset - mReadPos;
+ size_t bytesSkipped = mStream->read(nullptr, skipSize);
+ if (bytesSkipped <= skipSize) {
+ mReadPos += bytesSkipped;
+ }
+ if (bytesSkipped != skipSize) {
+ mEOS = true;
+ return ERROR_END_OF_STREAM;
+ }
+ }
+
+ if (size > kBufferSize) {
+ size = kBufferSize;
+ }
+ size_t bytesRead = mStream->read(mMemory->pointer(), size);
+ if (bytesRead > size || bytesRead == 0) {
+ // bytesRead is invalid
+ mEOS = true;
+ return ERROR_END_OF_STREAM;
+ } if (bytesRead < size) {
+ // read some bytes but not all, set EOS and return ERROR_END_OF_STREAM next time
+ mEOS = true;
+ }
+ mReadPos += bytesRead;
+ return bytesRead;
+}
+
+status_t HeifDataSource::getSize(off64_t* size) {
+ if (!mStream->hasLength()) {
+ *size = -1;
+ ALOGE("getSize: not supported!");
+ return ERROR_UNSUPPORTED;
+ }
+ *size = mStream->getLength();
+ ALOGV("getSize: size=%lld", (long long)*size);
+ return OK;
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+HeifDecoderImpl::HeifDecoderImpl() :
+ // output color format should always be set via setOutputColor(), in case
+ // it's not, default to HAL_PIXEL_FORMAT_RGB_565.
+ mOutputColor(HAL_PIXEL_FORMAT_RGB_565),
+ mCurScanline(0) {
+}
+
+HeifDecoderImpl::~HeifDecoderImpl() {
+}
+
+bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {
+ sp<HeifDataSource> dataSource = new HeifDataSource(stream);
+ if (!dataSource->init()) {
+ return false;
+ }
+ mDataSource = dataSource;
+
+ mRetriever = new MediaMetadataRetriever();
+ status_t err = mRetriever->setDataSource(mDataSource, "video/mp4");
+ if (err != OK) {
+ ALOGE("failed to set data source!");
+
+ mRetriever.clear();
+ mDataSource.clear();
+ return false;
+ }
+ ALOGV("successfully set data source.");
+
+ const char* hasVideo = mRetriever->extractMetadata(METADATA_KEY_HAS_VIDEO);
+ if (!hasVideo || strcasecmp(hasVideo, "yes")) {
+ ALOGE("no video: %s", hasVideo ? hasVideo : "null");
+ return false;
+ }
+
+ mFrameMemory = mRetriever->getFrameAtTime(0,
+ IMediaSource::ReadOptions::SEEK_PREVIOUS_SYNC,
+ mOutputColor, true /*metaOnly*/);
+ if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+ ALOGE("getFrameAtTime: videoFrame is a nullptr");
+ return false;
+ }
+
+ VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+
+ ALOGV("Meta dimension %dx%d, display %dx%d, angle %d, iccSize %d",
+ videoFrame->mWidth,
+ videoFrame->mHeight,
+ videoFrame->mDisplayWidth,
+ videoFrame->mDisplayHeight,
+ videoFrame->mRotationAngle,
+ videoFrame->mIccSize);
+
+ if (frameInfo != nullptr) {
+ frameInfo->set(
+ videoFrame->mWidth,
+ videoFrame->mHeight,
+ videoFrame->mRotationAngle,
+ videoFrame->mBytesPerPixel,
+ videoFrame->mIccSize,
+ videoFrame->getFlattenedIccData());
+ }
+ return true;
+}
+
+bool HeifDecoderImpl::getEncodedColor(HeifEncodedColor* /*outColor*/) const {
+ ALOGW("getEncodedColor: not implemented!");
+ return false;
+}
+
+bool HeifDecoderImpl::setOutputColor(HeifColorFormat heifColor) {
+ switch(heifColor) {
+ case kHeifColorFormat_RGB565:
+ {
+ mOutputColor = HAL_PIXEL_FORMAT_RGB_565;
+ return true;
+ }
+ case kHeifColorFormat_RGBA_8888:
+ {
+ mOutputColor = HAL_PIXEL_FORMAT_RGBA_8888;
+ return true;
+ }
+ case kHeifColorFormat_BGRA_8888:
+ {
+ mOutputColor = HAL_PIXEL_FORMAT_BGRA_8888;
+ return true;
+ }
+ default:
+ break;
+ }
+ ALOGE("Unsupported output color format %d", heifColor);
+ return false;
+}
+
+bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
+ mFrameMemory = mRetriever->getFrameAtTime(0,
+ IMediaSource::ReadOptions::SEEK_PREVIOUS_SYNC, mOutputColor);
+ if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+ ALOGE("getFrameAtTime: videoFrame is a nullptr");
+ return false;
+ }
+
+ VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+ ALOGV("Decoded dimension %dx%d, display %dx%d, angle %d, rowbytes %d, size %d",
+ videoFrame->mWidth,
+ videoFrame->mHeight,
+ videoFrame->mDisplayWidth,
+ videoFrame->mDisplayHeight,
+ videoFrame->mRotationAngle,
+ videoFrame->mRowBytes,
+ videoFrame->mSize);
+
+ if (frameInfo != nullptr) {
+ frameInfo->set(
+ videoFrame->mWidth,
+ videoFrame->mHeight,
+ videoFrame->mRotationAngle,
+ videoFrame->mBytesPerPixel,
+ videoFrame->mIccSize,
+ videoFrame->getFlattenedIccData());
+ }
+ return true;
+}
+
+bool HeifDecoderImpl::getScanline(uint8_t* dst) {
+ if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+ return false;
+ }
+ VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+ if (mCurScanline >= videoFrame->mHeight) {
+ return false;
+ }
+ uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
+ memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mWidth);
+ return true;
+}
+
+size_t HeifDecoderImpl::skipScanlines(size_t count) {
+ if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+ return 0;
+ }
+ VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+
+ uint32_t oldScanline = mCurScanline;
+ mCurScanline += count;
+ if (mCurScanline >= videoFrame->mHeight) {
+ mCurScanline = videoFrame->mHeight;
+ }
+ return (mCurScanline > oldScanline) ? (mCurScanline - oldScanline) : 0;
+}
+
+} // namespace android
diff --git a/media/libheif/HeifDecoderImpl.h b/media/libheif/HeifDecoderImpl.h
new file mode 100644
index 0000000..2f8f0f8
--- /dev/null
+++ b/media/libheif/HeifDecoderImpl.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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 _HEIF_DECODER_IMPL_
+#define _HEIF_DECODER_IMPL_
+
+#include "include/HeifDecoderAPI.h"
+#include <system/graphics.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class IDataSource;
+class IMemory;
+class MediaMetadataRetriever;
+
+/*
+ * An implementation of HeifDecoder based on Android's MediaMetadataRetriever.
+ */
+class HeifDecoderImpl : public HeifDecoder {
+public:
+
+ HeifDecoderImpl();
+ ~HeifDecoderImpl() override;
+
+ bool init(HeifStream* stream, HeifFrameInfo* frameInfo) override;
+
+ bool getEncodedColor(HeifEncodedColor* outColor) const override;
+
+ bool setOutputColor(HeifColorFormat heifColor) override;
+
+ bool decode(HeifFrameInfo* frameInfo) override;
+
+ bool getScanline(uint8_t* dst) override;
+
+ size_t skipScanlines(size_t count) override;
+
+private:
+ sp<IDataSource> mDataSource;
+ sp<MediaMetadataRetriever> mRetriever;
+ sp<IMemory> mFrameMemory;
+ android_pixel_format_t mOutputColor;
+ size_t mCurScanline;
+};
+
+} // namespace android
+
+#endif // _HEIF_DECODER_IMPL_
diff --git a/media/libheif/include/HeifDecoderAPI.h b/media/libheif/include/HeifDecoderAPI.h
new file mode 100644
index 0000000..5183c39
--- /dev/null
+++ b/media/libheif/include/HeifDecoderAPI.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2017 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 _HEIF_DECODER_API_
+#define _HEIF_DECODER_API_
+
+#include <memory>
+
+/*
+ * The output color pixel format of heif decoder.
+ */
+typedef enum {
+ kHeifColorFormat_RGB565 = 0,
+ kHeifColorFormat_RGBA_8888 = 1,
+ kHeifColorFormat_BGRA_8888 = 2,
+} HeifColorFormat;
+
+/*
+ * The color spaces encoded in the heif image.
+ */
+typedef enum {
+ kHeifEncodedColor_RGB = 0,
+ kHeifEncodedColor_YUV = 1,
+ kHeifEncodedColor_CMYK = 2,
+} HeifEncodedColor;
+
+/*
+ * Represents a color converted (RGB-based) video frame
+ */
+struct HeifFrameInfo
+{
+ HeifFrameInfo() :
+ mWidth(0), mHeight(0), mRotationAngle(0), mBytesPerPixel(0),
+ mIccSize(0), mIccData(nullptr) {}
+
+ // update the frame info, will make a copy of |iccData| internally
+ void set(uint32_t width, uint32_t height, int32_t rotation, uint32_t bpp,
+ uint32_t iccSize, uint8_t* iccData) {
+ mWidth = width;
+ mHeight = height;
+ mRotationAngle = rotation;
+ mBytesPerPixel = bpp;
+
+ if (mIccData != nullptr) {
+ mIccData.reset(nullptr);
+ }
+ mIccSize = iccSize;
+ if (iccSize > 0) {
+ mIccData.reset(new uint8_t[iccSize]);
+ if (mIccData.get() != nullptr) {
+ memcpy(mIccData.get(), iccData, iccSize);
+ } else {
+ mIccSize = 0;
+ }
+ }
+ }
+
+ // Intentional public access modifiers:
+ uint32_t mWidth;
+ uint32_t mHeight;
+ int32_t mRotationAngle; // Rotation angle, clockwise, should be multiple of 90
+ uint32_t mBytesPerPixel; // Number of bytes for one pixel
+ uint32_t mIccSize; // Number of bytes in mIccData
+ std::unique_ptr<uint8_t> mIccData; // Actual ICC data, memory is owned by this structure
+};
+
+/*
+ * Abstract interface to provide data to HeifDecoder.
+ */
+struct HeifStream {
+ HeifStream() {}
+
+ virtual ~HeifStream() {}
+
+ /*
+ * Reads or skips size number of bytes. return the number of bytes actually
+ * read or skipped.
+ * If |buffer| == NULL, skip size bytes, return how many were skipped.
+ * If |buffer| != NULL, copy size bytes into buffer, return how many were copied.
+ */
+ virtual size_t read(void* buffer, size_t size) = 0;
+
+ /*
+ * Rewinds to the beginning of the stream. Returns true if the stream is known
+ * to be at the beginning after this call returns.
+ */
+ virtual bool rewind() = 0;
+
+ /*
+ * Seeks to an absolute position in the stream. If this cannot be done, returns false.
+ * If an attempt is made to seek past the end of the stream, the position will be set
+ * to the end of the stream.
+ */
+ virtual bool seek(size_t /*position*/) = 0;
+
+ /** Returns true if this stream can report its total length. */
+ virtual bool hasLength() const = 0;
+
+ /** Returns the total length of the stream. If this cannot be done, returns 0. */
+ virtual size_t getLength() const = 0;
+
+private:
+ HeifStream(const HeifFrameInfo&) = delete;
+ HeifStream& operator=(const HeifFrameInfo&) = delete;
+};
+
+/*
+ * Abstract interface to decode heif images from a HeifStream data source.
+ */
+struct HeifDecoder {
+ HeifDecoder() {}
+
+ virtual ~HeifDecoder() {}
+
+ /*
+ * Returns true if it successfully sets outColor to the encoded color,
+ * and false otherwise.
+ */
+ virtual bool getEncodedColor(HeifEncodedColor* outColor) const = 0;
+
+ /*
+ * Returns true if it successfully sets the output color format to color,
+ * and false otherwise.
+ */
+ virtual bool setOutputColor(HeifColorFormat color) = 0;
+
+ /*
+ * Returns true if it successfully initialize heif decoder with source,
+ * and false otherwise. |frameInfo| will be filled with information of
+ * the primary picture upon success and unmodified upon failure.
+ * Takes ownership of |stream| regardless of result.
+ */
+ virtual bool init(HeifStream* stream, HeifFrameInfo* frameInfo) = 0;
+
+ /*
+ * Decode the picture internally, returning whether it succeeded. |frameInfo|
+ * will be filled with information of the primary picture upon success and
+ * unmodified upon failure.
+ *
+ * After this succeeded, getScanline can be called to read the scanlines
+ * that were decoded.
+ */
+ virtual bool decode(HeifFrameInfo* frameInfo) = 0;
+
+ /*
+ * Read the next scanline (in top-down order), returns true upon success
+ * and false otherwise.
+ */
+ virtual bool getScanline(uint8_t* dst) = 0;
+
+ /*
+ * Skip the next |count| scanlines, returns true upon success and
+ * false otherwise.
+ */
+ virtual size_t skipScanlines(size_t count) = 0;
+
+private:
+ HeifDecoder(const HeifFrameInfo&) = delete;
+ HeifDecoder& operator=(const HeifFrameInfo&) = delete;
+};
+
+/*
+ * Creates a HeifDecoder. Returns a HeifDecoder instance upon success, or NULL
+ * if the creation has failed.
+ */
+HeifDecoder* createHeifDecoder();
+
+#endif // _HEIF_DECODER_API_
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index c73632c..ad38390 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -12,78 +12,10 @@
* 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.
+ *
+ *
*/
-/*
-* Documentation: Workflow summary for histogram data processing:
-* For more details on FIFO, please see system/media/audio_utils; doxygen
-* TODO: add this documentation to doxygen once it is further developed
-* 1) Writing buffer period timestamp to the circular buffer
-* onWork()
-* Called every period length (e.g., 4ms)
-* Calls LOG_HIST_TS
-* LOG_HIST_TS
-* Hashes file name and line number, and writes single timestamp to buffer
-* calls NBLOG::Writer::logEventHistTS once
-* NBLOG::Writer::logEventHistTS
-* calls NBLOG::Writer::log on hash and current timestamp
-* time is in CLOCK_MONOTONIC converted to ns
-* NBLOG::Writer::log(Event, const void*, size_t)
-* Initializes Entry, a struct containing one log entry
-* Entry contains the event type (mEvent), data length (mLength),
-* and data pointer (mData)
-* TODO: why mLength (max length of buffer data) must be <= kMaxLength = 255?
-* calls NBLOG::Writer::log(Entry *, bool)
-* NBLog::Writer::log(Entry *, bool)
-* Calls copyEntryDataAt to format data as follows in temp array:
-* [type][length][data ... ][length]
-* calls audio_utils_fifo_writer.write on temp
-* audio_utils_fifo_writer.write
-* calls obtain(), memcpy (reference in doxygen)
-* returns number of frames written
-* ssize_t audio_utils_fifo_reader::obtain
-* Determines readable buffer section via pointer arithmetic on reader
-* and writer pointers
-* Similarly, LOG_AUDIO_STATE() is called by onStateChange whenever audio is
-* turned on or off, and writes this notification to the FIFO.
-*
-* 2) reading the data from shared memory
-* Thread::threadloop()
-* NBLog::MergeThread::threadLoop()
-* Waits on a mutex, called periodically
-* Calls NBLog::Merger::merge and MergeReader.getAndProcessSnapshot.
-* NBLog::Merger::merge
-* Merges snapshots sorted by timestamp
-* Calls Reader::getSnapshot on each individual thread buffer to in shared
-* memory and writes all their data to the single FIFO stored in mMerger.
-* NBLog::Reader::getSnapshot
-* copies snapshot of reader's fifo buffer into its own buffer
-* calls mFifoReader->obtain to find readable data
-* sets snapshot.begin() and .end() iterators to boundaries of valid entries
-* moves the fifo reader index to after the last entry read
-* in this case, the buffer is in shared memory. in (4), the buffer is private
-* NBLog::MergeThread::getAndProcessSnapshot
-* Iterates through the entries in the local FIFO. Processes the data in
-* specific ways depending on the entry type. If the data is a histogram
-* timestamp or an audio on/off signal, writes to a map of PerformanceAnalysis
-* class instances, where the wakeup() intervals are stored as histograms
-* and analyzed.
-*
-* 3) Dumpsys media.log call to report the data
-* MediaLogService::dump in MediaLogService.cpp
-* calls NBLog::Reader::dump, which calls ReportPerformance::dump
-* ReportPerformance::dump
-* calls PerformanceAnalysis::ReportPerformance
-* and ReportPerformance::WriteToFile
-* PerformanceAnalysis::ReportPerformance
-* for each thread/source file location instance of PerformanceAnalysis data,
-* combines all histograms into a single one and prints it to the console
-* along with outlier data
-* ReportPerformance::WriteToFile
-* writes histogram, outlier, and peak information to file separately for each
-* instance of PerformanceAnalysis data.
-*/
-
#define LOG_TAG "NBLog"
#include <algorithm>
@@ -875,14 +807,6 @@
void NBLog::MergeReader::getAndProcessSnapshot(NBLog::Reader::Snapshot &snapshot)
{
String8 timestamp, body;
- // TODO: check: is this thread safe?
- // TODO: add lost data information and notification to ReportPerformance
- size_t lost = snapshot.lost() + (snapshot.begin() - EntryIterator(snapshot.data()));
- if (lost > 0) {
- // TODO: ultimately, this will be += and reset to 0. TODO: check that this is
- // obsolete now that Merger::merge is called periodically. No data should be lost
- mLost = lost;
- }
for (auto entry = snapshot.begin(); entry != snapshot.end();) {
switch (entry->type) {
diff --git a/media/libnbaio/OWNERS b/media/libnbaio/OWNERS
index f9cb567..eece71f 100644
--- a/media/libnbaio/OWNERS
+++ b/media/libnbaio/OWNERS
@@ -1 +1,2 @@
gkasten@google.com
+hunga@google.com
diff --git a/media/libnbaio/PerformanceAnalysis.cpp b/media/libnbaio/PerformanceAnalysis.cpp
index 4e446a4..9e0f84d 100644
--- a/media/libnbaio/PerformanceAnalysis.cpp
+++ b/media/libnbaio/PerformanceAnalysis.cpp
@@ -46,9 +46,8 @@
namespace ReportPerformance {
-// Given a the most recent timestamp of a series of audio processing
-// wakeup timestamps,
-// buckets the time interval into a histogram, searches for
+// Given an audio processing wakeup timestamp, buckets the time interval
+// since the previous timestamp into a histogram, searches for
// outliers, analyzes the outlier series for unexpectedly
// small or large values and stores these as peaks
void PerformanceAnalysis::logTsEntry(timestamp ts) {
@@ -75,7 +74,6 @@
// NormalMixer times vary much more than FastMixer times.
// TODO: mOutlierFactor values are set empirically based on what appears to be
// an outlier. Learn these values from the data.
- // TODO: the current settings are too high, change after next data collection is over
mBufferPeriod.mOutlierFactor = mBufferPeriod.mMean < kFastMixerMax ? 1.8 : 2.0;
// set outlier threshold
mBufferPeriod.mOutlier = mBufferPeriod.mMean * mBufferPeriod.mOutlierFactor;
@@ -265,7 +263,6 @@
timestamp startingTs = mHists[0].first;
// histogram which stores .1 precision ms counts instead of Jiffy multiple counts
- // TODO: when there is more data, print many histograms, possibly separated at peaks
std::map<double, int> buckets;
for (const auto &shortHist: mHists) {
for (const auto &countPair : shortHist.second) {
diff --git a/media/libnbaio/include/media/nbaio/NBLog.h b/media/libnbaio/include/media/nbaio/NBLog.h
index 5549728..2c00386 100644
--- a/media/libnbaio/include/media/nbaio/NBLog.h
+++ b/media/libnbaio/include/media/nbaio/NBLog.h
@@ -475,12 +475,6 @@
audio_utils_fifo_reader * const mFifoReader; // used to read from FIFO,
// non-NULL unless constructor fails
- // TODO: it might be clearer, instead of a direct map from source location to vector of
- // timestamps, if we instead first mapped from source location to an object that
- // represented that location. And one_of its fields would be a vector of timestamps.
- // That would allow us to record other information about the source location beyond
- // timestamps.
-
// Searches for the last entry of type <type> in the range [front, back)
// back has to be entry-aligned. Returns nullptr if none enconuntered.
static const uint8_t *findLastEntryOfTypes(const uint8_t *front, const uint8_t *back,
diff --git a/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h b/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
index fe73551..50367be 100644
--- a/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
+++ b/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
@@ -35,9 +35,9 @@
class PerformanceAnalysis {
// This class stores and analyzes audio processing wakeup timestamps from NBLog
- // FIXME: currently, all performance data is stored in deques. Need to add a mutex.
- // FIXME: continue this way until analysis is done in a separate thread. Then, use
- // the fifo writer utilities.
+ // FIXME: currently, all performance data is stored in deques. Turn these into circular
+ // buffers.
+ // TODO: add a mutex.
public:
PerformanceAnalysis() {};
@@ -45,20 +45,11 @@
friend void dump(int fd, int indent,
PerformanceAnalysisMap &threadPerformanceAnalysis);
- // Given a series of audio processing wakeup timestamps,
- // compresses and and analyzes the data, and flushes
- // the timestamp series from memory.
- void processAndFlushTimeStampSeries();
-
- // Called when an audio on/off event is read from the buffer,
- // e.g. EVENT_AUDIO_STATE.
- // calls flushTimeStampSeries on the data up to the event,
- // effectively discarding the idle audio time interval
+ // Called in the case of an audio on/off event, e.g., EVENT_AUDIO_STATE.
+ // Used to discard idle time intervals
void handleStateChange();
// Writes wakeup timestamp entry to log and runs analysis
- // TODO: make this thread safe. Each thread should have its own instance
- // of PerformanceAnalysis.
void logTsEntry(timestamp ts);
// FIXME: make peakdetector and storeOutlierData a single function
@@ -67,13 +58,11 @@
// writes timestamps of significant changes to mPeakTimestamps
bool detectAndStorePeak(msInterval delta, timestamp ts);
- // runs analysis on timestamp series before it is converted to a histogram
- // finds outliers
+ // stores timestamps of intervals above a threshold: these are assumed outliers.
// writes to mOutlierData <time elapsed since previous outlier, outlier timestamp>
bool detectAndStoreOutlier(const msInterval diffMs);
// Generates a string of analysis of the buffer periods and prints to console
- // TODO: WIP write more detailed analysis
// FIXME: move this data visualization to a separate class. Model/view/controller
void reportPerformance(String8 *body, int author, log_hash_t hash,
int maxHeight = 10);
diff --git a/media/libnbaio/include/media/nbaio/ReportPerformance.h b/media/libnbaio/include/media/nbaio/ReportPerformance.h
index af12812..ec0842f 100644
--- a/media/libnbaio/include/media/nbaio/ReportPerformance.h
+++ b/media/libnbaio/include/media/nbaio/ReportPerformance.h
@@ -23,8 +23,7 @@
namespace android {
-// This class is used by reportPerformance function
-// TODO move PerformanceAnalysis::reportPerformance function to ReportPerformance.cpp
+// The String8 class is used by reportPerformance function
class String8;
namespace ReportPerformance {
@@ -35,7 +34,6 @@
constexpr int kJiffyPerMs = 10; // time unit for histogram as a multiple of milliseconds
// stores a histogram: key: observed buffer period (multiple of jiffy). value: count
-// TODO: unsigned, unsigned
using Histogram = std::map<int, int>;
using msInterval = double;
@@ -45,7 +43,6 @@
using log_hash_t = uint64_t;
-// TODO: should this return an int64_t?
static inline int deltaMs(int64_t ns1, int64_t ns2) {
return (ns2 - ns1) / (1000 * 1000);
}
@@ -59,8 +56,7 @@
return 31 - __builtin_clz(x);
}
-// Writes outlier intervals, timestamps, and histograms spanning long time
-// intervals to a file.
+// Writes outlier intervals, timestamps, peaks timestamps, and histograms to a file.
void writeToFile(const std::deque<std::pair<timestamp, Histogram>> &hists,
const std::deque<std::pair<msInterval, timestamp>> &outlierData,
const std::deque<timestamp> &peakTimestamps,
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d4ec30d..63ad0e0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1866,16 +1866,15 @@
mFlags |= kFlagIsGrallocUsageProtected;
mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
}
+ }
+ if (mFlags & kFlagIsSecure) {
+ // use native_handles for secure input buffers
+ err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
- if (mFlags & kFlagIsSecure) {
- // use native_handles for secure input buffers
- err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
-
- if (err != OK) {
- ALOGI("falling back to non-native_handles");
- setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
- err = OK; // ignore error for now
- }
+ if (err != OK) {
+ ALOGI("falling back to non-native_handles");
+ setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
+ err = OK; // ignore error for now
}
}
if (haveNativeWindow) {
diff --git a/media/libstagefright/codec2/Android.bp b/media/libstagefright/codec2/Android.bp
index e5bc4b3..f79e058 100644
--- a/media/libstagefright/codec2/Android.bp
+++ b/media/libstagefright/codec2/Android.bp
@@ -1,6 +1,10 @@
cc_library_shared {
name: "libstagefright_codec2",
+ tags: [
+ "optional",
+ ],
+
srcs: ["C2.cpp"],
include_dirs: [
@@ -24,4 +28,5 @@
subdirs = [
"tests",
+ "vndk",
]
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 9f6b487..88f1db3 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -223,7 +223,11 @@
*
* \return acquired object potentially invalidated if waiting for the fence failed.
*/
- T get();
+ T get() {
+ // TODO:
+ // wait();
+ return mT;
+ }
protected:
C2Acquirable(C2Error error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
@@ -268,7 +272,7 @@
: mCapacity(parent == nullptr ? 0 : parent->capacity()) { }
private:
- const uint32_t mCapacity;
+ uint32_t mCapacity;
/// @}
};
@@ -429,7 +433,7 @@
/**
* \return pointer to the start of the block or nullptr on error.
*/
- const uint8_t *data();
+ const uint8_t *data() const;
/**
* Returns a portion of this view.
@@ -447,6 +451,10 @@
*/
C2Error error();
+protected:
+ C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
+ explicit C2ReadView(C2Error error);
+
private:
class Impl;
std::shared_ptr<Impl> mImpl;
@@ -476,6 +484,10 @@
*/
C2Error error();
+protected:
+ C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
+ explicit C2WriteView(C2Error error);
+
private:
class Impl;
/// \todo should this be unique_ptr to make this movable only - to avoid inconsistent regions
@@ -516,7 +528,13 @@
*/
C2Fence fence() const { return mFence; }
+protected:
+ C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc);
+ C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size);
+
private:
+ class Impl;
+ std::shared_ptr<Impl> mImpl;
C2Fence mFence;
};
@@ -544,6 +562,14 @@
* The block shall be modified only until firing the event for the fence.
*/
C2ConstLinearBlock share(size_t offset, size_t size, C2Fence fence);
+
+protected:
+ C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc);
+ C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size);
+
+private:
+ class Impl;
+ std::shared_ptr<Impl> mImpl;
};
/// @}
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index aeaf829..f071423 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -282,7 +282,7 @@
* fields in the same list?
*/
virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> fields,
+ const std::vector<const C2ParamField> &fields,
std::vector<C2FieldSupportedValues>* const values) const = 0;
virtual ~C2ComponentInterface() = default;
diff --git a/media/libstagefright/codec2/include/C2Config.h b/media/libstagefright/codec2/include/C2Config.h
index 30e9193..18e0a47 100644
--- a/media/libstagefright/codec2/include/C2Config.h
+++ b/media/libstagefright/codec2/include/C2Config.h
@@ -67,6 +67,7 @@
kParamIndexStructStart = 0x1,
kParamIndexVideoSize,
kParamIndexMaxVideoSizeHint,
+ kParamIndexVideoSizeTuning,
kParamIndexParamStart = 0x800,
};
@@ -230,19 +231,22 @@
int32_t mWidth; ///< video width
int32_t mHeight; ///< video height
- DEFINE_AND_DESCRIBE_C2STRUCT(VideoSize)
+ DEFINE_C2STRUCT_NO_BASE(VideoSize)
+} C2_PACK;
+
+DESCRIBE_C2STRUCT(VideoSize, {
C2FIELD(mWidth, "width")
C2FIELD(mHeight, "height")
-};
+})
// video size for video decoder [OUT]
-typedef C2StreamParam<C2Info, C2VideoSizeStruct> C2VideoSizeStreamInfo;
+typedef C2StreamParam<C2Info, C2VideoSizeStruct, kParamIndexVideoSize> C2VideoSizeStreamInfo;
// max video size for video decoder [IN]
typedef C2PortParam<C2Setting, C2VideoSizeStruct, kParamIndexMaxVideoSizeHint> C2MaxVideoSizeHintPortSetting;
// video encoder size [IN]
-typedef C2StreamParam<C2Tuning, C2VideoSizeStruct> C2VideoSizeStreamTuning;
+typedef C2StreamParam<C2Tuning, C2VideoSizeStruct, kParamIndexVideoSizeTuning> C2VideoSizeStreamTuning;
/// @}
diff --git a/media/libstagefright/codec2/include/C2Param.h b/media/libstagefright/codec2/include/C2Param.h
index fd43061..aab0474 100644
--- a/media/libstagefright/codec2/include/C2Param.h
+++ b/media/libstagefright/codec2/include/C2Param.h
@@ -362,6 +362,17 @@
return param;
}
+ /// Returns managed clone of |orig| at heap.
+ inline static std::unique_ptr<C2Param> Copy(const C2Param &orig) {
+ if (orig.size() == 0) {
+ return nullptr;
+ }
+ void *mem = ::operator new (orig.size());
+ C2Param *param = new (mem) C2Param(orig.size(), orig._mIndex);
+ param->updateFrom(orig);
+ return std::unique_ptr<C2Param>(param);
+ }
+
#if 0
template<typename P, class=decltype(C2Param(P()))>
P *As() { return P::From(this); }
@@ -661,11 +672,11 @@
Primitive mValue;
};
-template<> const int32_t &C2Value::Primitive::ref<int32_t>() const { return i32; }
-template<> const int64_t &C2Value::Primitive::ref<int64_t>() const { return i64; }
-template<> const uint32_t &C2Value::Primitive::ref<uint32_t>() const { return u32; }
-template<> const uint64_t &C2Value::Primitive::ref<uint64_t>() const { return u64; }
-template<> const float &C2Value::Primitive::ref<float>() const { return fp; }
+template<> inline const int32_t &C2Value::Primitive::ref<int32_t>() const { return i32; }
+template<> inline const int64_t &C2Value::Primitive::ref<int64_t>() const { return i64; }
+template<> inline const uint32_t &C2Value::Primitive::ref<uint32_t>() const { return u32; }
+template<> inline const uint64_t &C2Value::Primitive::ref<uint64_t>() const { return u64; }
+template<> inline const float &C2Value::Primitive::ref<float>() const { return fp; }
template<> constexpr C2Value::Type C2Value::typeFor<int32_t>() { return INT32; }
template<> constexpr C2Value::Type C2Value::typeFor<int64_t>() { return INT64; }
diff --git a/media/libstagefright/codec2/tests/Android.bp b/media/libstagefright/codec2/tests/Android.bp
index 1dc6a58..a8a6565 100644
--- a/media/libstagefright/codec2/tests/Android.bp
+++ b/media/libstagefright/codec2/tests/Android.bp
@@ -6,6 +6,7 @@
],
srcs: [
+ "vndk/C2BufferTest.cpp",
"vndk/C2UtilTest.cpp",
"C2_test.cpp",
"C2Param_test.cpp",
@@ -21,6 +22,16 @@
"libcutils",
"liblog",
"libstagefright_codec2",
+ "libcutils",
+ "libhidlbase",
+ "libion",
+ "liblog",
+ "libstagefright_codec2",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libstagefright_codec2_vndk",
],
cflags: [
diff --git a/media/libstagefright/codec2/tests/C2Param_test.cpp b/media/libstagefright/codec2/tests/C2Param_test.cpp
index ec82c84..9165aad 100644
--- a/media/libstagefright/codec2/tests/C2Param_test.cpp
+++ b/media/libstagefright/codec2/tests/C2Param_test.cpp
@@ -968,6 +968,10 @@
EXPECT_EQ(C2NumberStreamTuning::From(&tun), nullptr);
EXPECT_EQ(C2NumberStreamTuning::input::From(&tun), nullptr);
EXPECT_EQ(C2NumberStreamTuning::output::From(&tun), nullptr);
+
+ EXPECT_EQ(*(C2Param::Copy(btun)), btun);
+ btun.invalidate();
+ EXPECT_FALSE(C2Param::Copy(btun));
}
const C2NumberPortTuning outp1(true, 100), inp1(false, 100);
@@ -1171,6 +1175,11 @@
EXPECT_EQ(C2NumberStreamTuning::output::From(&inp2), nullptr);
EXPECT_EQ(C2NumberStreamTuning::output::From(&outp1), nullptr);
EXPECT_EQ(C2NumberStreamTuning::output::From(&outp2), nullptr);
+
+ EXPECT_EQ(*(C2Param::Copy(inp1)), inp1);
+ EXPECT_EQ(*(C2Param::Copy(inp2)), inp2);
+ EXPECT_EQ(*(C2Param::Copy(outp1)), outp1);
+ EXPECT_EQ(*(C2Param::Copy(outp2)), outp2);
}
const C2NumberStreamTuning outs1(true, 1u, 100), ins1(false, 1u, 100);
@@ -1383,6 +1392,10 @@
EXPECT_EQ(C2NumberStreamTuning::output::From(&outs1), (C2NumberStreamTuning::output*)&outs1);
EXPECT_EQ(C2NumberStreamTuning::output::From(&outs2), &outs2);
+ EXPECT_EQ(*(C2Param::Copy(ins1)), ins1);
+ EXPECT_EQ(*(C2Param::Copy(ins2)), ins2);
+ EXPECT_EQ(*(C2Param::Copy(outs1)), outs1);
+ EXPECT_EQ(*(C2Param::Copy(outs2)), outs2);
}
{
@@ -1518,6 +1531,8 @@
EXPECT_EQ(C2NumbersStreamTuning::From(tun.get()), nullptr);
EXPECT_EQ(C2NumbersStreamTuning::input::From(tun.get()), nullptr);
EXPECT_EQ(C2NumbersStreamTuning::output::From(tun.get()), nullptr);
+
+ EXPECT_EQ(*(C2Param::Copy(*tun)), *tun);
}
std::unique_ptr<C2NumbersPortTuning> outp1_(C2NumbersPortTuning::alloc_unique(1, true)),
@@ -1739,6 +1754,10 @@
EXPECT_EQ(C2NumbersStreamTuning::output::From(outp1.get()), nullptr);
EXPECT_EQ(C2NumbersStreamTuning::output::From(outp2.get()), nullptr);
+ EXPECT_EQ(*(C2Param::Copy(*inp1)), *inp1);
+ EXPECT_EQ(*(C2Param::Copy(*inp2)), *inp2);
+ EXPECT_EQ(*(C2Param::Copy(*outp1)), *outp1);
+ EXPECT_EQ(*(C2Param::Copy(*outp2)), *outp2);
}
std::unique_ptr<C2NumbersStreamTuning> outs1_(C2NumbersStreamTuning::alloc_unique(1, true, 1u));
@@ -1968,6 +1987,10 @@
EXPECT_EQ(C2NumbersStreamTuning::output::From(outs1.get()), (C2NumbersStreamTuning::output*)outs1.get());
EXPECT_EQ(C2NumbersStreamTuning::output::From(outs2.get()), outs2.get());
+ EXPECT_EQ(*(C2Param::Copy(*ins1)), *ins1);
+ EXPECT_EQ(*(C2Param::Copy(*ins2)), *ins2);
+ EXPECT_EQ(*(C2Param::Copy(*outs1)), *outs1);
+ EXPECT_EQ(*(C2Param::Copy(*outs2)), *outs2);
}
{
@@ -2262,7 +2285,7 @@
for (const C2Param::Index index : heapParamIndices) {
if (mMyParams.count(index)) {
C2Param & myParam = mMyParams.find(index)->second;
- std::unique_ptr<C2Param> paramCopy(C2Param::From(&myParam, myParam.size()));
+ std::unique_ptr<C2Param> paramCopy(C2Param::Copy(myParam));
heapParams->push_back(std::move(paramCopy));
}
}
@@ -2303,7 +2326,7 @@
};
virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> fields,
+ const std::vector<const C2ParamField> &fields,
std::vector<C2FieldSupportedValues>* const values) const {
for (const C2ParamField &field : fields) {
if (field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
new file mode 100644
index 0000000..0ba3cad
--- /dev/null
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <C2Buffer.h>
+#include <C2BufferPriv.h>
+
+#include <system/graphics.h>
+
+namespace android {
+
+class C2BufferTest : public ::testing::Test {
+public:
+ C2BufferTest()
+ : mAllocator(std::make_shared<C2AllocatorIon>()),
+ mSize(0u),
+ mAddr(nullptr) {
+ }
+
+ ~C2BufferTest() = default;
+
+ void allocate(size_t capacity) {
+ C2Error err = mAllocator->allocateLinearBuffer(
+ capacity,
+ { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
+ &mAllocation);
+ if (err != C2_OK) {
+ mAllocation.reset();
+ FAIL() << "C2Allocator::allocateLinearBuffer() failed: " << err;
+ }
+ }
+
+ void map(size_t offset, size_t size, uint8_t **addr) {
+ ASSERT_TRUE(mAllocation);
+ C2Error err = mAllocation->map(
+ offset,
+ size,
+ { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
+ // TODO: fence
+ nullptr,
+ &mAddr);
+ if (err != C2_OK) {
+ mAddr = nullptr;
+ FAIL() << "C2LinearAllocation::map() failed: " << err;
+ }
+ ASSERT_NE(nullptr, mAddr);
+ mSize = size;
+ *addr = (uint8_t *)mAddr;
+ }
+
+ void unmap() {
+ ASSERT_TRUE(mAllocation);
+ ASSERT_NE(nullptr, mAddr);
+ ASSERT_NE(0u, mSize);
+
+ // TODO: fence
+ ASSERT_EQ(C2_OK, mAllocation->unmap(mAddr, mSize, nullptr));
+ mSize = 0u;
+ mAddr = nullptr;
+ }
+
+ std::shared_ptr<C2BlockAllocator> makeBlockAllocator() {
+ return std::make_shared<C2DefaultBlockAllocator>(mAllocator);
+ }
+
+private:
+ std::shared_ptr<C2Allocator> mAllocator;
+ std::shared_ptr<C2LinearAllocation> mAllocation;
+ size_t mSize;
+ void *mAddr;
+};
+
+TEST_F(C2BufferTest, LinearAllocationTest) {
+ constexpr size_t kCapacity = 1024u * 1024u;
+
+ allocate(kCapacity);
+
+ uint8_t *addr = nullptr;
+ map(0u, kCapacity, &addr);
+ ASSERT_NE(nullptr, addr);
+
+ for (size_t i = 0; i < kCapacity; ++i) {
+ addr[i] = i % 100u;
+ }
+
+ unmap();
+ addr = nullptr;
+
+ map(kCapacity / 3, kCapacity / 3, &addr);
+ ASSERT_NE(nullptr, addr);
+ for (size_t i = 0; i < kCapacity / 3; ++i) {
+ ASSERT_EQ((i + kCapacity / 3) % 100, addr[i]) << " at i = " << i;
+ }
+}
+
+TEST_F(C2BufferTest, BlockAllocatorTest) {
+ constexpr size_t kCapacity = 1024u * 1024u;
+
+ std::shared_ptr<C2BlockAllocator> blockAllocator(makeBlockAllocator());
+
+ std::shared_ptr<C2LinearBlock> block;
+ ASSERT_EQ(C2_OK, blockAllocator->allocateLinearBlock(
+ kCapacity,
+ { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
+ &block));
+ ASSERT_TRUE(block);
+
+ C2Acquirable<C2WriteView> writeViewHolder = block->map();
+ C2WriteView writeView = writeViewHolder.get();
+ ASSERT_EQ(C2_OK, writeView.error());
+ ASSERT_EQ(kCapacity, writeView.capacity());
+ ASSERT_EQ(0u, writeView.offset());
+ ASSERT_EQ(kCapacity, writeView.size());
+
+ uint8_t *data = writeView.data();
+ ASSERT_NE(nullptr, data);
+ for (size_t i = 0; i < writeView.size(); ++i) {
+ data[i] = i % 100u;
+ }
+
+ C2Fence fence;
+ C2ConstLinearBlock constBlock = block->share(
+ kCapacity / 3, kCapacity / 3, fence);
+
+ C2Acquirable<C2ReadView> readViewHolder = constBlock.map();
+ C2ReadView readView = readViewHolder.get();
+ ASSERT_EQ(C2_OK, readView.error());
+ ASSERT_EQ(kCapacity / 3, readView.capacity());
+
+ // TODO: fence
+ const uint8_t *constData = readView.data();
+ ASSERT_NE(nullptr, constData);
+ for (size_t i = 0; i < readView.capacity(); ++i) {
+ ASSERT_EQ((i + kCapacity / 3) % 100u, constData[i]) << " at i = " << i
+ << "; data = " << static_cast<void *>(data)
+ << "; constData = " << static_cast<const void *>(constData);
+ }
+
+ readView = readView.subView(333u, 100u);
+ ASSERT_EQ(C2_OK, readView.error());
+ ASSERT_EQ(100u, readView.capacity());
+
+ constData = readView.data();
+ ASSERT_NE(nullptr, constData);
+ for (size_t i = 0; i < readView.capacity(); ++i) {
+ ASSERT_EQ((i + 333u + kCapacity / 3) % 100u, constData[i]) << " at i = " << i;
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/codec2/vndk/Android.bp b/media/libstagefright/codec2/vndk/Android.bp
new file mode 100644
index 0000000..9426b4e
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/Android.bp
@@ -0,0 +1,30 @@
+cc_library_static {
+ name: "libstagefright_codec2_vndk",
+
+ srcs: ["C2Buffer.cpp"],
+
+ include_dirs: [
+ "frameworks/av/media/libstagefright/codec2/include",
+ "frameworks/av/media/libstagefright/codec2/vndk/include",
+ "frameworks/native/include/media/hardware",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libdl",
+ "libhardware",
+ "libhidlbase",
+ "libion",
+ "liblog",
+ "libmedia",
+ "libstagefright_foundation",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-std=c++14",
+ ],
+}
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
new file mode 100644
index 0000000..ffb6c2e
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -0,0 +1,720 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "C2Buffer"
+#include <utils/Log.h>
+
+#include <C2BufferPriv.h>
+
+#include <ion/ion.h>
+#include <sys/mman.h>
+
+namespace android {
+
+// standard ERRNO mappings
+template<int N> constexpr C2Error _c2_errno2error_impl();
+template<> constexpr C2Error _c2_errno2error_impl<0>() { return C2_OK; }
+template<> constexpr C2Error _c2_errno2error_impl<EINVAL>() { return C2_BAD_VALUE; }
+template<> constexpr C2Error _c2_errno2error_impl<EACCES>() { return C2_NO_PERMISSION; }
+template<> constexpr C2Error _c2_errno2error_impl<EPERM>() { return C2_NO_PERMISSION; }
+template<> constexpr C2Error _c2_errno2error_impl<ENOMEM>() { return C2_NO_MEMORY; }
+
+// map standard errno-s to the equivalent C2Error
+template<int... N> struct _c2_map_errno_impl;
+template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
+ static C2Error map(int result) {
+ if (result == E) {
+ return _c2_errno2error_impl<E>();
+ } else {
+ return _c2_map_errno_impl<N...>::map(result);
+ }
+ }
+};
+template<> struct _c2_map_errno_impl<> {
+ static C2Error map(int result) {
+ return result == 0 ? C2_OK : C2_CORRUPTED;
+ }
+};
+
+template<int... N>
+C2Error c2_map_errno(int result) {
+ return _c2_map_errno_impl<N...>::map(result);
+}
+
+namespace {
+
+// Inherit from the parent, share with the friend.
+
+class DummyCapacityAspect : public _C2LinearCapacityAspect {
+ using _C2LinearCapacityAspect::_C2LinearCapacityAspect;
+ friend class ::android::C2ReadView;
+ friend class ::android::C2ConstLinearBlock;
+};
+
+class C2DefaultReadView : public C2ReadView {
+ using C2ReadView::C2ReadView;
+ friend class ::android::C2ConstLinearBlock;
+};
+
+class C2DefaultWriteView : public C2WriteView {
+ using C2WriteView::C2WriteView;
+ friend class ::android::C2LinearBlock;
+};
+
+class C2AcquirableReadView : public C2Acquirable<C2ReadView> {
+ using C2Acquirable::C2Acquirable;
+ friend class ::android::C2ConstLinearBlock;
+};
+
+class C2AcquirableWriteView : public C2Acquirable<C2WriteView> {
+ using C2Acquirable::C2Acquirable;
+ friend class ::android::C2LinearBlock;
+};
+
+class C2DefaultConstLinearBlock : public C2ConstLinearBlock {
+ using C2ConstLinearBlock::C2ConstLinearBlock;
+ friend class ::android::C2LinearBlock;
+};
+
+class C2DefaultLinearBlock : public C2LinearBlock {
+ using C2LinearBlock::C2LinearBlock;
+ friend class ::android::C2DefaultBlockAllocator;
+};
+
+} // namespace
+
+/* ======================================= ION ALLOCATION ====================================== */
+
+/**
+ * ION handle
+ */
+struct C2HandleIon : public C2Handle {
+ C2HandleIon(int ionFd, ion_user_handle_t buffer) : C2Handle(cHeader),
+ mFds{ ionFd, buffer },
+ mInts{ kMagic } { }
+
+ static bool isValid(const C2Handle * const o);
+
+ int ionFd() const { return mFds.mIon; }
+ ion_user_handle_t buffer() const { return mFds.mBuffer; }
+
+ void setBuffer(ion_user_handle_t bufferFd) { mFds.mBuffer = bufferFd; }
+
+protected:
+ struct {
+ int mIon;
+ int mBuffer; // ion_user_handle_t
+ } mFds;
+ struct {
+ int mMagic;
+ } mInts;
+
+private:
+ typedef C2HandleIon _type;
+ enum {
+ kMagic = 'ion1',
+ numFds = sizeof(mFds) / sizeof(int),
+ numInts = sizeof(mInts) / sizeof(int),
+ version = sizeof(C2Handle) + sizeof(mFds) + sizeof(mInts)
+ };
+ //constexpr static C2Handle cHeader = { version, numFds, numInts, {} };
+ const static C2Handle cHeader;
+};
+
+const C2Handle C2HandleIon::cHeader = {
+ C2HandleIon::version,
+ C2HandleIon::numFds,
+ C2HandleIon::numInts,
+ {}
+};
+
+// static
+bool C2HandleIon::isValid(const C2Handle * const o) {
+ if (!o || memcmp(o, &cHeader, sizeof(cHeader))) {
+ return false;
+ }
+ const C2HandleIon *other = static_cast<const C2HandleIon*>(o);
+ return other->mInts.mMagic == kMagic;
+}
+
+// TODO: is the dup of an ion fd identical to ion_share?
+
+class C2AllocationIon : public C2LinearAllocation {
+public:
+ virtual C2Error map(
+ size_t offset, size_t size, C2MemoryUsage usage, int *fence,
+ void **addr /* nonnull */);
+ virtual C2Error unmap(void *addr, size_t size, int *fenceFd);
+ virtual bool isValid() const;
+ virtual ~C2AllocationIon();
+ virtual const C2Handle *handle() const;
+ virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const;
+
+ // internal methods
+ C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
+ C2AllocationIon(int ionFd, size_t size, int shareFd);
+ int dup() const;
+ C2Error status() const;
+
+protected:
+ class Impl;
+ Impl *mImpl;
+};
+
+class C2AllocationIon::Impl {
+public:
+ // NOTE: using constructor here instead of a factory method as we will need the
+ // error value and this simplifies the error handling by the wrapper.
+ Impl(int ionFd, size_t capacity, size_t align, unsigned heapMask, unsigned flags)
+ : mInit(C2_OK),
+ mHandle(ionFd, -1),
+ mMapFd(-1),
+ mCapacity(capacity) {
+ ion_user_handle_t buffer = -1;
+ int ret = ion_alloc(mHandle.ionFd(), mCapacity, align, heapMask, flags, &buffer);
+ if (ret == 0) {
+ mHandle.setBuffer(buffer);
+ } else {
+ mInit = c2_map_errno<ENOMEM, EACCES, EINVAL>(-ret);
+ }
+ }
+
+ Impl(int ionFd, size_t capacity, int shareFd)
+ : mHandle(ionFd, -1),
+ mMapFd(-1),
+ mCapacity(capacity) {
+ ion_user_handle_t buffer;
+ mInit = ion_import(mHandle.ionFd(), shareFd, &buffer);
+ if (mInit == 0) {
+ mHandle.setBuffer(buffer);
+ }
+ (void)mCapacity; // TODO
+ }
+
+ C2Error map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+ (void)fenceFd; // TODO: wait for fence
+ *addr = nullptr;
+ int prot = PROT_NONE;
+ int flags = MAP_PRIVATE;
+ if (usage.mConsumer & GRALLOC_USAGE_SW_READ_MASK) {
+ prot |= PROT_READ;
+ }
+ if (usage.mProducer & GRALLOC_USAGE_SW_WRITE_MASK) {
+ prot |= PROT_WRITE;
+ flags = MAP_SHARED;
+ }
+
+ size_t alignmentBytes = offset % PAGE_SIZE;
+ size_t mapOffset = offset - alignmentBytes;
+ size_t mapSize = size + alignmentBytes;
+
+ C2Error err = C2_OK;
+ if (mMapFd == -1) {
+ int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
+ flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
+ if (ret) {
+ mMapFd = -1;
+ *addr = nullptr;
+ err = c2_map_errno<EINVAL>(-ret);
+ } else {
+ *addr = (uint8_t *)mMapAddr + alignmentBytes;
+ mMapAlignmentBytes = alignmentBytes;
+ mMapSize = mapSize;
+ }
+ } else {
+ mMapAddr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset);
+ if (mMapAddr == MAP_FAILED) {
+ mMapAddr = *addr = nullptr;
+ err = c2_map_errno<EINVAL>(errno);
+ } else {
+ *addr = (uint8_t *)mMapAddr + alignmentBytes;
+ mMapAlignmentBytes = alignmentBytes;
+ mMapSize = mapSize;
+ }
+ }
+ return err;
+ }
+
+ C2Error unmap(void *addr, size_t size, int *fenceFd) {
+ if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
+ size + mMapAlignmentBytes != mMapSize) {
+ return C2_BAD_VALUE;
+ }
+ int err = munmap(mMapAddr, mMapSize);
+ if (err != 0) {
+ return c2_map_errno<EINVAL>(errno);
+ }
+ if (fenceFd) {
+ *fenceFd = -1;
+ }
+ return C2_OK;
+ }
+
+ ~Impl() {
+ if (mMapFd != -1) {
+ close(mMapFd);
+ mMapFd = -1;
+ }
+
+ (void)ion_free(mHandle.ionFd(), mHandle.buffer());
+ }
+
+ C2Error status() const {
+ return mInit;
+ }
+
+ const C2Handle * handle() const {
+ return &mHandle;
+ }
+
+ int dup() const {
+ int fd = -1;
+ if (mInit != 0 || ion_share(mHandle.ionFd(), mHandle.buffer(), &fd) != 0) {
+ fd = -1;
+ }
+ return fd;
+ }
+
+private:
+ C2Error mInit;
+ C2HandleIon mHandle;
+ int mMapFd; // only one for now
+ void *mMapAddr;
+ size_t mMapAlignmentBytes;
+ size_t mMapSize;
+ size_t mCapacity;
+};
+
+C2Error C2AllocationIon::map(
+ size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+ return mImpl->map(offset, size, usage, fenceFd, addr);
+}
+
+C2Error C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+ return mImpl->unmap(addr, size, fenceFd);
+}
+
+bool C2AllocationIon::isValid() const {
+ return mImpl->status() == C2_OK;
+}
+
+C2Error C2AllocationIon::status() const {
+ return mImpl->status();
+}
+
+bool C2AllocationIon::equals(const std::shared_ptr<C2LinearAllocation> &other) const {
+ return other != nullptr &&
+ other->handle(); // TODO
+}
+
+const C2Handle *C2AllocationIon::handle() const {
+ return mImpl->handle();
+}
+
+C2AllocationIon::~C2AllocationIon() {
+ delete mImpl;
+}
+
+C2AllocationIon::C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags)
+ : C2LinearAllocation(size),
+ mImpl(new Impl(ionFd, size, align, heapMask, flags)) { }
+
+C2AllocationIon::C2AllocationIon(int ionFd, size_t size, int shareFd)
+ : C2LinearAllocation(size),
+ mImpl(new Impl(ionFd, size, shareFd)) { }
+
+int C2AllocationIon::dup() const {
+ return mImpl->dup();
+}
+
+/* ======================================= ION ALLOCATOR ====================================== */
+
+C2AllocatorIon::C2AllocatorIon() : mInit(C2_OK), mIonFd(ion_open()) {
+ if (mIonFd < 0) {
+ switch (errno) {
+ case ENOENT: mInit = C2_UNSUPPORTED; break;
+ default: mInit = c2_map_errno<EACCES>(errno); break;
+ }
+ }
+}
+
+C2AllocatorIon::~C2AllocatorIon() {
+ if (mInit == C2_OK) {
+ ion_close(mIonFd);
+ }
+}
+
+/**
+ * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
+ * stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param capacity the size of requested allocation (the allocation could be slightly
+ * larger, e.g. to account for any system-required alignment)
+ * \param usage the memory usage info for the requested allocation. \note that the
+ * returned allocation may be later used/mapped with different usage.
+ * The allocator should layout the buffer to be optimized for this usage,
+ * but must support any usage. One exception: protected buffers can
+ * only be used in a protected scenario.
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete the allocation
+ * \retval C2_TIMED_OUT the allocation timed out
+ * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+C2Error C2AllocatorIon::allocateLinearBuffer(
+ uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
+ *allocation = nullptr;
+ if (mInit != C2_OK) {
+ return C2_UNSUPPORTED;
+ }
+
+ // get align, heapMask and flags
+ //size_t align = 1;
+ size_t align = 0;
+ unsigned heapMask = ~0;
+ unsigned flags = 0;
+ //TODO
+ (void) usage;
+#if 0
+ int err = mUsageMapper(usage, capacity, &align, &heapMask, &flags);
+ if (err < 0) {
+ return c2_map_errno<EINVAL, ENOMEM, EACCES>(-err);
+ }
+#endif
+
+ std::shared_ptr<C2AllocationIon> alloc
+ = std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
+ C2Error ret = alloc->status();
+ if (ret == C2_OK) {
+ *allocation = alloc;
+ }
+ return ret;
+}
+
+/**
+ * (Re)creates a 1D allocation from a native |handle|. If successful, the allocation is stored
+ * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param handle the handle for the existing allocation
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was recreated successfully
+ * \retval C2_NO_MEMORY not enough memory to recreate the allocation
+ * \retval C2_TIMED_OUT the recreation timed out (unexpected)
+ * \retval C2_NO_PERMISSION no permission to recreate the allocation
+ * \retval C2_BAD_VALUE invalid handle (caller error)
+ * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+C2Error C2AllocatorIon::recreateLinearBuffer(
+ const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
+ *allocation = nullptr;
+ if (mInit != C2_OK) {
+ return C2_UNSUPPORTED;
+ }
+
+ if (!C2HandleIon::isValid(handle)) {
+ return C2_BAD_VALUE;
+ }
+
+ // TODO: get capacity and validate it
+ const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
+ std::shared_ptr<C2AllocationIon> alloc
+ = std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
+ C2Error ret = alloc->status();
+ if (ret == C2_OK) {
+ *allocation = alloc;
+ }
+ return ret;
+}
+
+/* ========================================== 1D BLOCK ========================================= */
+
+class C2Block1D::Impl {
+public:
+ const C2Handle *handle() const {
+ return mAllocation->handle();
+ }
+
+ Impl(std::shared_ptr<C2LinearAllocation> alloc)
+ : mAllocation(alloc) {}
+
+private:
+ std::shared_ptr<C2LinearAllocation> mAllocation;
+};
+
+const C2Handle *C2Block1D::handle() const {
+ return mImpl->handle();
+};
+
+C2Block1D::C2Block1D(std::shared_ptr<C2LinearAllocation> alloc)
+ : _C2LinearRangeAspect(alloc.get()), mImpl(new Impl(alloc)) {
+}
+
+C2Block1D::C2Block1D(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size)
+ : _C2LinearRangeAspect(alloc.get(), offset, size), mImpl(new Impl(alloc)) {
+}
+
+class C2ReadView::Impl {
+public:
+ explicit Impl(const uint8_t *data)
+ : mData(data), mError(C2_OK) {}
+
+ explicit Impl(C2Error error)
+ : mData(nullptr), mError(error) {}
+
+ const uint8_t *data() const {
+ return mData;
+ }
+
+ C2Error error() const {
+ return mError;
+ }
+
+private:
+ const uint8_t *mData;
+ C2Error mError;
+};
+
+C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
+ : _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
+
+C2ReadView::C2ReadView(C2Error error)
+ : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
+
+const uint8_t *C2ReadView::data() const {
+ return mImpl->data();
+}
+
+C2ReadView C2ReadView::subView(size_t offset, size_t size) const {
+ if (offset > capacity()) {
+ offset = capacity();
+ }
+ if (size > capacity() - offset) {
+ size = capacity() - offset;
+ }
+ // TRICKY: newCapacity will just be used to grab the size.
+ DummyCapacityAspect newCapacity((uint32_t)size);
+ return C2ReadView(&newCapacity, data() + offset);
+}
+
+C2Error C2ReadView::error() {
+ return mImpl->error();
+}
+
+class C2WriteView::Impl {
+public:
+ explicit Impl(uint8_t *base)
+ : mBase(base), mError(C2_OK) {}
+
+ explicit Impl(C2Error error)
+ : mBase(nullptr), mError(error) {}
+
+ uint8_t *base() const {
+ return mBase;
+ }
+
+ C2Error error() const {
+ return mError;
+ }
+
+private:
+ uint8_t *mBase;
+ C2Error mError;
+};
+
+C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
+ : _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
+
+C2WriteView::C2WriteView(C2Error error)
+ : _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
+
+uint8_t *C2WriteView::base() { return mImpl->base(); }
+
+uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
+
+C2Error C2WriteView::error() { return mImpl->error(); }
+
+class C2ConstLinearBlock::Impl {
+public:
+ explicit Impl(std::shared_ptr<C2LinearAllocation> alloc)
+ : mAllocation(alloc), mBase(nullptr), mSize(0u), mError(C2_CORRUPTED) {}
+
+ ~Impl() {
+ if (mBase != nullptr) {
+ // TODO: fence
+ C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+ if (err != C2_OK) {
+ // TODO: Log?
+ }
+ }
+ }
+
+ C2ConstLinearBlock subBlock(size_t offset, size_t size) const {
+ return C2ConstLinearBlock(mAllocation, offset, size);
+ }
+
+ void map(size_t offset, size_t size) {
+ if (mBase == nullptr) {
+ void *base = nullptr;
+ mError = mAllocation->map(
+ offset, size, { C2MemoryUsage::kSoftwareRead, 0 }, nullptr, &base);
+ // TODO: fence
+ if (mError == C2_OK) {
+ mBase = (uint8_t *)base;
+ mSize = size;
+ }
+ }
+ }
+
+ const uint8_t *base() const { return mBase; }
+
+ C2Error error() const { return mError; }
+
+private:
+ std::shared_ptr<C2LinearAllocation> mAllocation;
+ uint8_t *mBase;
+ size_t mSize;
+ C2Error mError;
+};
+
+C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
+ : C2Block1D(alloc), mImpl(std::make_shared<Impl>(alloc)) {}
+
+C2ConstLinearBlock::C2ConstLinearBlock(
+ std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size)
+ : C2Block1D(alloc, offset, size), mImpl(std::make_shared<Impl>(alloc)) {}
+
+C2Acquirable<C2ReadView> C2ConstLinearBlock::map() const {
+ mImpl->map(offset(), size());
+ if (mImpl->base() == nullptr) {
+ C2DefaultReadView view(mImpl->error());
+ return C2AcquirableReadView(mImpl->error(), mFence, view);
+ }
+ DummyCapacityAspect newCapacity(size());
+ C2DefaultReadView view(&newCapacity, mImpl->base());
+ return C2AcquirableReadView(mImpl->error(), mFence, view);
+}
+
+C2ConstLinearBlock C2ConstLinearBlock::subBlock(size_t offset, size_t size) const {
+ return mImpl->subBlock(offset, size);
+}
+
+class C2LinearBlock::Impl {
+public:
+ Impl(std::shared_ptr<C2LinearAllocation> alloc)
+ : mAllocation(alloc), mBase(nullptr), mSize(0u), mError(C2_CORRUPTED) {}
+
+ ~Impl() {
+ if (mBase != nullptr) {
+ // TODO: fence
+ C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+ if (err != C2_OK) {
+ // TODO: Log?
+ }
+ }
+ }
+
+ void map(size_t capacity) {
+ if (mBase == nullptr) {
+ void *base = nullptr;
+ // TODO: fence
+ mError = mAllocation->map(
+ 0u,
+ capacity,
+ { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
+ nullptr,
+ &base);
+ if (mError == C2_OK) {
+ mBase = (uint8_t *)base;
+ mSize = capacity;
+ }
+ }
+ }
+
+ C2ConstLinearBlock share(size_t offset, size_t size, C2Fence &fence) {
+ // TODO
+ (void) fence;
+ return C2DefaultConstLinearBlock(mAllocation, offset, size);
+ }
+
+ uint8_t *base() const { return mBase; }
+
+ C2Error error() const { return mError; }
+
+ C2Fence fence() const { return mFence; }
+
+private:
+ std::shared_ptr<C2LinearAllocation> mAllocation;
+ uint8_t *mBase;
+ size_t mSize;
+ C2Error mError;
+ C2Fence mFence;
+};
+
+C2LinearBlock::C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
+ : C2Block1D(alloc),
+ mImpl(new Impl(alloc)) {}
+
+C2LinearBlock::C2LinearBlock(std::shared_ptr<C2LinearAllocation> alloc, size_t offset, size_t size)
+ : C2Block1D(alloc, offset, size),
+ mImpl(new Impl(alloc)) {}
+
+C2Acquirable<C2WriteView> C2LinearBlock::map() {
+ mImpl->map(capacity());
+ if (mImpl->base() == nullptr) {
+ C2DefaultWriteView view(mImpl->error());
+ return C2AcquirableWriteView(mImpl->error(), mImpl->fence(), view);
+ }
+ C2DefaultWriteView view(this, mImpl->base());
+ view.setOffset_be(offset());
+ view.setSize_be(size());
+ return C2AcquirableWriteView(mImpl->error(), mImpl->fence(), view);
+}
+
+C2ConstLinearBlock C2LinearBlock::share(size_t offset, size_t size, C2Fence fence) {
+ return mImpl->share(offset, size, fence);
+}
+
+C2DefaultBlockAllocator::C2DefaultBlockAllocator(
+ const std::shared_ptr<C2Allocator> &allocator)
+ : mAllocator(allocator) {}
+
+C2Error C2DefaultBlockAllocator::allocateLinearBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
+ block->reset();
+
+ std::shared_ptr<C2LinearAllocation> alloc;
+ C2Error err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
+ if (err != C2_OK) {
+ return err;
+ }
+
+ block->reset(new C2DefaultLinearBlock(alloc));
+
+ return C2_OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
new file mode 100644
index 0000000..bfb069c
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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 STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
+#define STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
+
+#include <functional>
+
+#include <C2Buffer.h>
+
+namespace android {
+
+class C2AllocatorIon : public C2Allocator {
+public:
+ // (usage, capacity) => (align, heapMask, flags)
+ typedef std::function<int (C2MemoryUsage, size_t,
+ /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
+
+ virtual C2Error allocateLinearBuffer(
+ uint32_t capacity, C2MemoryUsage usage,
+ std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+ virtual C2Error recreateLinearBuffer(
+ const C2Handle *handle,
+ std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+ C2AllocatorIon();
+
+ C2Error status() const { return mInit; }
+
+ virtual ~C2AllocatorIon();
+
+private:
+ C2Error mInit;
+ int mIonFd;
+ usage_mapper_fn mUsageMapper;
+};
+
+class C2DefaultBlockAllocator : public C2BlockAllocator {
+public:
+ explicit C2DefaultBlockAllocator(const std::shared_ptr<C2Allocator> &allocator);
+
+ virtual ~C2DefaultBlockAllocator() = default;
+
+ virtual C2Error allocateLinearBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
+
+ // TODO:
+private:
+ const std::shared_ptr<C2Allocator> mAllocator;
+};
+
+#if 0
+class C2Allocation::Impl {
+public:
+ Impl() : mMapped(false), mBase(nullptr) { }
+ uint8_t* base() { return mMapped ? mBase : nullptr; }
+
+ // TODO: call map...
+
+private:
+ bool mMapped;
+ uint8_t *mBase;
+};
+#endif
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/libstagefright/codecs/opus/dec/Android.bp b/media/libstagefright/codecs/opus/dec/Android.bp
index 2bedbda..d7569a9 100644
--- a/media/libstagefright/codecs/opus/dec/Android.bp
+++ b/media/libstagefright/codecs/opus/dec/Android.bp
@@ -21,6 +21,8 @@
"liblog",
],
+ cflags: ["-Werror"],
+
sanitize: {
misc_undefined: [
"signed-integer-overflow",
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index d1f5e59..813004b 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -62,6 +62,7 @@
mSeekPreRoll(0),
mAnchorTimeUs(0),
mNumFramesOutput(0),
+ mHaveEOS(false),
mOutputPortSettingsChange(NONE) {
initPorts();
CHECK_EQ(initDecoder(), (status_t)OK);
@@ -384,7 +385,31 @@
return static_cast<double>(ns) * kRate / 1000000000;
}
-void SoftOpus::onQueueFilled(OMX_U32 portIndex) {
+void SoftOpus::handleEOS() {
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+ CHECK(!inQueue.empty() && !outQueue.empty());
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ mHaveEOS = true;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ ++mInputBufferCount;
+}
+
+void SoftOpus::onQueueFilled(OMX_U32 /* portIndex */) {
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
@@ -392,104 +417,108 @@
return;
}
- if (portIndex == 0 && mInputBufferCount < 3) {
- BufferInfo *info = *inQueue.begin();
- OMX_BUFFERHEADERTYPE *header = info->mHeader;
-
- const uint8_t *data = header->pBuffer + header->nOffset;
- size_t size = header->nFilledLen;
-
- if (mInputBufferCount == 0) {
- CHECK(mHeader == NULL);
- mHeader = new OpusHeader();
- memset(mHeader, 0, sizeof(*mHeader));
- if (!ParseOpusHeader(data, size, mHeader)) {
- ALOGV("Parsing Opus Header failed.");
- notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- return;
- }
-
- uint8_t channel_mapping[kMaxChannels] = {0};
- if (mHeader->channels <= kMaxChannelsWithDefaultLayout) {
- memcpy(&channel_mapping,
- kDefaultOpusChannelLayout,
- kMaxChannelsWithDefaultLayout);
- } else {
- memcpy(&channel_mapping,
- mHeader->stream_map,
- mHeader->channels);
- }
-
- int status = OPUS_INVALID_STATE;
- mDecoder = opus_multistream_decoder_create(kRate,
- mHeader->channels,
- mHeader->num_streams,
- mHeader->num_coupled,
- channel_mapping,
- &status);
- if (!mDecoder || status != OPUS_OK) {
- ALOGV("opus_multistream_decoder_create failed status=%s",
- opus_strerror(status));
- notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- return;
- }
- status =
- opus_multistream_decoder_ctl(mDecoder,
- OPUS_SET_GAIN(mHeader->gain_db));
- if (status != OPUS_OK) {
- ALOGV("Failed to set OPUS header gain; status=%s",
- opus_strerror(status));
- notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- return;
- }
- } else if (mInputBufferCount == 1) {
- mCodecDelay = ns_to_samples(
- *(reinterpret_cast<int64_t*>(header->pBuffer +
- header->nOffset)),
- kRate);
- mSamplesToDiscard = mCodecDelay;
- } else {
- mSeekPreRoll = ns_to_samples(
- *(reinterpret_cast<int64_t*>(header->pBuffer +
- header->nOffset)),
- kRate);
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
- }
-
- inQueue.erase(inQueue.begin());
- info->mOwnedByUs = false;
- notifyEmptyBufferDone(header);
- ++mInputBufferCount;
- return;
- }
-
- while (!inQueue.empty() && !outQueue.empty()) {
+ while (!mHaveEOS && !inQueue.empty() && !outQueue.empty()) {
BufferInfo *inInfo = *inQueue.begin();
OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
- // Ignore CSD re-submissions.
- if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ if (mInputBufferCount < 3) {
+ const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
+ size_t size = inHeader->nFilledLen;
+
+ if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && size == 0) {
+ handleEOS();
+ return;
+ }
+
+ if (mInputBufferCount == 0) {
+ CHECK(mHeader == NULL);
+ mHeader = new OpusHeader();
+ memset(mHeader, 0, sizeof(*mHeader));
+ if (!ParseOpusHeader(data, size, mHeader)) {
+ ALOGV("Parsing Opus Header failed.");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
+ uint8_t channel_mapping[kMaxChannels] = {0};
+ if (mHeader->channels <= kMaxChannelsWithDefaultLayout) {
+ memcpy(&channel_mapping,
+ kDefaultOpusChannelLayout,
+ kMaxChannelsWithDefaultLayout);
+ } else {
+ memcpy(&channel_mapping,
+ mHeader->stream_map,
+ mHeader->channels);
+ }
+
+ int status = OPUS_INVALID_STATE;
+ mDecoder = opus_multistream_decoder_create(kRate,
+ mHeader->channels,
+ mHeader->num_streams,
+ mHeader->num_coupled,
+ channel_mapping,
+ &status);
+ if (!mDecoder || status != OPUS_OK) {
+ ALOGV("opus_multistream_decoder_create failed status=%s",
+ opus_strerror(status));
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+ status =
+ opus_multistream_decoder_ctl(mDecoder,
+ OPUS_SET_GAIN(mHeader->gain_db));
+ if (status != OPUS_OK) {
+ ALOGV("Failed to set OPUS header gain; status=%s",
+ opus_strerror(status));
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+ } else if (mInputBufferCount == 1) {
+ mCodecDelay = ns_to_samples(
+ *(reinterpret_cast<int64_t*>(inHeader->pBuffer +
+ inHeader->nOffset)),
+ kRate);
+ mSamplesToDiscard = mCodecDelay;
+ } else {
+ mSeekPreRoll = ns_to_samples(
+ *(reinterpret_cast<int64_t*>(inHeader->pBuffer +
+ inHeader->nOffset)),
+ kRate);
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ }
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ handleEOS();
+ return;
+ }
+
inQueue.erase(inQueue.begin());
inInfo->mOwnedByUs = false;
notifyEmptyBufferDone(inHeader);
- return;
+ ++mInputBufferCount;
+
+ continue;
+ }
+
+ // Ignore CSD re-submissions.
+ if (mInputBufferCount >= 3 && (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ handleEOS();
+ return;
+ }
+
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+ continue;
}
BufferInfo *outInfo = *outQueue.begin();
OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
- inQueue.erase(inQueue.begin());
- inInfo->mOwnedByUs = false;
- notifyEmptyBufferDone(inHeader);
-
- outHeader->nFilledLen = 0;
- outHeader->nFlags = OMX_BUFFERFLAG_EOS;
-
- outQueue.erase(outQueue.begin());
- outInfo->mOwnedByUs = false;
- notifyFillBufferDone(outHeader);
+ handleEOS();
return;
}
@@ -539,7 +568,6 @@
}
outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
- outHeader->nFlags = 0;
outHeader->nTimeStamp = mAnchorTimeUs +
(mNumFramesOutput * 1000000ll) /
@@ -548,22 +576,20 @@
mNumFramesOutput += numFrames;
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
- inHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ mHaveEOS = true;
} else {
- inInfo->mOwnedByUs = false;
- inQueue.erase(inQueue.begin());
- inInfo = NULL;
- notifyEmptyBufferDone(inHeader);
- inHeader = NULL;
+ outHeader->nFlags = 0;
}
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ notifyEmptyBufferDone(inHeader);
+ ++mInputBufferCount;
+
outInfo->mOwnedByUs = false;
outQueue.erase(outQueue.begin());
- outInfo = NULL;
notifyFillBufferDone(outHeader);
- outHeader = NULL;
-
- ++mInputBufferCount;
}
}
@@ -575,6 +601,7 @@
opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
mAnchorTimeUs = 0;
mSamplesToDiscard = mSeekPreRoll;
+ mHaveEOS = false;
}
}
@@ -591,6 +618,7 @@
}
mOutputPortSettingsChange = NONE;
+ mHaveEOS = false;
}
void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.h b/media/libstagefright/codecs/opus/dec/SoftOpus.h
index fab925d..91cafa1 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.h
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.h
@@ -75,6 +75,7 @@
int64_t mSamplesToDiscard;
int64_t mAnchorTimeUs;
int64_t mNumFramesOutput;
+ bool mHaveEOS;
enum {
NONE,
@@ -85,6 +86,7 @@
void initPorts();
status_t initDecoder();
bool isConfigured() const;
+ void handleEOS();
DISALLOW_EVIL_CONSTRUCTORS(SoftOpus);
};
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 96e01b6..8912f8a 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -309,7 +309,33 @@
oggpack_readinit(bits, ref);
}
-void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
+void SoftVorbis::handleEOS() {
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ CHECK(!inQueue.empty() && !outQueue.empty());
+
+ mSawInputEos = true;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ mSignalledOutputEos = true;
+
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+ ++mInputBufferCount;
+}
+
+void SoftVorbis::onQueueFilled(OMX_U32 /* portIndex */) {
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
@@ -317,69 +343,7 @@
return;
}
- if (portIndex == 0 && mInputBufferCount < 2) {
- BufferInfo *info = *inQueue.begin();
- OMX_BUFFERHEADERTYPE *header = info->mHeader;
-
- const uint8_t *data = header->pBuffer + header->nOffset;
- size_t size = header->nFilledLen;
- if (size < 7) {
- ALOGE("Too small input buffer: %zu bytes", size);
- android_errorWriteLog(0x534e4554, "27833616");
- notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- mSignalledError = true;
- return;
- }
-
- ogg_buffer buf;
- ogg_reference ref;
- oggpack_buffer bits;
-
- makeBitReader(
- (const uint8_t *)data + 7, size - 7,
- &buf, &ref, &bits);
-
- if (mInputBufferCount == 0) {
- CHECK(mVi == NULL);
- mVi = new vorbis_info;
- vorbis_info_init(mVi);
-
- int ret = _vorbis_unpack_info(mVi, &bits);
- if (ret != 0) {
- notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
- mSignalledError = true;
- return;
- }
- } else {
- int ret = _vorbis_unpack_books(mVi, &bits);
- if (ret != 0) {
- notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
- mSignalledError = true;
- return;
- }
-
- CHECK(mState == NULL);
- mState = new vorbis_dsp_state;
- CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
-
- if (mVi->rate != kDefaultSamplingRate ||
- mVi->channels != kDefaultChannelCount) {
- ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels);
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
- }
- }
-
- inQueue.erase(inQueue.begin());
- info->mOwnedByUs = false;
- notifyEmptyBufferDone(header);
-
- ++mInputBufferCount;
-
- return;
- }
-
- while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
+ while (!mSignalledOutputEos && (!inQueue.empty() || mSawInputEos) && !outQueue.empty()) {
BufferInfo *inInfo = NULL;
OMX_BUFFERHEADERTYPE *inHeader = NULL;
if (!inQueue.empty()) {
@@ -393,6 +357,73 @@
int32_t numPageSamples = 0;
if (inHeader) {
+ if (mInputBufferCount < 2) {
+ const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
+ size_t size = inHeader->nFilledLen;
+
+ if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && size == 0) {
+ handleEOS();
+ return;
+ }
+
+ if (size < 7) {
+ ALOGE("Too small input buffer: %zu bytes", size);
+ android_errorWriteLog(0x534e4554, "27833616");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ ogg_buffer buf;
+ ogg_reference ref;
+ oggpack_buffer bits;
+
+ makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits);
+
+ if (mInputBufferCount == 0) {
+ CHECK(mVi == NULL);
+ mVi = new vorbis_info;
+ vorbis_info_init(mVi);
+
+ int ret = _vorbis_unpack_info(mVi, &bits);
+ if (ret != 0) {
+ notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
+ mSignalledError = true;
+ return;
+ }
+ } else {
+ int ret = _vorbis_unpack_books(mVi, &bits);
+ if (ret != 0) {
+ notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ CHECK(mState == NULL);
+ mState = new vorbis_dsp_state;
+ CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
+
+ if (mVi->rate != kDefaultSamplingRate ||
+ mVi->channels != kDefaultChannelCount) {
+ ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels);
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ }
+ }
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ handleEOS();
+ return;
+ }
+
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+ ++mInputBufferCount;
+
+ continue;
+ }
+
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
mSawInputEos = true;
}
@@ -406,8 +437,7 @@
return;
}
memcpy(&numPageSamples,
- inHeader->pBuffer
- + inHeader->nOffset + inHeader->nFilledLen - 4,
+ inHeader->pBuffer + inHeader->nOffset + inHeader->nFilledLen - 4,
sizeof(numPageSamples));
if (inHeader->nOffset == 0) {
@@ -446,6 +476,14 @@
int numFrames = 0;
outHeader->nFlags = 0;
+
+ if (mState == nullptr || mVi == nullptr) {
+ notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
+ mSignalledError = true;
+ ALOGE("onQueueFilled, input does not have CSD");
+ return;
+ }
+
int err = vorbis_dsp_synthesis(mState, &pack, 1);
if (err != 0) {
// FIXME temporary workaround for log spam
@@ -495,18 +533,13 @@
if (inHeader) {
inInfo->mOwnedByUs = false;
inQueue.erase(inQueue.begin());
- inInfo = NULL;
notifyEmptyBufferDone(inHeader);
- inHeader = NULL;
+ ++mInputBufferCount;
}
outInfo->mOwnedByUs = false;
outQueue.erase(outQueue.begin());
- outInfo = NULL;
notifyFillBufferDone(outHeader);
- outHeader = NULL;
-
- ++mInputBufferCount;
}
}
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
index 52d1632..5ff8ea4 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
@@ -72,6 +72,7 @@
void initPorts();
status_t initDecoder();
bool isConfigured() const;
+ void handleEOS();
DISALLOW_EVIL_CONSTRUCTORS(SoftVorbis);
};
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index ce164a2..a127843 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -34,20 +34,21 @@
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.h264.decoder" type="video/avc">
- <!-- profiles and levels: ProfileHigh : Level41 -->
- <Limit name="size" min="16x16" max="1920x1088" />
+ <!-- profiles and levels: ProfileHigh : Level52 -->
+ <Limit name="size" min="2x2" max="4096x4096" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" range="1-244800" />
- <Limit name="bitrate" range="1-12000000" />
+ <Limit name="block-count" range="1-32768" /> <!-- max 4096x2048 -->
+ <Limit name="blocks-per-second" range="1-1966080" />
+ <Limit name="bitrate" range="1-48000000" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.hevc.decoder" type="video/hevc">
<!-- profiles and levels: ProfileMain : MainTierLevel51 -->
- <Limit name="size" min="2x2" max="2048x2048" />
+ <Limit name="size" min="2x2" max="4096x4096" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="8x8" />
- <Limit name="block-count" range="1-139264" />
+ <Limit name="block-count" range="1-196608" /> <!-- max 4096x3072 -->
<Limit name="blocks-per-second" range="1-2000000" />
<Limit name="bitrate" range="1-10000000" />
<Feature name="adaptive-playback" />
@@ -56,6 +57,7 @@
<Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
+ <Limit name="block-count" range="1-16384" />
<Limit name="blocks-per-second" range="1-1000000" />
<Limit name="bitrate" range="1-40000000" />
<Feature name="adaptive-playback" />
@@ -64,6 +66,7 @@
<Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
+ <Limit name="block-count" range="1-16384" />
<Limit name="blocks-per-second" range="1-500000" />
<Limit name="bitrate" range="1-40000000" />
<Feature name="adaptive-playback" />
@@ -79,10 +82,11 @@
</MediaCodec>
<MediaCodec name="OMX.google.h264.encoder" type="video/avc">
<!-- profiles and levels: ProfileBaseline : Level41 -->
- <Limit name="size" min="16x16" max="1920x1088" />
+ <Limit name="size" min="16x16" max="2048x2048" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" range="1-244800" />
+ <Limit name="block-count" range="1-8192" /> <!-- max 2048x1024 -->
+ <Limit name="blocks-per-second" range="1-245760" />
<Limit name="bitrate" range="1-12000000" />
<Feature name="intra-refresh" />
</MediaCodec>
@@ -98,6 +102,9 @@
<!-- profiles and levels: ProfileMain : Level_Version0-3 -->
<Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <!-- 2016 devices can encode at about 10fps at this block count -->
+ <Limit name="block-count" range="1-16384" />
<Limit name="bitrate" range="1-40000000" />
<Feature name="bitrate-modes" value="VBR,CBR" />
</MediaCodec>
@@ -105,6 +112,9 @@
<!-- profiles and levels: ProfileMain : Level_Version0-3 -->
<Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <!-- 2016 devices can encode at about 8fps at this block count -->
+ <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
<Limit name="bitrate" range="1-40000000" />
<Feature name="bitrate-modes" value="VBR,CBR" />
</MediaCodec>
diff --git a/media/libstagefright/data/media_codecs_google_video_le.xml b/media/libstagefright/data/media_codecs_google_video_le.xml
index 034a038..d7c6570 100644
--- a/media/libstagefright/data/media_codecs_google_video_le.xml
+++ b/media/libstagefright/data/media_codecs_google_video_le.xml
@@ -34,22 +34,22 @@
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.h264.decoder" type="video/avc">
- <!-- profiles and levels: ProfileBaseline : Level51 -->
+ <!-- profiles and levels: ProfileHigh : Level51 -->
<Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-8160" />
- <Limit name="blocks-per-second" range="1-489600" />
+ <Limit name="block-count" range="1-16384" />
+ <Limit name="blocks-per-second" range="1-491520" />
<Limit name="bitrate" range="1-40000000" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.hevc.decoder" type="video/hevc">
<!-- profiles and levels: ProfileMain : MainTierLevel51 -->
- <Limit name="size" min="2x2" max="1280x1280" />
+ <Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="8x8" />
- <Limit name="block-count" range="1-139264" />
- <Limit name="blocks-per-second" range="1-432000" />
+ <Limit name="block-count" range="1-65536" />
+ <Limit name="blocks-per-second" range="1-491520" />
<Limit name="bitrate" range="1-5000000" />
<Feature name="adaptive-playback" />
</MediaCodec>
@@ -57,7 +57,7 @@
<Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-8160" />
+ <Limit name="block-count" range="1-8192" /> <!-- max 2048x1024 -->
<Limit name="blocks-per-second" range="1-500000" />
<Limit name="bitrate" range="1-40000000" />
<Feature name="adaptive-playback" />
@@ -66,7 +66,7 @@
<Limit name="size" min="2x2" max="1280x1280" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-3600" />
+ <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
<Limit name="blocks-per-second" range="1-108000" />
<Limit name="bitrate" range="1-5000000" />
<Feature name="adaptive-playback" />
@@ -81,12 +81,14 @@
<Limit name="bitrate" range="1-128000" />
</MediaCodec>
<MediaCodec name="OMX.google.h264.encoder" type="video/avc">
- <!-- profiles and levels: ProfileBaseline : Level2 -->
- <Limit name="size" min="16x16" max="896x896" />
- <Limit name="alignment" value="16x16" />
+ <!-- profiles and levels: ProfileBaseline : Level3 -->
+ <Limit name="size" min="16x16" max="1808x1808" />
+ <Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" range="1-11880" />
+ <Limit name="block-count" range="1-1620" />
+ <Limit name="blocks-per-second" range="1-40500" />
<Limit name="bitrate" range="1-2000000" />
+ <Feature name="intra-refresh" />
</MediaCodec>
<MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es">
<!-- profiles and levels: ProfileCore : Level2 -->
@@ -100,7 +102,8 @@
<!-- profiles and levels: ProfileMain : Level_Version0-3 -->
<Limit name="size" min="2x2" max="1280x1280" />
<Limit name="alignment" value="2x2" />
- <Limit name="block-count" range="1-3600" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
<Limit name="bitrate" range="1-20000000" />
<Feature name="bitrate-modes" value="VBR,CBR" />
</MediaCodec>
diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp
index 7da7db9..cc89064 100644
--- a/media/libstagefright/foundation/base64.cpp
+++ b/media/libstagefright/foundation/base64.cpp
@@ -78,8 +78,7 @@
accum = (accum << 6) | value;
if (((i + 1) % 4) == 0) {
- out[j++] = (accum >> 16);
-
+ if (j < outLen) { out[j++] = (accum >> 16); }
if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
if (j < outLen) { out[j++] = accum & 0xff; }
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index 09e6d75..87c2411 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -213,6 +213,13 @@
Mutex::Autolock autoLock(mLock);
CHECK_LT(portIndex, mPorts.size());
+ PortInfo *port = &mPorts.editItemAt(portIndex);
+ if (size < port->mDef.nBufferSize) {
+ ALOGE("b/63522430, Buffer size is too small.");
+ android_errorWriteLog(0x534e4554, "63522430");
+ return OMX_ErrorBadParameter;
+ }
+
*header = new OMX_BUFFERHEADERTYPE;
(*header)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
(*header)->nVersion.s.nVersionMajor = 1;
@@ -235,8 +242,6 @@
(*header)->nOutputPortIndex = portIndex;
(*header)->nInputPortIndex = portIndex;
- PortInfo *port = &mPorts.editItemAt(portIndex);
-
CHECK(mState == OMX_StateLoaded || port->mDef.bEnabled == OMX_FALSE);
CHECK_LT(port->mBuffers.size(), port->mDef.nBufferCountActual);
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 23fd7ab..4132fed 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -724,7 +724,7 @@
char *temp = new char[me.length];
memcpy(temp, me.data, me.length);
me.data = temp;
- std::thread t([&me](MtpFfsHandle *h) { return h->doSendEvent(me); }, this);
+ std::thread t([this, me]() { return this->doSendEvent(me); });
t.detach();
return 0;
}
@@ -732,9 +732,9 @@
void MtpFfsHandle::doSendEvent(mtp_event me) {
unsigned length = me.length;
int ret = ::write(mIntr, me.data, length);
- delete[] reinterpret_cast<char*>(me.data);
if (static_cast<unsigned>(ret) != length)
PLOG(ERROR) << "Mtp error sending event thread!";
+ delete[] reinterpret_cast<char*>(me.data);
}
} // namespace android
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 40974f3..0d48de1 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -90,3 +90,9 @@
},
},
}
+
+llndk_library {
+ name: "libmediandk",
+ symbol_file: "libmediandk.map.txt",
+ export_include_dirs: ["include"],
+}
diff --git a/media/ndk/OWNERS b/media/ndk/OWNERS
new file mode 100644
index 0000000..43e4bb3
--- /dev/null
+++ b/media/ndk/OWNERS
@@ -0,0 +1 @@
+marcone@google.com
diff --git a/media/utils/OWNERS b/media/utils/OWNERS
new file mode 100644
index 0000000..f9cb567
--- /dev/null
+++ b/media/utils/OWNERS
@@ -0,0 +1 @@
+gkasten@google.com
diff --git a/services/OWNERS b/services/OWNERS
index d500dce..d5d00da 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -1,4 +1,4 @@
elaurent@google.com
etalvala@google.com
-gkasten@android.com
+gkasten@google.com
hunga@google.com
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
old mode 100644
new mode 100755
index d6d8dde..4981ce7
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -396,7 +396,7 @@
}
// Read JFIF segment markers, skip over segment data
- size = 0;
+ size = MARKER_LENGTH; //jump SOI;
while (size <= maxSize - MARKER_LENGTH) {
segment_t *segment = (segment_t*)(jpegBuffer + size);
uint8_t type = checkJpegMarker(segment->marker);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index fc5a28e..6fd9263 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -570,7 +570,7 @@
/*out*/
int* newStreamId) {
int width, height, format, surfaceType;
- int32_t consumerUsage;
+ uint64_t consumerUsage;
android_dataspace dataSpace;
status_t err;
binder::Status res;
@@ -766,24 +766,23 @@
// Query consumer usage bits to set async operation mode for
// GLConsumer using controlledByApp parameter.
bool useAsync = false;
- int32_t consumerUsage;
+ uint64_t consumerUsage = 0;
status_t err;
- if ((err = gbp->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
- &consumerUsage)) != OK) {
+ if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
mCameraIdStr.string(), strerror(-err), err);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
}
if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
- ALOGW("%s: Camera %s with consumer usage flag: 0x%x: Forcing asynchronous mode for stream",
+ ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for stream",
__FUNCTION__, mCameraIdStr.string(), consumerUsage);
useAsync = true;
}
- int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
+ uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
GRALLOC_USAGE_RENDERSCRIPT;
- int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
+ uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
GraphicBuffer::USAGE_HW_TEXTURE |
GraphicBuffer::USAGE_HW_COMPOSER;
bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
@@ -876,7 +875,7 @@
//surface class type. Use usage flag to approximate the comparison.
if (consumerUsage != streamInfo.consumerUsage) {
String8 msg = String8::format(
- "Camera %s:Surface usage flag doesn't match 0x%x vs 0x%x",
+ "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index e8fc080..50661cb 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -213,13 +213,13 @@
int height;
int format;
android_dataspace dataSpace;
- int32_t consumerUsage;
+ uint64_t consumerUsage;
bool finalized = false;
OutputStreamInfo() :
width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
consumerUsage(0) {}
OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
- int32_t _consumerUsage) :
+ uint64_t _consumerUsage) :
width(_width), height(_height), format(_format),
dataSpace(_dataSpace), consumerUsage(_consumerUsage) {}
};
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index d9059f3..54fcb0a 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -119,7 +119,7 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint32_t consumerUsage = 0) = 0;
+ bool isShared = false, uint64_t consumerUsage = 0) = 0;
/**
* Create an output stream of the requested size, format, rotation and
@@ -132,7 +132,7 @@
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint32_t consumerUsage = 0) = 0;
+ bool isShared = false, uint64_t consumerUsage = 0) = 0;
/**
* Create an input stream of width, height, and format.
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 469c86c..991b50f 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -29,11 +29,6 @@
CameraHardwareInterface::~CameraHardwareInterface()
{
ALOGI("Destroying camera %s", mName.string());
- if (mDevice) {
- int rc = mDevice->common.close(&mDevice->common);
- if (rc != OK)
- ALOGE("Could not close camera %s: %d", mName.string(), rc);
- }
if (mHidlDevice != nullptr) {
mHidlDevice->close();
mHidlDevice.clear();
@@ -42,12 +37,6 @@
}
status_t CameraHardwareInterface::initialize(sp<CameraProviderManager> manager) {
- if (mDevice) {
- ALOGE("%s: camera hardware interface has been initialized to libhardware path!",
- __FUNCTION__);
- return INVALID_OPERATION;
- }
-
ALOGI("Opening camera %s", mName.string());
status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
@@ -372,7 +361,7 @@
ALOGE("%s: preview window is null", __FUNCTION__);
return s;
}
- mPreviewUsage = (int) usage;
+ mPreviewUsage = static_cast<uint64_t> (usage);
int rc = native_window_set_usage(a, mPreviewUsage);
if (rc == OK) {
cleanupCirculatingBuffers();
@@ -444,23 +433,6 @@
}
return CameraProviderManager::mapToStatusT(
mHidlDevice->setPreviewWindow(buf.get() ? this : nullptr));
- } else if (mDevice) {
- if (mDevice->ops->set_preview_window) {
- mPreviewWindow = buf;
- if (buf != nullptr) {
- if (mPreviewScalingMode != NOT_SET) {
- setPreviewScalingMode(mPreviewScalingMode);
- }
- if (mPreviewTransform != NOT_SET) {
- setPreviewTransform(mPreviewTransform);
- }
- }
- mHalPreviewWindow.user = this;
- ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p",__FUNCTION__,
- &mHalPreviewWindow, mHalPreviewWindow.user);
- return mDevice->ops->set_preview_window(mDevice,
- buf.get() ? &mHalPreviewWindow.nw : 0);
- }
}
return INVALID_OPERATION;
}
@@ -478,15 +450,6 @@
mCbUser = user;
ALOGV("%s(%s)", __FUNCTION__, mName.string());
-
- if (mDevice && mDevice->ops->set_callbacks) {
- mDevice->ops->set_callbacks(mDevice,
- sNotifyCb,
- sDataCb,
- sDataCbTimestamp,
- sGetMemory,
- this);
- }
}
void CameraHardwareInterface::enableMsgType(int32_t msgType)
@@ -494,8 +457,6 @@
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (CC_LIKELY(mHidlDevice != nullptr)) {
mHidlDevice->enableMsgType(msgType);
- } else if (mDevice && mDevice->ops->enable_msg_type) {
- mDevice->ops->enable_msg_type(mDevice, msgType);
}
}
@@ -504,8 +465,6 @@
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (CC_LIKELY(mHidlDevice != nullptr)) {
mHidlDevice->disableMsgType(msgType);
- } else if (mDevice && mDevice->ops->disable_msg_type) {
- mDevice->ops->disable_msg_type(mDevice, msgType);
}
}
@@ -514,8 +473,6 @@
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (CC_LIKELY(mHidlDevice != nullptr)) {
return mHidlDevice->msgTypeEnabled(msgType);
- } else if (mDevice && mDevice->ops->msg_type_enabled) {
- return mDevice->ops->msg_type_enabled(mDevice, msgType);
}
return false;
}
@@ -526,8 +483,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->startPreview());
- } else if (mDevice && mDevice->ops->start_preview) {
- return mDevice->ops->start_preview(mDevice);
}
return INVALID_OPERATION;
}
@@ -537,8 +492,6 @@
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (CC_LIKELY(mHidlDevice != nullptr)) {
mHidlDevice->stopPreview();
- } else if (mDevice && mDevice->ops->stop_preview) {
- mDevice->ops->stop_preview(mDevice);
}
}
@@ -547,8 +500,6 @@
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (CC_LIKELY(mHidlDevice != nullptr)) {
return mHidlDevice->previewEnabled();
- } else if (mDevice && mDevice->ops->preview_enabled) {
- return mDevice->ops->preview_enabled(mDevice);
}
return false;
}
@@ -559,8 +510,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->storeMetaDataInBuffers(enable));
- } else if (mDevice && mDevice->ops->store_meta_data_in_buffers) {
- return mDevice->ops->store_meta_data_in_buffers(mDevice, enable);
}
return enable ? INVALID_OPERATION: OK;
}
@@ -571,8 +520,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->startRecording());
- } else if (mDevice && mDevice->ops->start_recording) {
- return mDevice->ops->start_recording(mDevice);
}
return INVALID_OPERATION;
}
@@ -585,8 +532,6 @@
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (CC_LIKELY(mHidlDevice != nullptr)) {
mHidlDevice->stopRecording();
- } else if (mDevice && mDevice->ops->stop_recording) {
- mDevice->ops->stop_recording(mDevice);
}
}
@@ -598,8 +543,6 @@
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (CC_LIKELY(mHidlDevice != nullptr)) {
return mHidlDevice->recordingEnabled();
- } else if (mDevice && mDevice->ops->recording_enabled) {
- return mDevice->ops->recording_enabled(mDevice);
}
return false;
}
@@ -624,9 +567,6 @@
} else {
mHidlDevice->releaseRecordingFrame(heapId, bufferIndex);
}
- } else if (mDevice && mDevice->ops->release_recording_frame) {
- void *data = ((uint8_t *)heap->base()) + offset;
- return mDevice->ops->release_recording_frame(mDevice, data);
}
}
@@ -653,9 +593,6 @@
ALOGE("%s only supports VideoNativeHandleMetadata mode", __FUNCTION__);
return;
}
- } else {
- ALOGE("Non HIDL mode do not support %s", __FUNCTION__);
- return;
}
}
@@ -674,8 +611,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->autoFocus());
- } else if (mDevice && mDevice->ops->auto_focus) {
- return mDevice->ops->auto_focus(mDevice);
}
return INVALID_OPERATION;
}
@@ -686,8 +621,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->cancelAutoFocus());
- } else if (mDevice && mDevice->ops->cancel_auto_focus) {
- return mDevice->ops->cancel_auto_focus(mDevice);
}
return INVALID_OPERATION;
}
@@ -698,8 +631,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->takePicture());
- } else if (mDevice && mDevice->ops->take_picture) {
- return mDevice->ops->take_picture(mDevice);
}
return INVALID_OPERATION;
}
@@ -710,8 +641,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->cancelPicture());
- } else if (mDevice && mDevice->ops->cancel_picture) {
- return mDevice->ops->cancel_picture(mDevice);
}
return INVALID_OPERATION;
}
@@ -722,8 +651,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->setParameters(params.flatten().string()));
- } else if (mDevice && mDevice->ops->set_parameters) {
- return mDevice->ops->set_parameters(mDevice, params.flatten().string());
}
return INVALID_OPERATION;
}
@@ -740,14 +667,6 @@
});
String8 tmp(outParam.c_str());
parms.unflatten(tmp);
- } else if (mDevice && mDevice->ops->get_parameters) {
- char *temp = mDevice->ops->get_parameters(mDevice);
- String8 str_parms(temp);
- if (mDevice->ops->put_parameters)
- mDevice->ops->put_parameters(mDevice, temp);
- else
- free(temp);
- parms.unflatten(str_parms);
}
return parms;
}
@@ -758,8 +677,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
return CameraProviderManager::mapToStatusT(
mHidlDevice->sendCommand((CommandType) cmd, arg1, arg2));
- } else if (mDevice && mDevice->ops->send_command) {
- return mDevice->ops->send_command(mDevice, cmd, arg1, arg2);
}
return INVALID_OPERATION;
}
@@ -773,8 +690,6 @@
if (CC_LIKELY(mHidlDevice != nullptr)) {
mHidlDevice->close();
mHidlDevice.clear();
- } else if (mDevice && mDevice->ops->release) {
- mDevice->ops->release(mDevice);
}
}
@@ -790,15 +705,10 @@
Status s = mHidlDevice->dumpState(handle);
native_handle_delete(handle);
return CameraProviderManager::mapToStatusT(s);
- } else if (mDevice && mDevice->ops->dump) {
- return mDevice->ops->dump(mDevice, fd);
}
return OK; // It's fine if the HAL doesn't implement dump()
}
-/**
- * Methods for legacy (non-HIDL) path follows
- */
void CameraHardwareInterface::sNotifyCb(int32_t msg_type, int32_t ext1,
int32_t ext2, void *user)
{
@@ -868,177 +778,4 @@
mem->decStrong(mem);
}
-ANativeWindow* CameraHardwareInterface::sToAnw(void *user)
-{
- CameraHardwareInterface *object =
- reinterpret_cast<CameraHardwareInterface *>(user);
- return object->mPreviewWindow.get();
-}
-#define anw(n) sToAnw(((struct camera_preview_window *)(n))->user)
-#define hwi(n) reinterpret_cast<CameraHardwareInterface *>(\
- ((struct camera_preview_window *)(n))->user)
-
-int CameraHardwareInterface::sDequeueBuffer(struct preview_stream_ops* w,
- buffer_handle_t** buffer, int *stride)
-{
- int rc;
- ANativeWindow *a = anw(w);
- ANativeWindowBuffer* anb;
- rc = native_window_dequeue_buffer_and_wait(a, &anb);
- if (rc == OK) {
- *buffer = &anb->handle;
- *stride = anb->stride;
- }
- return rc;
-}
-
-#ifndef container_of
-#define container_of(ptr, type, member) ({ \
- const __typeof__(((type *) 0)->member) *__mptr = (ptr); \
- (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
-#endif
-
-int CameraHardwareInterface::sLockBuffer(struct preview_stream_ops* w,
- buffer_handle_t* /*buffer*/)
-{
- ANativeWindow *a = anw(w);
- (void)a;
- return 0;
-}
-
-int CameraHardwareInterface::sEnqueueBuffer(struct preview_stream_ops* w,
- buffer_handle_t* buffer)
-{
- ANativeWindow *a = anw(w);
- return a->queueBuffer(a,
- container_of(buffer, ANativeWindowBuffer, handle), -1);
-}
-
-int CameraHardwareInterface::sCancelBuffer(struct preview_stream_ops* w,
- buffer_handle_t* buffer)
-{
- ANativeWindow *a = anw(w);
- return a->cancelBuffer(a,
- container_of(buffer, ANativeWindowBuffer, handle), -1);
-}
-
-int CameraHardwareInterface::sSetBufferCount(struct preview_stream_ops* w, int count)
-{
- ANativeWindow *a = anw(w);
-
- if (a != nullptr) {
- // Workaround for b/27039775
- // Previously, setting the buffer count would reset the buffer
- // queue's flag that allows for all buffers to be dequeued on the
- // producer side, instead of just the producer's declared max count,
- // if no filled buffers have yet been queued by the producer. This
- // reset no longer happens, but some HALs depend on this behavior,
- // so it needs to be maintained for HAL backwards compatibility.
- // Simulate the prior behavior by disconnecting/reconnecting to the
- // window and setting the values again. This has the drawback of
- // actually causing memory reallocation, which may not have happened
- // in the past.
- CameraHardwareInterface *hw = hwi(w);
- native_window_api_disconnect(a, NATIVE_WINDOW_API_CAMERA);
- native_window_api_connect(a, NATIVE_WINDOW_API_CAMERA);
- if (hw->mPreviewScalingMode != NOT_SET) {
- native_window_set_scaling_mode(a, hw->mPreviewScalingMode);
- }
- if (hw->mPreviewTransform != NOT_SET) {
- native_window_set_buffers_transform(a, hw->mPreviewTransform);
- }
- if (hw->mPreviewWidth != NOT_SET) {
- native_window_set_buffers_dimensions(a,
- hw->mPreviewWidth, hw->mPreviewHeight);
- native_window_set_buffers_format(a, hw->mPreviewFormat);
- }
- if (hw->mPreviewUsage != 0) {
- native_window_set_usage(a, hw->mPreviewUsage);
- }
- if (hw->mPreviewSwapInterval != NOT_SET) {
- a->setSwapInterval(a, hw->mPreviewSwapInterval);
- }
- if (hw->mPreviewCrop.left != NOT_SET) {
- native_window_set_crop(a, &(hw->mPreviewCrop));
- }
- }
-
- return native_window_set_buffer_count(a, count);
-}
-
-int CameraHardwareInterface::sSetBuffersGeometry(struct preview_stream_ops* w,
- int width, int height, int format)
-{
- int rc;
- ANativeWindow *a = anw(w);
- CameraHardwareInterface *hw = hwi(w);
- hw->mPreviewWidth = width;
- hw->mPreviewHeight = height;
- hw->mPreviewFormat = format;
- rc = native_window_set_buffers_dimensions(a, width, height);
- if (rc == OK) {
- rc = native_window_set_buffers_format(a, format);
- }
- return rc;
-}
-
-int CameraHardwareInterface::sSetCrop(struct preview_stream_ops *w,
- int left, int top, int right, int bottom)
-{
- ANativeWindow *a = anw(w);
- CameraHardwareInterface *hw = hwi(w);
- hw->mPreviewCrop.left = left;
- hw->mPreviewCrop.top = top;
- hw->mPreviewCrop.right = right;
- hw->mPreviewCrop.bottom = bottom;
- return native_window_set_crop(a, &(hw->mPreviewCrop));
-}
-
-int CameraHardwareInterface::sSetTimestamp(struct preview_stream_ops *w,
- int64_t timestamp) {
- ANativeWindow *a = anw(w);
- return native_window_set_buffers_timestamp(a, timestamp);
-}
-
-int CameraHardwareInterface::sSetUsage(struct preview_stream_ops* w, int usage)
-{
- ANativeWindow *a = anw(w);
- CameraHardwareInterface *hw = hwi(w);
- hw->mPreviewUsage = usage;
- return native_window_set_usage(a, usage);
-}
-
-int CameraHardwareInterface::sSetSwapInterval(struct preview_stream_ops *w, int interval)
-{
- ANativeWindow *a = anw(w);
- CameraHardwareInterface *hw = hwi(w);
- hw->mPreviewSwapInterval = interval;
- return a->setSwapInterval(a, interval);
-}
-
-int CameraHardwareInterface::sGetMinUndequeuedBufferCount(
- const struct preview_stream_ops *w,
- int *count)
-{
- ANativeWindow *a = anw(w);
- return a->query(a, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, count);
-}
-
-void CameraHardwareInterface::initHalPreviewWindow()
-{
- mHalPreviewWindow.nw.cancel_buffer = sCancelBuffer;
- mHalPreviewWindow.nw.lock_buffer = sLockBuffer;
- mHalPreviewWindow.nw.dequeue_buffer = sDequeueBuffer;
- mHalPreviewWindow.nw.enqueue_buffer = sEnqueueBuffer;
- mHalPreviewWindow.nw.set_buffer_count = sSetBufferCount;
- mHalPreviewWindow.nw.set_buffers_geometry = sSetBuffersGeometry;
- mHalPreviewWindow.nw.set_crop = sSetCrop;
- mHalPreviewWindow.nw.set_timestamp = sSetTimestamp;
- mHalPreviewWindow.nw.set_usage = sSetUsage;
- mHalPreviewWindow.nw.set_swap_interval = sSetSwapInterval;
-
- mHalPreviewWindow.nw.get_min_undequeued_buffer_count =
- sGetMinUndequeuedBufferCount;
-}
-
}; // namespace android
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 1c38d00..6a1b4fb 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -90,7 +90,6 @@
public:
explicit CameraHardwareInterface(const char *name):
- mDevice(nullptr),
mHidlDevice(nullptr),
mName(name),
mPreviewScalingMode(NOT_SET),
@@ -299,7 +298,6 @@
status_t dump(int fd, const Vector<String16>& /*args*/) const;
private:
- camera_device_t *mDevice;
sp<hardware::camera::device::V1_0::ICameraDevice> mHidlDevice;
String8 mName;
@@ -369,41 +367,6 @@
static void sPutMemory(camera_memory_t *data);
- static ANativeWindow *sToAnw(void *user);
-
- static int sDequeueBuffer(struct preview_stream_ops* w,
- buffer_handle_t** buffer, int *stride);
-
- static int sLockBuffer(struct preview_stream_ops* w,
- buffer_handle_t* /*buffer*/);
-
- static int sEnqueueBuffer(struct preview_stream_ops* w,
- buffer_handle_t* buffer);
-
- static int sCancelBuffer(struct preview_stream_ops* w,
- buffer_handle_t* buffer);
-
- static int sSetBufferCount(struct preview_stream_ops* w, int count);
-
- static int sSetBuffersGeometry(struct preview_stream_ops* w,
- int width, int height, int format);
-
- static int sSetCrop(struct preview_stream_ops *w,
- int left, int top, int right, int bottom);
-
- static int sSetTimestamp(struct preview_stream_ops *w,
- int64_t timestamp);
-
- static int sSetUsage(struct preview_stream_ops* w, int usage);
-
- static int sSetSwapInterval(struct preview_stream_ops *w, int interval);
-
- static int sGetMinUndequeuedBufferCount(
- const struct preview_stream_ops *w,
- int *count);
-
- void initHalPreviewWindow();
-
std::pair<bool, uint64_t> getBufferId(ANativeWindowBuffer* anb);
void cleanupCirculatingBuffers();
@@ -459,13 +422,6 @@
sp<ANativeWindow> mPreviewWindow;
- struct camera_preview_window {
- struct preview_stream_ops nw;
- void *user;
- };
-
- struct camera_preview_window mHalPreviewWindow;
-
notify_callback mNotifyCb;
data_callback mDataCb;
data_callback_timestamp mDataCbTimestamp;
@@ -479,7 +435,7 @@
int mPreviewWidth;
int mPreviewHeight;
int mPreviewFormat;
- int mPreviewUsage;
+ uint64_t mPreviewUsage;
int mPreviewSwapInterval;
android_native_rect_t mPreviewCrop;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 89d2c65..02f5424 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -407,7 +407,7 @@
}
BufferUsageFlags Camera3Device::mapToConsumerUsage(
- uint32_t usage) {
+ uint64_t usage) {
return usage;
}
@@ -460,12 +460,12 @@
return static_cast<uint32_t>(pixelFormat);
}
-uint32_t Camera3Device::mapConsumerToFrameworkUsage(
+uint64_t Camera3Device::mapConsumerToFrameworkUsage(
BufferUsageFlags usage) {
return usage;
}
-uint32_t Camera3Device::mapProducerToFrameworkUsage(
+uint64_t Camera3Device::mapProducerToFrameworkUsage(
BufferUsageFlags usage) {
return usage;
}
@@ -1208,7 +1208,7 @@
status_t Camera3Device::createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
- int streamSetId, bool isShared, uint32_t consumerUsage) {
+ int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -1226,13 +1226,13 @@
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
- int streamSetId, bool isShared, uint32_t consumerUsage) {
+ int streamSetId, bool isShared, uint64_t consumerUsage) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Mutex::Autolock l(mLock);
ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
- " consumer usage 0x%x, isShared %d", mId.string(), mNextStreamId, width, height, format,
+ " consumer usage %" PRIu64 ", isShared %d", mId.string(), mNextStreamId, width, height, format,
dataSpace, rotation, consumerUsage, isShared);
status_t res;
@@ -3058,24 +3058,20 @@
Camera3Device::HalInterface::HalInterface(
sp<ICameraDeviceSession> &session,
std::shared_ptr<RequestMetadataQueue> queue) :
- mHal3Device(nullptr),
mHidlSession(session),
mRequestMetadataQueue(queue) {}
-Camera3Device::HalInterface::HalInterface() :
- mHal3Device(nullptr) {}
+Camera3Device::HalInterface::HalInterface() {}
Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
- mHal3Device(other.mHal3Device),
mHidlSession(other.mHidlSession),
mRequestMetadataQueue(other.mRequestMetadataQueue) {}
bool Camera3Device::HalInterface::valid() {
- return (mHal3Device != nullptr) || (mHidlSession != nullptr);
+ return (mHidlSession != nullptr);
}
void Camera3Device::HalInterface::clear() {
- mHal3Device = nullptr;
mHidlSession.clear();
}
@@ -3090,72 +3086,60 @@
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
- if (mHal3Device != nullptr) {
- const camera_metadata *r;
- r = mHal3Device->ops->construct_default_request_settings(
- mHal3Device, templateId);
- if (r == nullptr) return BAD_VALUE;
- *requestTemplate = clone_camera_metadata(r);
- if (requestTemplate == nullptr) {
- ALOGE("%s: Unable to clone camera metadata received from HAL",
- __FUNCTION__);
- return INVALID_OPERATION;
- }
- } else {
- common::V1_0::Status status;
- RequestTemplate id;
- switch (templateId) {
- case CAMERA3_TEMPLATE_PREVIEW:
- id = RequestTemplate::PREVIEW;
- break;
- case CAMERA3_TEMPLATE_STILL_CAPTURE:
- id = RequestTemplate::STILL_CAPTURE;
- break;
- case CAMERA3_TEMPLATE_VIDEO_RECORD:
- id = RequestTemplate::VIDEO_RECORD;
- break;
- case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
- id = RequestTemplate::VIDEO_SNAPSHOT;
- break;
- case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
- id = RequestTemplate::ZERO_SHUTTER_LAG;
- break;
- case CAMERA3_TEMPLATE_MANUAL:
- id = RequestTemplate::MANUAL;
- break;
- default:
- // Unknown template ID
- return BAD_VALUE;
- }
- auto err = mHidlSession->constructDefaultRequestSettings(id,
- [&status, &requestTemplate]
- (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
- status = s;
- if (status == common::V1_0::Status::OK) {
- const camera_metadata *r =
- reinterpret_cast<const camera_metadata_t*>(request.data());
- size_t expectedSize = request.size();
- int ret = validate_camera_metadata_structure(r, &expectedSize);
- if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
- *requestTemplate = clone_camera_metadata(r);
- if (*requestTemplate == nullptr) {
- ALOGE("%s: Unable to clone camera metadata received from HAL",
- __FUNCTION__);
- status = common::V1_0::Status::INTERNAL_ERROR;
- }
- } else {
- ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ common::V1_0::Status status;
+ RequestTemplate id;
+ switch (templateId) {
+ case CAMERA3_TEMPLATE_PREVIEW:
+ id = RequestTemplate::PREVIEW;
+ break;
+ case CAMERA3_TEMPLATE_STILL_CAPTURE:
+ id = RequestTemplate::STILL_CAPTURE;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_RECORD:
+ id = RequestTemplate::VIDEO_RECORD;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+ id = RequestTemplate::VIDEO_SNAPSHOT;
+ break;
+ case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+ id = RequestTemplate::ZERO_SHUTTER_LAG;
+ break;
+ case CAMERA3_TEMPLATE_MANUAL:
+ id = RequestTemplate::MANUAL;
+ break;
+ default:
+ // Unknown template ID
+ return BAD_VALUE;
+ }
+ auto err = mHidlSession->constructDefaultRequestSettings(id,
+ [&status, &requestTemplate]
+ (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
+ status = s;
+ if (status == common::V1_0::Status::OK) {
+ const camera_metadata *r =
+ reinterpret_cast<const camera_metadata_t*>(request.data());
+ size_t expectedSize = request.size();
+ int ret = validate_camera_metadata_structure(r, &expectedSize);
+ if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ *requestTemplate = clone_camera_metadata(r);
+ if (*requestTemplate == nullptr) {
+ ALOGE("%s: Unable to clone camera metadata received from HAL",
+ __FUNCTION__);
status = common::V1_0::Status::INTERNAL_ERROR;
}
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ status = common::V1_0::Status::INTERNAL_ERROR;
}
- });
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- res = DEAD_OBJECT;
- } else {
- res = CameraProviderManager::mapToStatusT(status);
- }
+ }
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ res = DEAD_OBJECT;
+ } else {
+ res = CameraProviderManager::mapToStatusT(status);
}
+
return res;
}
@@ -3164,138 +3148,137 @@
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
- if (mHal3Device != nullptr) {
- res = mHal3Device->ops->configure_streams(mHal3Device, config);
- } else {
- // Convert stream config to HIDL
- std::set<int> activeStreams;
- StreamConfiguration requestedConfiguration;
- requestedConfiguration.streams.resize(config->num_streams);
- for (size_t i = 0; i < config->num_streams; i++) {
- Stream &dst = requestedConfiguration.streams[i];
- camera3_stream_t *src = config->streams[i];
+ // Convert stream config to HIDL
+ std::set<int> activeStreams;
+ StreamConfiguration requestedConfiguration;
+ requestedConfiguration.streams.resize(config->num_streams);
+ for (size_t i = 0; i < config->num_streams; i++) {
+ Stream &dst = requestedConfiguration.streams[i];
+ camera3_stream_t *src = config->streams[i];
- Camera3Stream* cam3stream = Camera3Stream::cast(src);
- cam3stream->setBufferFreedListener(this);
- int streamId = cam3stream->getId();
- StreamType streamType;
- switch (src->stream_type) {
- case CAMERA3_STREAM_OUTPUT:
- streamType = StreamType::OUTPUT;
- break;
- case CAMERA3_STREAM_INPUT:
- streamType = StreamType::INPUT;
- break;
- default:
- ALOGE("%s: Stream %d: Unsupported stream type %d",
- __FUNCTION__, streamId, config->streams[i]->stream_type);
- return BAD_VALUE;
+ Camera3Stream* cam3stream = Camera3Stream::cast(src);
+ cam3stream->setBufferFreedListener(this);
+ int streamId = cam3stream->getId();
+ StreamType streamType;
+ switch (src->stream_type) {
+ case CAMERA3_STREAM_OUTPUT:
+ streamType = StreamType::OUTPUT;
+ break;
+ case CAMERA3_STREAM_INPUT:
+ streamType = StreamType::INPUT;
+ break;
+ default:
+ ALOGE("%s: Stream %d: Unsupported stream type %d",
+ __FUNCTION__, streamId, config->streams[i]->stream_type);
+ return BAD_VALUE;
+ }
+ dst.id = streamId;
+ dst.streamType = streamType;
+ dst.width = src->width;
+ dst.height = src->height;
+ dst.format = mapToPixelFormat(src->format);
+ dst.usage = mapToConsumerUsage(cam3stream->getUsage());
+ dst.dataSpace = mapToHidlDataspace(src->data_space);
+ dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+
+ activeStreams.insert(streamId);
+ // Create Buffer ID map if necessary
+ if (mBufferIdMaps.count(streamId) == 0) {
+ mBufferIdMaps.emplace(streamId, BufferIdMap{});
+ }
+ }
+ // remove BufferIdMap for deleted streams
+ for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
+ int streamId = it->first;
+ bool active = activeStreams.count(streamId) > 0;
+ if (!active) {
+ it = mBufferIdMaps.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ res = mapToStreamConfigurationMode(
+ (camera3_stream_configuration_mode_t) config->operation_mode,
+ /*out*/ &requestedConfiguration.operationMode);
+ if (res != OK) {
+ return res;
+ }
+
+ // Invoke configureStreams
+
+ HalStreamConfiguration finalConfiguration;
+ common::V1_0::Status status;
+ auto err = mHidlSession->configureStreams(requestedConfiguration,
+ [&status, &finalConfiguration]
+ (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
+ finalConfiguration = halConfiguration;
+ status = s;
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ if (status != common::V1_0::Status::OK ) {
+ return CameraProviderManager::mapToStatusT(status);
+ }
+
+ // And convert output stream configuration from HIDL
+
+ for (size_t i = 0; i < config->num_streams; i++) {
+ camera3_stream_t *dst = config->streams[i];
+ int streamId = Camera3Stream::cast(dst)->getId();
+
+ // Start scan at i, with the assumption that the stream order matches
+ size_t realIdx = i;
+ bool found = false;
+ for (size_t idx = 0; idx < finalConfiguration.streams.size(); idx++) {
+ if (finalConfiguration.streams[realIdx].id == streamId) {
+ found = true;
+ break;
}
- dst.id = streamId;
- dst.streamType = streamType;
- dst.width = src->width;
- dst.height = src->height;
- dst.format = mapToPixelFormat(src->format);
- dst.usage = mapToConsumerUsage(src->usage);
- dst.dataSpace = mapToHidlDataspace(src->data_space);
- dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+ realIdx = (realIdx >= finalConfiguration.streams.size()) ? 0 : realIdx + 1;
+ }
+ if (!found) {
+ ALOGE("%s: Stream %d not found in stream configuration response from HAL",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
+ }
+ HalStream &src = finalConfiguration.streams[realIdx];
- activeStreams.insert(streamId);
- // Create Buffer ID map if necessary
- if (mBufferIdMaps.count(streamId) == 0) {
- mBufferIdMaps.emplace(streamId, BufferIdMap{});
+ int overrideFormat = mapToFrameworkFormat(src.overrideFormat);
+ if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ if (dst->format != overrideFormat) {
+ ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
+ streamId, dst->format);
}
- }
- // remove BufferIdMap for deleted streams
- for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
- int streamId = it->first;
- bool active = activeStreams.count(streamId) > 0;
- if (!active) {
- it = mBufferIdMaps.erase(it);
- } else {
- ++it;
- }
+ } else {
+ // Override allowed with IMPLEMENTATION_DEFINED
+ dst->format = overrideFormat;
}
- res = mapToStreamConfigurationMode(
- (camera3_stream_configuration_mode_t) config->operation_mode,
- /*out*/ &requestedConfiguration.operationMode);
- if (res != OK) {
- return res;
- }
-
- // Invoke configureStreams
-
- HalStreamConfiguration finalConfiguration;
- common::V1_0::Status status;
- auto err = mHidlSession->configureStreams(requestedConfiguration,
- [&status, &finalConfiguration]
- (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
- finalConfiguration = halConfiguration;
- status = s;
- });
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
-
- if (status != common::V1_0::Status::OK ) {
- return CameraProviderManager::mapToStatusT(status);
- }
-
- // And convert output stream configuration from HIDL
-
- for (size_t i = 0; i < config->num_streams; i++) {
- camera3_stream_t *dst = config->streams[i];
- int streamId = Camera3Stream::cast(dst)->getId();
-
- // Start scan at i, with the assumption that the stream order matches
- size_t realIdx = i;
- bool found = false;
- for (size_t idx = 0; idx < finalConfiguration.streams.size(); idx++) {
- if (finalConfiguration.streams[realIdx].id == streamId) {
- found = true;
- break;
- }
- realIdx = (realIdx >= finalConfiguration.streams.size()) ? 0 : realIdx + 1;
- }
- if (!found) {
- ALOGE("%s: Stream %d not found in stream configuration response from HAL",
+ if (dst->stream_type == CAMERA3_STREAM_INPUT) {
+ if (src.producerUsage != 0) {
+ ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
__FUNCTION__, streamId);
return INVALID_OPERATION;
}
- HalStream &src = finalConfiguration.streams[realIdx];
-
- int overrideFormat = mapToFrameworkFormat(src.overrideFormat);
- if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
- if (dst->format != overrideFormat) {
- ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
- streamId, dst->format);
- }
- } else {
- // Override allowed with IMPLEMENTATION_DEFINED
- dst->format = overrideFormat;
+ Camera3Stream::cast(dst)->setUsage(
+ mapConsumerToFrameworkUsage(src.consumerUsage));
+ } else {
+ // OUTPUT
+ if (src.consumerUsage != 0) {
+ ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
}
-
- if (dst->stream_type == CAMERA3_STREAM_INPUT) {
- if (src.producerUsage != 0) {
- ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- dst->usage = mapConsumerToFrameworkUsage(src.consumerUsage);
- } else {
- // OUTPUT
- if (src.consumerUsage != 0) {
- ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- dst->usage = mapProducerToFrameworkUsage(src.producerUsage);
- }
- dst->max_buffers = src.maxBuffers;
+ Camera3Stream::cast(dst)->setUsage(
+ mapProducerToFrameworkUsage(src.producerUsage));
}
+ dst->max_buffers = src.maxBuffers;
}
+
return res;
}
@@ -3451,14 +3434,11 @@
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
- if (mHal3Device != nullptr) {
- res = mHal3Device->ops->process_capture_request(mHal3Device, request);
- } else {
- uint32_t numRequestProcessed = 0;
- std::vector<camera3_capture_request_t*> requests(1);
- requests[0] = request;
- res = processBatchCaptureRequests(requests, &numRequestProcessed);
- }
+ uint32_t numRequestProcessed = 0;
+ std::vector<camera3_capture_request_t*> requests(1);
+ requests[0] = request;
+ res = processBatchCaptureRequests(requests, &numRequestProcessed);
+
return res;
}
@@ -3467,31 +3447,24 @@
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
- if (mHal3Device != nullptr) {
- res = mHal3Device->ops->flush(mHal3Device);
+ auto err = mHidlSession->flush();
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ res = DEAD_OBJECT;
} else {
- auto err = mHidlSession->flush();
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- res = DEAD_OBJECT;
- } else {
- res = CameraProviderManager::mapToStatusT(err);
- }
+ res = CameraProviderManager::mapToStatusT(err);
}
+
return res;
}
-status_t Camera3Device::HalInterface::dump(int fd) {
+status_t Camera3Device::HalInterface::dump(int /*fd*/) {
ATRACE_NAME("CameraHal::dump");
if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
- if (mHal3Device != nullptr) {
- mHal3Device->ops->dump(mHal3Device, fd);
- } else {
- // Handled by CameraProviderManager::dump
- }
- return res;
+ // Handled by CameraProviderManager::dump
+
+ return OK;
}
status_t Camera3Device::HalInterface::close() {
@@ -3499,15 +3472,12 @@
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
- if (mHal3Device != nullptr) {
- mHal3Device->common.close(&mHal3Device->common);
- } else {
- auto err = mHidlSession->close();
- // Interface will be dead shortly anyway, so don't log errors
- if (!err.isOk()) {
- res = DEAD_OBJECT;
- }
+ auto err = mHidlSession->close();
+ // Interface will be dead shortly anyway, so don't log errors
+ if (!err.isOk()) {
+ res = DEAD_OBJECT;
}
+
return res;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d700e03..b5f19d7 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -117,12 +117,12 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint32_t consumerUsage = 0) override;
+ bool isShared = false, uint64_t consumerUsage = 0) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint32_t consumerUsage = 0) override;
+ bool isShared = false, uint64_t consumerUsage = 0) override;
status_t createInputStream(
uint32_t width, uint32_t height, int format,
@@ -271,7 +271,6 @@
void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out);
private:
- camera3_device_t *mHal3Device;
sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
@@ -590,7 +589,7 @@
static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
android_dataspace dataSpace);
- static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint32_t usage);
+ static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
camera3_stream_rotation_t rotation);
// Returns a negative error code if the passed-in operation mode is not valid.
@@ -598,9 +597,9 @@
/*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
- static uint32_t mapConsumerToFrameworkUsage(
+ static uint64_t mapConsumerToFrameworkUsage(
hardware::camera::device::V3_2::BufferUsageFlags usage);
- static uint32_t mapProducerToFrameworkUsage(
+ static uint64_t mapProducerToFrameworkUsage(
hardware::camera::device::V3_2::BufferUsageFlags usage);
struct RequestTrigger {
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 9c951b7..6e2978f 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -95,7 +95,7 @@
return OK;
}
-status_t Camera3DummyStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3DummyStream::getEndpointUsage(uint64_t *usage) const {
*usage = DUMMY_USAGE;
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 35a6a18..492fb49 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -94,7 +94,7 @@
static const int DUMMY_FORMAT = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
static const android_dataspace DUMMY_DATASPACE = HAL_DATASPACE_UNKNOWN;
static const camera3_stream_rotation_t DUMMY_ROTATION = CAMERA3_STREAM_ROTATION_0;
- static const uint32_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
+ static const uint64_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
/**
* Internal Camera3Stream interface
@@ -107,7 +107,7 @@
virtual status_t configureQueueLocked();
- virtual status_t getEndpointUsage(uint32_t *usage) const;
+ virtual status_t getEndpointUsage(uint64_t *usage) const;
}; // class Camera3DummyStream
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index 7ad2300..a52422d 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -69,7 +69,7 @@
(void) args;
String8 lines;
- uint32_t consumerUsage = 0;
+ uint64_t consumerUsage = 0;
status_t res = getEndpointUsage(&consumerUsage);
if (res != OK) consumerUsage = 0;
@@ -78,8 +78,8 @@
camera3_stream::width, camera3_stream::height,
camera3_stream::format, camera3_stream::data_space);
lines.appendFormat(" Max size: %zu\n", mMaxSize);
- lines.appendFormat(" Combined usage: %d, max HAL buffers: %d\n",
- camera3_stream::usage | consumerUsage, camera3_stream::max_buffers);
+ lines.appendFormat(" Combined usage: %" PRIu64 ", max HAL buffers: %d\n",
+ mUsage | consumerUsage, camera3_stream::max_buffers);
lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n",
mFrameCount, mLastTimestamp);
lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n",
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 35dda39..2376058 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -85,7 +85,7 @@
virtual size_t getHandoutInputBufferCountLocked();
- virtual status_t getEndpointUsage(uint32_t *usage) const = 0;
+ virtual status_t getEndpointUsage(uint64_t *usage) const = 0;
status_t getBufferPreconditionCheckLocked() const;
status_t returnBufferPreconditionCheckLocked() const;
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index ff2dcef..2cb1ea7 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -258,7 +258,7 @@
camera3_stream::max_buffers : minBufs;
// TODO: somehow set the total buffer count when producer connects?
- mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage,
+ mConsumer = new BufferItemConsumer(consumer, mUsage,
mTotalBufferCount);
mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
@@ -284,7 +284,7 @@
return OK;
}
-status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3InputStream::getEndpointUsage(uint64_t *usage) const {
// Per HAL3 spec, input streams have 0 for their initial usage field.
*usage = 0;
return OK;
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 8f5b431..81226f8 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -76,7 +76,7 @@
virtual status_t configureQueueLocked();
- virtual status_t getEndpointUsage(uint32_t *usage) const;
+ virtual status_t getEndpointUsage(uint64_t *usage) const;
/**
* BufferItemConsumer::BufferFreedListener interface
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index b02cd6a..dcaefe3 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -90,7 +90,7 @@
Camera3OutputStream::Camera3OutputStream(int id,
uint32_t width, uint32_t height, int format,
- uint32_t consumerUsage, android_dataspace dataSpace,
+ uint64_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation, nsecs_t timestampOffset, int setId) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation, setId),
@@ -111,7 +111,8 @@
// Sanity check for the consumer usage flag.
if ((consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) == 0 &&
(consumerUsage & GraphicBuffer::USAGE_HW_COMPOSER) == 0) {
- ALOGE("%s: Deferred consumer usage flag is illegal (0x%x)!", __FUNCTION__, consumerUsage);
+ ALOGE("%s: Deferred consumer usage flag is illegal %" PRIu64 "!",
+ __FUNCTION__, consumerUsage);
mState = STATE_ERROR;
}
@@ -127,7 +128,7 @@
int format,
android_dataspace dataSpace,
camera3_stream_rotation_t rotation,
- uint32_t consumerUsage, nsecs_t timestampOffset,
+ uint64_t consumerUsage, nsecs_t timestampOffset,
int setId) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
@@ -365,10 +366,10 @@
mConsumerName = mConsumer->getConsumerName();
- res = native_window_set_usage(mConsumer.get(), camera3_stream::usage);
+ res = native_window_set_usage(mConsumer.get(), mUsage);
if (res != OK) {
- ALOGE("%s: Unable to configure usage %08x for stream %d",
- __FUNCTION__, camera3_stream::usage, mId);
+ ALOGE("%s: Unable to configure usage %" PRIu64 " for stream %d",
+ __FUNCTION__, mUsage, mId);
return res;
}
@@ -461,11 +462,11 @@
* HAL3.2 devices may not support the dynamic buffer registeration.
*/
if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
- uint32_t consumerUsage = 0;
+ uint64_t consumerUsage = 0;
getEndpointUsage(&consumerUsage);
StreamInfo streamInfo(
getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(),
- camera3_stream::usage | consumerUsage, mTotalBufferCount,
+ mUsage | consumerUsage, mTotalBufferCount,
/*isConfigured*/true);
wp<Camera3OutputStream> weakThis(this);
res = mBufferManager->registerStream(weakThis,
@@ -628,7 +629,7 @@
return OK;
}
-status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3OutputStream::getEndpointUsage(uint64_t *usage) const {
status_t res;
@@ -643,14 +644,12 @@
return res;
}
-status_t Camera3OutputStream::getEndpointUsageForSurface(uint32_t *usage,
+status_t Camera3OutputStream::getEndpointUsageForSurface(uint64_t *usage,
const sp<Surface>& surface) const {
status_t res;
- int32_t u = 0;
+ uint64_t u = 0;
- res = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
- NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
-
+ res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(surface.get()), &u);
// If an opaque output stream's endpoint is ImageReader, add
// GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used
// for the ZSL use case.
@@ -670,7 +669,7 @@
}
bool Camera3OutputStream::isVideoStream() const {
- uint32_t usage = 0;
+ uint64_t usage = 0;
status_t res = getEndpointUsage(&usage);
if (res != OK) {
ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
@@ -813,7 +812,7 @@
}
bool Camera3OutputStream::isConsumedByHWComposer() const {
- uint32_t usage = 0;
+ uint64_t usage = 0;
status_t res = getEndpointUsage(&usage);
if (res != OK) {
ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
@@ -824,7 +823,7 @@
}
bool Camera3OutputStream::isConsumedByHWTexture() const {
- uint32_t usage = 0;
+ uint64_t usage = 0;
status_t res = getEndpointUsage(&usage);
if (res != OK) {
ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 97aa7d4..7023d5d 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -44,7 +44,7 @@
uint32_t height;
uint32_t format;
android_dataspace dataSpace;
- uint32_t combinedUsage;
+ uint64_t combinedUsage;
size_t totalBufferCount;
bool isConfigured;
explicit StreamInfo(int id = CAMERA3_STREAM_ID_INVALID,
@@ -53,7 +53,7 @@
uint32_t h = 0,
uint32_t fmt = 0,
android_dataspace ds = HAL_DATASPACE_UNKNOWN,
- uint32_t usage = 0,
+ uint64_t usage = 0,
size_t bufferCount = 0,
bool configured = false) :
streamId(id),
@@ -101,7 +101,7 @@
* stream set id needs to be set to support buffer sharing between multiple streams.
*/
Camera3OutputStream(int id, uint32_t width, uint32_t height, int format,
- uint32_t consumerUsage, android_dataspace dataSpace,
+ uint64_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -176,7 +176,7 @@
Camera3OutputStream(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation,
- uint32_t consumerUsage = 0, nsecs_t timestampOffset = 0,
+ uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
/**
@@ -191,14 +191,14 @@
virtual status_t disconnectLocked();
- status_t getEndpointUsageForSurface(uint32_t *usage,
+ status_t getEndpointUsageForSurface(uint64_t *usage,
const sp<Surface>& surface) const;
status_t configureConsumerQueueLocked();
// Consumer as the output of camera HAL
sp<Surface> mConsumer;
- uint32_t getPresetConsumerUsage() const { return mConsumerUsage; }
+ uint64_t getPresetConsumerUsage() const { return mConsumerUsage; }
static const nsecs_t kDequeueBufferTimeout = 1000000000; // 1 sec
@@ -245,7 +245,7 @@
* Consumer end point usage flag set by the constructor for the deferred
* consumer case.
*/
- uint32_t mConsumerUsage;
+ uint64_t mConsumerUsage;
/**
* Internal Camera3Stream interface
@@ -262,7 +262,7 @@
virtual status_t configureQueueLocked();
- virtual status_t getEndpointUsage(uint32_t *usage) const;
+ virtual status_t getEndpointUsage(uint64_t *usage) const;
/**
* Private methods
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 2ae5660..5051711 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -23,7 +23,7 @@
Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
const std::vector<sp<Surface>>& surfaces,
uint32_t width, uint32_t height, int format,
- uint32_t consumerUsage, android_dataspace dataSpace,
+ uint64_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation,
nsecs_t timestampOffset, int setId) :
Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
@@ -41,7 +41,7 @@
mStreamSplitter = new Camera3StreamSplitter();
- uint32_t usage;
+ uint64_t usage;
getEndpointUsage(&usage);
res = mStreamSplitter->connect(mSurfaces, usage, camera3_stream::max_buffers, &mConsumer);
@@ -191,10 +191,10 @@
return res;
}
-status_t Camera3SharedOutputStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3SharedOutputStream::getEndpointUsage(uint64_t *usage) const {
status_t res = OK;
- uint32_t u = 0;
+ uint64_t u = 0;
if (mConsumer == nullptr) {
// Called before shared buffer queue is constructed.
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 7be0940..22bb2fc 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -34,7 +34,7 @@
*/
Camera3SharedOutputStream(int id, const std::vector<sp<Surface>>& surfaces,
uint32_t width, uint32_t height, int format,
- uint32_t consumerUsage, android_dataspace dataSpace,
+ uint64_t consumerUsage, android_dataspace dataSpace,
camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -74,7 +74,7 @@
virtual status_t disconnectLocked();
- virtual status_t getEndpointUsage(uint32_t *usage) const;
+ virtual status_t getEndpointUsage(uint64_t *usage) const;
}; // class Camera3SharedOutputStream
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 9e6ac79..25e44a5 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -56,6 +56,7 @@
mState(STATE_CONSTRUCTED),
mStatusId(StatusTracker::NO_STATUS_ID),
mStreamUnpreparable(true),
+ mUsage(0),
mOldUsage(0),
mOldMaxBuffers(0),
mPrepared(false),
@@ -69,7 +70,6 @@
camera3_stream::format = format;
camera3_stream::data_space = dataSpace;
camera3_stream::rotation = rotation;
- camera3_stream::usage = 0;
camera3_stream::max_buffers = 0;
camera3_stream::priv = NULL;
@@ -104,6 +104,14 @@
return camera3_stream::data_space;
}
+uint64_t Camera3Stream::getUsage() const {
+ return mUsage;
+}
+
+void Camera3Stream::setUsage(uint64_t usage) {
+ mUsage = usage;
+}
+
camera3_stream* Camera3Stream::startConfiguration() {
ATRACE_CALL();
Mutex::Autolock l(mLock);
@@ -133,10 +141,10 @@
return NULL;
}
- mOldUsage = camera3_stream::usage;
+ mOldUsage = mUsage;
mOldMaxBuffers = camera3_stream::max_buffers;
- res = getEndpointUsage(&(camera3_stream::usage));
+ res = getEndpointUsage(&mUsage);
if (res != OK) {
ALOGE("%s: Cannot query consumer endpoint usage!",
__FUNCTION__);
@@ -197,7 +205,7 @@
// Check if the stream configuration is unchanged, and skip reallocation if
// so. As documented in hardware/camera3.h:configure_streams().
if (mState == STATE_IN_RECONFIG &&
- mOldUsage == camera3_stream::usage &&
+ mOldUsage == mUsage &&
mOldMaxBuffers == camera3_stream::max_buffers) {
mState = STATE_CONFIGURED;
return OK;
@@ -243,7 +251,7 @@
return INVALID_OPERATION;
}
- camera3_stream::usage = mOldUsage;
+ mUsage = mOldUsage;
camera3_stream::max_buffers = mOldMaxBuffers;
mState = (mState == STATE_IN_RECONFIG) ? STATE_CONFIGURED : STATE_CONSTRUCTED;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 44fe6b6..9090f83 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -144,6 +144,8 @@
uint32_t getHeight() const;
int getFormat() const;
android_dataspace getDataSpace() const;
+ uint64_t getUsage() const;
+ void setUsage(uint64_t usage);
camera3_stream* asHalStream() override {
return this;
@@ -459,7 +461,7 @@
// Get the usage flags for the other endpoint, or return
// INVALID_OPERATION if they cannot be obtained.
- virtual status_t getEndpointUsage(uint32_t *usage) const = 0;
+ virtual status_t getEndpointUsage(uint64_t *usage) const = 0;
// Return whether the buffer is in the list of outstanding buffers.
bool isOutstandingBuffer(const camera3_stream_buffer& buffer) const;
@@ -473,8 +475,10 @@
// prepareNextBuffer called on it.
bool mStreamUnpreparable;
+ uint64_t mUsage;
+
private:
- uint32_t mOldUsage;
+ uint64_t mOldUsage;
uint32_t mOldMaxBuffers;
Condition mOutputBufferReturnedSignal;
Condition mInputBufferReturnedSignal;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 869e93a..a0a50c2 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -39,7 +39,7 @@
namespace android {
status_t Camera3StreamSplitter::connect(const std::vector<sp<Surface> >& surfaces,
- uint32_t consumerUsage, size_t halMaxBuffers, sp<Surface>* consumer) {
+ uint64_t consumerUsage, size_t halMaxBuffers, sp<Surface>* consumer) {
ATRACE_CALL();
if (consumer == nullptr) {
SP_LOGE("%s: consumer pointer is NULL", __FUNCTION__);
@@ -195,10 +195,8 @@
// Set dequeueBuffer/attachBuffer timeout if the consumer is not hw composer or hw texture.
// We need skip these cases as timeout will disable the non-blocking (async) mode.
- int32_t usage = 0;
- static_cast<ANativeWindow*>(outputQueue.get())->query(
- outputQueue.get(),
- NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
+ uint64_t usage = 0;
+ res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(outputQueue.get()), &usage);
if (!(usage & (GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_TEXTURE))) {
outputQueue->setDequeueTimeout(kDequeueBufferTimeout);
}
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index cc623e0..3b8839e 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -52,7 +52,7 @@
// Connect to the stream splitter by creating buffer queue and connecting it
// with output surfaces.
status_t connect(const std::vector<sp<Surface> >& surfaces,
- uint32_t consumerUsage, size_t halMaxBuffers,
+ uint64_t consumerUsage, size_t halMaxBuffers,
sp<Surface>* consumer);
// addOutput adds an output BufferQueue to the splitter. The splitter
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index 3d54460..ee018c3 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -38,7 +38,7 @@
namespace android {
RingBufferConsumer::RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer,
- uint32_t consumerUsage,
+ uint64_t consumerUsage,
int bufferCount) :
ConsumerBase(consumer),
mBufferCount(bufferCount),
@@ -368,7 +368,7 @@
return mConsumer->setDefaultBufferFormat(defaultFormat);
}
-status_t RingBufferConsumer::setConsumerUsage(uint32_t usage) {
+status_t RingBufferConsumer::setConsumerUsage(uint64_t usage) {
Mutex::Autolock _l(mMutex);
return mConsumer->setConsumerUsageBits(usage);
}
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index 2bafe4a..b737469 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -60,7 +60,7 @@
// the consumer usage flags passed to the graphics allocator. The
// bufferCount parameter specifies how many buffers can be pinned for user
// access at the same time.
- RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint32_t consumerUsage,
+ RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
int bufferCount);
virtual ~RingBufferConsumer();
@@ -80,7 +80,7 @@
// setConsumerUsage allows the BufferQueue consumer usage to be
// set at a later time after construction.
- status_t setConsumerUsage(uint32_t usage);
+ status_t setConsumerUsage(uint64_t usage);
// Buffer info, minus the graphics buffer/slot itself.
struct BufferInfo {
diff --git a/services/mediaanalytics/OWNERS b/services/mediaanalytics/OWNERS
new file mode 100644
index 0000000..9af258b
--- /dev/null
+++ b/services/mediaanalytics/OWNERS
@@ -0,0 +1 @@
+essick@google.com
diff --git a/services/medialog/OWNERS b/services/medialog/OWNERS
index fb8b8ee..21723ba 100644
--- a/services/medialog/OWNERS
+++ b/services/medialog/OWNERS
@@ -1,3 +1,3 @@
elaurent@google.com
-gkasten@android.com
+gkasten@google.com
hunga@google.com
diff --git a/services/minijail/OWNERS b/services/minijail/OWNERS
new file mode 100644
index 0000000..19f4f9f
--- /dev/null
+++ b/services/minijail/OWNERS
@@ -0,0 +1,2 @@
+jorgelo@google.com
+marcone@google.com
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index d648c6d..57990ce 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -131,7 +131,7 @@
aaudio_direction_t direction = request.getDirection();
AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
- mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, configurationOutput, direction);
+ mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, configurationInput, direction);
if (mServiceEndpoint == nullptr) {
ALOGE("AAudioServiceStreamShared::open() mServiceEndPoint = %p", mServiceEndpoint);
return AAUDIO_ERROR_UNAVAILABLE;
diff --git a/tools/OWNERS b/tools/OWNERS
index 6dcb035..f9cb567 100644
--- a/tools/OWNERS
+++ b/tools/OWNERS
@@ -1 +1 @@
-gkasten@android.com
+gkasten@google.com
diff --git a/tools/resampler_tools/OWNERS b/tools/resampler_tools/OWNERS
new file mode 100644
index 0000000..b4a6798
--- /dev/null
+++ b/tools/resampler_tools/OWNERS
@@ -0,0 +1 @@
+hunga@google.com