Merge "Change softvpx buffer count to 10" into pi-dev
diff --git a/include/media/TimeCheck.h b/include/media/TimeCheck.h
new file mode 120000
index 0000000..e3ef134
--- /dev/null
+++ b/include/media/TimeCheck.h
@@ -0,0 +1 @@
+../../media/libmedia/include/media/TimeCheck.h
\ No newline at end of file
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index 666d68a..26b8251 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -76,9 +76,14 @@
Vector<uint32_t> thumbnails;
Vector<uint32_t> dimgRefs;
+ Vector<uint32_t> cdscRefs;
size_t nextTileIndex;
};
+struct ExifItem {
+ off64_t offset;
+ size_t size;
+};
/////////////////////////////////////////////////////////////////////
//
@@ -473,7 +478,9 @@
uint32_t itemId() { return mItemId; }
- void apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) const;
+ void apply(
+ KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
+ KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const;
private:
uint32_t mItemId;
@@ -483,17 +490,20 @@
DISALLOW_EVIL_CONSTRUCTORS(ItemReference);
};
-void ItemReference::apply(KeyedVector<uint32_t, ImageItem> &itemIdToItemMap) const {
- ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId);
-
- // ignore non-image items
- if (itemIndex < 0) {
- return;
- }
-
+void ItemReference::apply(
+ KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
+ KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const {
ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId);
- if (type() == FOURCC('d', 'i', 'm', 'g')) {
+ switch(type()) {
+ case FOURCC('d', 'i', 'm', 'g'): {
+ ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId);
+
+ // ignore non-image items
+ if (itemIndex < 0) {
+ return;
+ }
+
ImageItem &derivedImage = itemIdToItemMap.editValueAt(itemIndex);
if (!derivedImage.dimgRefs.empty()) {
ALOGW("dimgRefs if not clean!");
@@ -512,7 +522,16 @@
// mark the source image of the derivation as hidden
sourceImage.hidden = true;
}
- } else if (type() == FOURCC('t', 'h', 'm', 'b')) {
+ break;
+ }
+ case FOURCC('t', 'h', 'm', 'b'): {
+ ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId);
+
+ // ignore non-image items
+ if (itemIndex < 0) {
+ return;
+ }
+
// mark thumbnail image as hidden, these can be retrieved if the client
// request thumbnail explicitly, but won't be exposed as displayables.
ImageItem &thumbImage = itemIdToItemMap.editValueAt(itemIndex);
@@ -532,11 +551,43 @@
}
masterImage.thumbnails.push_back(mItemId);
}
- } else if (type() == FOURCC('a', 'u', 'x', 'l')) {
+ break;
+ }
+ case FOURCC('c', 'd', 's', 'c'): {
+ ssize_t itemIndex = itemIdToExifMap.indexOfKey(mItemId);
+
+ // ignore non-exif block items
+ if (itemIndex < 0) {
+ return;
+ }
+
+ for (size_t i = 0; i < mRefs.size(); i++) {
+ itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]);
+
+ // ignore non-image items
+ if (itemIndex < 0) {
+ continue;
+ }
+ ALOGV("Image item id %d uses metadata item id %d", mRefs[i], mItemId);
+ ImageItem &image = itemIdToItemMap.editValueAt(itemIndex);
+ image.cdscRefs.push_back(mItemId);
+ }
+ break;
+ }
+ case FOURCC('a', 'u', 'x', 'l'): {
+ ssize_t itemIndex = itemIdToItemMap.indexOfKey(mItemId);
+
+ // ignore non-image items
+ if (itemIndex < 0) {
+ return;
+ }
+
// mark auxiliary image as hidden
ImageItem &auxImage = itemIdToItemMap.editValueAt(itemIndex);
auxImage.hidden = true;
- } else {
+ break;
+ }
+ default:
ALOGW("ignoring unsupported ref type 0x%x", type());
}
}
@@ -1299,10 +1350,13 @@
for (size_t i = 0; i < mItemInfos.size(); i++) {
const ItemInfo &info = mItemInfos[i];
-
- // ignore non-image items
+ // Only handle 3 types of items, all others are ignored:
+ // 'grid': derived image from tiles
+ // 'hvc1': coded image (or tile)
+ // 'Exif': EXIF metadata
if (info.itemType != FOURCC('g', 'r', 'i', 'd') &&
- info.itemType != FOURCC('h', 'v', 'c', '1')) {
+ info.itemType != FOURCC('h', 'v', 'c', '1') &&
+ info.itemType != FOURCC('E', 'x', 'i', 'f')) {
continue;
}
@@ -1325,6 +1379,19 @@
return ERROR_MALFORMED;
}
+ if (info.itemType == FOURCC('E', 'x', 'i', 'f')) {
+ // Only add if the Exif data is non-empty. The first 4 bytes contain
+ // the offset to TIFF header, which the Exif parser doesn't use.
+ if (size > 4) {
+ ExifItem exifItem = {
+ .offset = offset,
+ .size = size,
+ };
+ mItemIdToExifMap.add(info.itemId, exifItem);
+ }
+ continue;
+ }
+
ImageItem image(info.itemType, info.itemId, info.hidden);
ALOGV("adding %s: itemId %d", image.isGrid() ? "grid" : "image", info.itemId);
@@ -1354,7 +1421,7 @@
}
for (size_t i = 0; i < mItemReferences.size(); i++) {
- mItemReferences[i]->apply(mItemIdToItemMap);
+ mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToExifMap);
}
bool foundPrimary = false;
@@ -1574,6 +1641,34 @@
return OK;
}
+status_t ItemTable::getExifOffsetAndSize(off64_t *offset, size_t *size) {
+ if (!mImageItemsValid) {
+ return INVALID_OPERATION;
+ }
+
+ ssize_t itemIndex = mItemIdToItemMap.indexOfKey(mPrimaryItemId);
+
+ // this should not happen, something's seriously wrong.
+ if (itemIndex < 0) {
+ return INVALID_OPERATION;
+ }
+
+ const ImageItem &image = mItemIdToItemMap[itemIndex];
+ if (image.cdscRefs.size() == 0) {
+ return NAME_NOT_FOUND;
+ }
+
+ ssize_t exifIndex = mItemIdToExifMap.indexOfKey(image.cdscRefs[0]);
+ if (exifIndex < 0) {
+ return NAME_NOT_FOUND;
+ }
+
+ // skip the first 4-byte of the offset to TIFF header
+ *offset = mItemIdToExifMap[exifIndex].offset + 4;
+ *size = mItemIdToExifMap[exifIndex].size - 4;
+ return OK;
+}
+
} // namespace heif
} // namespace android
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index f4a69cc..536dcb0 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -32,6 +32,7 @@
struct AssociationEntry;
struct ImageItem;
+struct ExifItem;
struct ItemLoc;
struct ItemInfo;
struct ItemProperty;
@@ -55,6 +56,7 @@
status_t findThumbnailItem(const uint32_t imageIndex, uint32_t *itemIndex);
status_t getImageOffsetAndSize(
uint32_t *itemIndex, off64_t *offset, size_t *size);
+ status_t getExifOffsetAndSize(off64_t *offset, size_t *size);
protected:
~ItemTable();
@@ -78,6 +80,7 @@
bool mImageItemsValid;
uint32_t mCurrentItemIndex;
KeyedVector<uint32_t, ImageItem> mItemIdToItemMap;
+ KeyedVector<uint32_t, ExifItem> mItemIdToExifMap;
Vector<uint32_t> mDisplayables;
status_t parseIlocBox(off64_t offset, size_t size);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index a9f66fa..07ef0e3 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -586,6 +586,12 @@
}
if (mIsHeif && (mItemTable != NULL) && (mItemTable->countImages() > 0)) {
+ off64_t exifOffset;
+ size_t exifSize;
+ if (mItemTable->getExifOffsetAndSize(&exifOffset, &exifSize) == OK) {
+ mFileMetaData.setInt64(kKeyExifOffset, (int64_t)exifOffset);
+ mFileMetaData.setInt64(kKeyExifSize, (int64_t)exifSize);
+ }
for (uint32_t imageIndex = 0;
imageIndex < mItemTable->countImages(); imageIndex++) {
sp<MetaData> meta = mItemTable->getImageMeta(imageIndex);
@@ -601,6 +607,7 @@
ALOGW("Extracting still images only");
err = OK;
}
+ mInitCheck = OK;
ALOGV("adding HEIF image track %u", imageIndex);
Track *track = new Track;
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 3358e35..873d836 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -24,6 +24,7 @@
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
+#include <media/TimeCheck.h>
#include <private/android_filesystem_config.h>
#include "IAudioFlinger.h"
@@ -933,6 +934,8 @@
break;
}
+ TimeCheck check("IAudioFlinger");
+
switch (code) {
case CREATE_TRACK: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 8f5ff30..0b98502 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -27,6 +27,7 @@
#include <media/AudioEffect.h>
#include <media/IAudioPolicyService.h>
+#include <media/TimeCheck.h>
#include <private/android_filesystem_config.h>
#include <system/audio.h>
@@ -882,6 +883,8 @@
break;
}
+ TimeCheck check("IAudioPolicyService");
+
switch (code) {
case SET_DEVICE_CONNECTION_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 34b15a8..3990e69 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -18,7 +18,7 @@
vndk: {
enabled: true,
},
- srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
+ srcs: ["AudioParameter.cpp", "TypeConverter.cpp", "TimeCheck.cpp"],
cflags: [
"-Werror",
"-Wno-error=deprecated-declarations",
diff --git a/media/libmedia/TimeCheck.cpp b/media/libmedia/TimeCheck.cpp
new file mode 100644
index 0000000..dab5d4f
--- /dev/null
+++ b/media/libmedia/TimeCheck.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <media/TimeCheck.h>
+
+namespace android {
+
+/* static */
+sp<TimeCheck::TimeCheckThread> TimeCheck::getTimeCheckThread()
+{
+ static sp<TimeCheck::TimeCheckThread> sTimeCheckThread = new TimeCheck::TimeCheckThread();
+ return sTimeCheckThread;
+}
+
+TimeCheck::TimeCheck(const char *tag, uint32_t timeoutMs)
+ : mEndTimeNs(getTimeCheckThread()->startMonitoring(tag, timeoutMs))
+{
+}
+
+TimeCheck::~TimeCheck() {
+ getTimeCheckThread()->stopMonitoring(mEndTimeNs);
+}
+
+TimeCheck::TimeCheckThread::~TimeCheckThread()
+{
+ AutoMutex _l(mMutex);
+ requestExit();
+ mMonitorRequests.clear();
+ mCond.signal();
+}
+
+nsecs_t TimeCheck::TimeCheckThread::startMonitoring(const char *tag, uint32_t timeoutMs) {
+ Mutex::Autolock _l(mMutex);
+ nsecs_t endTimeNs = systemTime() + milliseconds(timeoutMs);
+ for (; mMonitorRequests.indexOfKey(endTimeNs) >= 0; ++endTimeNs);
+ mMonitorRequests.add(endTimeNs, tag);
+ mCond.signal();
+ return endTimeNs;
+}
+
+void TimeCheck::TimeCheckThread::stopMonitoring(nsecs_t endTimeNs) {
+ Mutex::Autolock _l(mMutex);
+ mMonitorRequests.removeItem(endTimeNs);
+ mCond.signal();
+}
+
+bool TimeCheck::TimeCheckThread::threadLoop()
+{
+ status_t status = TIMED_OUT;
+ const char *tag;
+ {
+ AutoMutex _l(mMutex);
+
+ if (exitPending()) {
+ return false;
+ }
+
+ nsecs_t endTimeNs = INT64_MAX;
+ // KeyedVector mMonitorRequests is ordered so take first entry as next timeout
+ if (mMonitorRequests.size() != 0) {
+ endTimeNs = mMonitorRequests.keyAt(0);
+ tag = mMonitorRequests.valueAt(0);
+ }
+
+ const nsecs_t waitTimeNs = endTimeNs - systemTime();
+ if (waitTimeNs > 0) {
+ status = mCond.waitRelative(mMutex, waitTimeNs);
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "TimeCheck timeout for %s", tag);
+ return true;
+}
+
+}; // namespace android
diff --git a/media/libmedia/include/media/TimeCheck.h b/media/libmedia/include/media/TimeCheck.h
new file mode 100644
index 0000000..6c5f656
--- /dev/null
+++ b/media/libmedia/include/media/TimeCheck.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_TIME_CHECK_H
+#define ANDROID_TIME_CHECK_H
+
+#include <utils/KeyedVector.h>
+#include <utils/Thread.h>
+
+
+namespace android {
+
+// A class monitoring execution time for a code block (scoped variable) and causing an assert
+// if it exceeds a certain time
+
+class TimeCheck {
+public:
+
+ // The default timeout is chosen to be less than system server watchdog timeout
+ static constexpr uint32_t kDefaultTimeOutMs = 5000;
+
+ TimeCheck(const char *tag, uint32_t timeoutMs = kDefaultTimeOutMs);
+ ~TimeCheck();
+
+private:
+
+ class TimeCheckThread : public Thread {
+ public:
+
+ TimeCheckThread() {}
+ virtual ~TimeCheckThread() override;
+
+ nsecs_t startMonitoring(const char *tag, uint32_t timeoutMs);
+ void stopMonitoring(nsecs_t endTimeNs);
+
+ private:
+
+ // RefBase
+ virtual void onFirstRef() override { run("TimeCheckThread", PRIORITY_URGENT_AUDIO); }
+
+ // Thread
+ virtual bool threadLoop() override;
+
+ Condition mCond;
+ Mutex mMutex;
+ // using the end time in ns as key is OK given the risk is low that two entries
+ // are added in such a way that <add time> + <timeout> are the same for both.
+ KeyedVector< nsecs_t, const char*> mMonitorRequests;
+ };
+
+ static sp<TimeCheckThread> getTimeCheckThread();
+
+ const nsecs_t mEndTimeNs;
+};
+
+}; // namespace android
+
+#endif // ANDROID_TIME_CHECK_H
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
index 18e63f2..f1b7806 100644
--- a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
@@ -218,6 +218,8 @@
kKeyIccProfile = 'prof', // raw data, ICC profile data
kKeyIsPrimaryImage = 'prim', // bool (int32_t), image track is the primary image
kKeyFrameCount = 'nfrm', // int32_t, total number of frame in video track
+ kKeyExifOffset = 'exof', // int64_t, Exif data offset
+ kKeyExifSize = 'exsz', // int64_t, Exif data size
};
enum {
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index e2d5d0d..22b1e59 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -87,66 +87,6 @@
}
cc_library_shared {
- name: "libstagefright_ccodec",
-
- local_include_dirs: ["include"],
-
- srcs: [
- "C2OMXNode.cpp",
- "CCodec.cpp",
- "CCodecBufferChannel.cpp",
- "Codec2Buffer.cpp",
- "Codec2InfoBuilder.cpp",
- ],
-
- cflags: [
- "-Werror",
- "-Wall",
- ],
-
- header_libs: [
- "libstagefright_codec2_internal",
- ],
-
- shared_libs: [
- "libbinder",
- "libcutils",
- "libgui",
- "libhidlallocatorutils",
- "libhidlbase",
- "liblog",
- "libmedia",
- "libmedia_omx",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_codecbase",
- "libstagefright_foundation",
- "libstagefright_omx_utils",
- "libstagefright_xmlparser",
- "libui",
- "libutils",
- // TODO: Remove libv4l2_c2_componentstore.
- "libv4l2_c2componentstore",
- "android.hardware.cas.native@1.0",
-
- // TODO: do not link directly with impl
- "libstagefright_bufferqueue_helper",
- "android.hardware.media.c2@1.0-service-impl",
- ],
-
- sanitize: {
- cfi: true,
- misc_undefined: [
- "unsigned-integer-overflow",
- "signed-integer-overflow",
- ],
- diag: {
- cfi: true,
- },
- },
-}
-
-cc_library_shared {
name: "libstagefright",
srcs: [
@@ -220,7 +160,6 @@
"libui",
"libutils",
"libmedia_helper",
- "libstagefright_ccodec",
"libstagefright_codecbase",
"libstagefright_foundation",
"libstagefright_omx",
diff --git a/media/libstagefright/C2OMXNode.cpp b/media/libstagefright/C2OMXNode.cpp
deleted file mode 100644
index 04faa28..0000000
--- a/media/libstagefright/C2OMXNode.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright 2018, 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.
- */
-
-#ifdef __LP64__
-#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
-#endif
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "C2OMXNode"
-#include <log/log.h>
-
-#include <C2AllocatorGralloc.h>
-#include <C2BlockInternal.h>
-#include <C2Component.h>
-#include <C2PlatformSupport.h>
-
-#include <OMX_Component.h>
-#include <OMX_Index.h>
-#include <OMX_IndexExt.h>
-
-#include <media/stagefright/omx/OMXUtils.h>
-#include <media/stagefright/MediaErrors.h>
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-#include "include/C2OMXNode.h"
-
-namespace android {
-
-namespace {
-
-class Buffer2D : public C2Buffer {
-public:
- explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {}
-};
-
-} // namespace
-
-C2OMXNode::C2OMXNode(const std::shared_ptr<C2Component> &comp) : mComp(comp) {}
-
-status_t C2OMXNode::freeNode() {
- mComp.reset();
- return OK;
-}
-
-status_t C2OMXNode::sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
- (void)cmd;
- (void)param;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::getParameter(OMX_INDEXTYPE index, void *params, size_t size) {
- status_t err = ERROR_UNSUPPORTED;
- switch ((uint32_t)index) {
- case OMX_IndexParamConsumerUsageBits: {
- // TODO: read from intf()
- OMX_U32 *usage = (OMX_U32 *)params;
- *usage = GRALLOC_USAGE_SW_READ_OFTEN;
- err = OK;
- break;
- }
- case OMX_IndexParamPortDefinition: {
- if (size < sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
- return BAD_VALUE;
- }
- OMX_PARAM_PORTDEFINITIONTYPE *pDef = (OMX_PARAM_PORTDEFINITIONTYPE *)params;
- // TODO: read these from intf()
- pDef->nBufferCountActual = 16;
- pDef->eDomain = OMX_PortDomainVideo;
- pDef->format.video.nFrameWidth = 1080;
- pDef->format.video.nFrameHeight = 1920;
- err = OK;
- break;
- }
- default:
- break;
- }
- return err;
-}
-
-status_t C2OMXNode::setParameter(OMX_INDEXTYPE index, const void *params, size_t size) {
- (void)index;
- (void)params;
- (void)size;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::getConfig(OMX_INDEXTYPE index, void *config, size_t size) {
- (void)index;
- (void)config;
- (void)size;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::setConfig(OMX_INDEXTYPE index, const void *config, size_t size) {
- (void)index;
- (void)config;
- (void)size;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
- (void)portIndex;
- (void)mode;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::prepareForAdaptivePlayback(
- OMX_U32 portIndex, OMX_BOOL enable,
- OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
- (void)portIndex;
- (void)enable;
- (void)maxFrameWidth;
- (void)maxFrameHeight;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::configureVideoTunnelMode(
- OMX_U32 portIndex, OMX_BOOL tunneled,
- OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
- (void)portIndex;
- (void)tunneled;
- (void)audioHwSync;
- *sidebandHandle = nullptr;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage) {
- (void)portIndex;
- *usage = 0;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::setInputSurface(const sp<IOMXBufferSource> &bufferSource) {
- c2_status_t err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
- C2PlatformAllocatorStore::GRALLOC,
- &mAllocator);
- if (err != OK) {
- return UNKNOWN_ERROR;
- }
- mBufferSource = bufferSource;
- return OK;
-}
-
-status_t C2OMXNode::allocateSecureBuffer(
- OMX_U32 portIndex, size_t size, buffer_id *buffer,
- void **bufferData, sp<NativeHandle> *nativeHandle) {
- (void)portIndex;
- (void)size;
- (void)nativeHandle;
- *buffer = 0;
- *bufferData = nullptr;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::useBuffer(
- OMX_U32 portIndex, const OMXBuffer &omxBuf, buffer_id *buffer) {
- (void)portIndex;
- (void)omxBuf;
- *buffer = 0;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::freeBuffer(OMX_U32 portIndex, buffer_id buffer) {
- (void)portIndex;
- (void)buffer;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::fillBuffer(
- buffer_id buffer, const OMXBuffer &omxBuf, int fenceFd) {
- (void)buffer;
- (void)omxBuf;
- (void)fenceFd;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::emptyBuffer(
- buffer_id buffer, const OMXBuffer &omxBuf,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
- // TODO: better fence handling
- if (fenceFd >= 0) {
- sp<Fence> fence = new Fence(fenceFd);
- fence->waitForever(LOG_TAG);
- }
- std::shared_ptr<C2Component> comp = mComp.lock();
- if (!comp) {
- return NO_INIT;
- }
-
- uint32_t c2Flags = 0;
- std::shared_ptr<C2GraphicBlock> block;
-
- C2Handle *handle = nullptr;
- if (omxBuf.mBufferType == OMXBuffer::kBufferTypeANWBuffer) {
- std::shared_ptr<C2GraphicAllocation> alloc;
- handle = WrapNativeCodec2GrallocHandle(
- native_handle_clone(omxBuf.mGraphicBuffer->handle),
- omxBuf.mGraphicBuffer->width,
- omxBuf.mGraphicBuffer->height,
- omxBuf.mGraphicBuffer->format,
- omxBuf.mGraphicBuffer->usage,
- omxBuf.mGraphicBuffer->stride);
- c2_status_t err = mAllocator->priorGraphicAllocation(handle, &alloc);
- if (err != OK) {
- return UNKNOWN_ERROR;
- }
- block = _C2BlockFactory::CreateGraphicBlock(alloc);
- } else if (flags & OMX_BUFFERFLAG_EOS) {
- c2Flags = C2FrameData::FLAG_END_OF_STREAM;
- } else {
- return BAD_VALUE;
- }
-
- std::unique_ptr<C2Work> work(new C2Work);
- work->input.flags = (C2FrameData::flags_t)c2Flags;
- work->input.ordinal.timestamp = timestamp;
- work->input.ordinal.frameIndex = mFrameIndex++;
- work->input.buffers.clear();
- if (block) {
- std::shared_ptr<C2Buffer> c2Buffer(
- // TODO: fence
- new Buffer2D(block->share(
- C2Rect(block->width(), block->height()), ::C2Fence())),
- [handle, buffer, source = getSource()](C2Buffer *ptr) {
- delete ptr;
- native_handle_delete(handle);
- // TODO: fence
- (void)source->onInputBufferEmptied(buffer, -1);
- });
- work->input.buffers.push_back(c2Buffer);
- }
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
-
- c2_status_t err = comp->queue_nb(&items);
- if (err != C2_OK) {
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2OMXNode::getExtensionIndex(
- const char *parameterName, OMX_INDEXTYPE *index) {
- (void)parameterName;
- *index = OMX_IndexMax;
- return ERROR_UNSUPPORTED;
-}
-
-status_t C2OMXNode::dispatchMessage(const omx_message& msg) {
- if (msg.type != omx_message::EVENT) {
- return ERROR_UNSUPPORTED;
- }
- if (msg.u.event_data.event != OMX_EventDataSpaceChanged) {
- return ERROR_UNSUPPORTED;
- }
- // TODO: fill intf() with info inside |msg|.
- return OK;
-}
-
-sp<IOMXBufferSource> C2OMXNode::getSource() {
- return mBufferSource;
-}
-
-} // namespace android
diff --git a/media/libstagefright/CCodec.cpp b/media/libstagefright/CCodec.cpp
deleted file mode 100644
index 322f9fd..0000000
--- a/media/libstagefright/CCodec.cpp
+++ /dev/null
@@ -1,916 +0,0 @@
-/*
- * 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 "CCodec"
-#include <cutils/properties.h>
-#include <utils/Log.h>
-
-#include <thread>
-
-#include <C2PlatformSupport.h>
-#include <C2V4l2Support.h>
-
-#include <android/IOMXBufferSource.h>
-#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
-#include <gui/Surface.h>
-#include <media/stagefright/codec2/1.0/InputSurface.h>
-#include <media/stagefright/BufferProducerWrapper.h>
-#include <media/stagefright/CCodec.h>
-#include <media/stagefright/PersistentSurface.h>
-
-#include "include/C2OMXNode.h"
-#include "include/CCodecBufferChannel.h"
-#include "include/InputSurfaceWrapper.h"
-
-namespace android {
-
-using namespace std::chrono_literals;
-using ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
-
-namespace {
-
-class CCodecWatchdog : public AHandler {
-private:
- enum {
- kWhatRegister,
- kWhatWatch,
- };
- constexpr static int64_t kWatchIntervalUs = 3000000; // 3 secs
-
-public:
- static sp<CCodecWatchdog> getInstance() {
- Mutexed<sp<CCodecWatchdog>>::Locked instance(sInstance);
- if (*instance == nullptr) {
- *instance = new CCodecWatchdog;
- (*instance)->init();
- }
- return *instance;
- }
-
- ~CCodecWatchdog() = default;
-
- void registerCodec(CCodec *codec) {
- sp<AMessage> msg = new AMessage(kWhatRegister, this);
- msg->setPointer("codec", codec);
- msg->post();
- }
-
-protected:
- void onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatRegister: {
- void *ptr = nullptr;
- CHECK(msg->findPointer("codec", &ptr));
- Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
- codecs->emplace_back((CCodec *)ptr);
- break;
- }
-
- case kWhatWatch: {
- Mutexed<std::list<wp<CCodec>>>::Locked codecs(mCodecs);
- for (auto it = codecs->begin(); it != codecs->end(); ) {
- sp<CCodec> codec = it->promote();
- if (codec == nullptr) {
- it = codecs->erase(it);
- continue;
- }
- codec->initiateReleaseIfStuck();
- ++it;
- }
- msg->post(kWatchIntervalUs);
- break;
- }
-
- default: {
- TRESPASS("CCodecWatchdog: unrecognized message");
- }
- }
- }
-
-private:
- CCodecWatchdog() : mLooper(new ALooper) {}
-
- void init() {
- mLooper->setName("CCodecWatchdog");
- mLooper->registerHandler(this);
- mLooper->start();
- (new AMessage(kWhatWatch, this))->post(kWatchIntervalUs);
- }
-
- static Mutexed<sp<CCodecWatchdog>> sInstance;
-
- sp<ALooper> mLooper;
- Mutexed<std::list<wp<CCodec>>> mCodecs;
-};
-
-Mutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance;
-
-class CCodecListener : public C2Component::Listener {
-public:
- explicit CCodecListener(const wp<CCodec> &codec) : mCodec(codec) {}
-
- virtual void onWorkDone_nb(
- std::weak_ptr<C2Component> component,
- std::list<std::unique_ptr<C2Work>> workItems) override {
- (void)component;
- sp<CCodec> codec(mCodec.promote());
- if (!codec) {
- return;
- }
- codec->onWorkDone(workItems);
- }
-
- virtual void onTripped_nb(
- std::weak_ptr<C2Component> component,
- std::vector<std::shared_ptr<C2SettingResult>> settingResult) override {
- // TODO
- (void)component;
- (void)settingResult;
- }
-
- virtual void onError_nb(std::weak_ptr<C2Component> component, uint32_t errorCode) override {
- // TODO
- (void)component;
- (void)errorCode;
- }
-
-private:
- wp<CCodec> mCodec;
-};
-
-class C2InputSurfaceWrapper : public InputSurfaceWrapper {
-public:
- explicit C2InputSurfaceWrapper(const sp<InputSurface> &surface) : mSurface(surface) {}
- ~C2InputSurfaceWrapper() override = default;
-
- status_t connect(const std::shared_ptr<C2Component> &comp) override {
- if (mConnection != nullptr) {
- return ALREADY_EXISTS;
- }
- mConnection = mSurface->connectToComponent(comp);
- return OK;
- }
-
- void disconnect() override {
- if (mConnection != nullptr) {
- mConnection->disconnect();
- mConnection.clear();
- }
- }
-
-private:
- sp<InputSurface> mSurface;
- sp<InputSurfaceConnection> mConnection;
-};
-
-class GraphicBufferSourceWrapper : public InputSurfaceWrapper {
-public:
- explicit GraphicBufferSourceWrapper(const sp<IGraphicBufferSource> &source) : mSource(source) {}
- ~GraphicBufferSourceWrapper() override = default;
-
- status_t connect(const std::shared_ptr<C2Component> &comp) override {
- // TODO: proper color aspect & dataspace
- android_dataspace dataSpace = HAL_DATASPACE_BT709;
-
- mNode = new C2OMXNode(comp);
- mSource->configure(mNode, dataSpace);
-
- // TODO: configure according to intf().
-
- sp<IOMXBufferSource> source = mNode->getSource();
- if (source == nullptr) {
- return NO_INIT;
- }
- constexpr size_t kNumSlots = 16;
- for (size_t i = 0; i < kNumSlots; ++i) {
- source->onInputBufferAdded(i);
- }
- source->onOmxExecuting();
- return OK;
- }
-
- void disconnect() override {
- if (mNode == nullptr) {
- return;
- }
- sp<IOMXBufferSource> source = mNode->getSource();
- if (source == nullptr) {
- ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
- return;
- }
- source->onOmxIdle();
- source->onOmxLoaded();
- mNode.clear();
- }
-
-private:
- sp<IGraphicBufferSource> mSource;
- sp<C2OMXNode> mNode;
-};
-
-} // namespace
-
-CCodec::CCodec()
- : mChannel(new CCodecBufferChannel([this] (status_t err, enum ActionCode actionCode) {
- mCallback->onError(err, actionCode);
- })) {
- CCodecWatchdog::getInstance()->registerCodec(this);
-}
-
-CCodec::~CCodec() {
-}
-
-std::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
- return mChannel;
-}
-
-status_t CCodec::tryAndReportOnError(std::function<status_t()> job) {
- status_t err = job();
- if (err != C2_OK) {
- mCallback->onError(err, ACTION_CODE_FATAL);
- }
- return err;
-}
-
-void CCodec::initiateAllocateComponent(const sp<AMessage> &msg) {
- auto setAllocating = [this] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != RELEASED) {
- return INVALID_OPERATION;
- }
- state->set(ALLOCATING);
- return OK;
- };
- if (tryAndReportOnError(setAllocating) != OK) {
- return;
- }
-
- sp<RefBase> codecInfo;
- CHECK(msg->findObject("codecInfo", &codecInfo));
- // For Codec 2.0 components, componentName == codecInfo->getCodecName().
-
- sp<AMessage> allocMsg(new AMessage(kWhatAllocate, this));
- allocMsg->setObject("codecInfo", codecInfo);
- allocMsg->post();
-}
-
-void CCodec::allocate(const sp<MediaCodecInfo> &codecInfo) {
- if (codecInfo == nullptr) {
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- return;
- }
- ALOGV("allocate(%s)", codecInfo->getCodecName());
- mListener.reset(new CCodecListener(this));
-
- AString componentName = codecInfo->getCodecName();
- // TODO: use codecInfo->getOwnerName() for connecting to remote process.
-
- std::shared_ptr<C2Component> comp;
- c2_status_t err = GetCodec2PlatformComponentStore()->createComponent(
- componentName.c_str(), &comp);
- static bool v4l2Enabled =
- property_get_bool("debug.stagefright.ccodec_v4l2", false);
- if (err != C2_OK && v4l2Enabled) {
- err = GetCodec2VDAComponentStore()->createComponent(
- componentName.c_str(), &comp);
- }
- if (err != C2_OK) {
- ALOGE("Failed Create component: %s", componentName.c_str());
- Mutexed<State>::Locked state(mState);
- state->set(RELEASED);
- state.unlock();
- mCallback->onError(err, ACTION_CODE_FATAL);
- state.lock();
- return;
- }
- ALOGV("Success Create component: %s", componentName.c_str());
- comp->setListener_vb(mListener, C2_MAY_BLOCK);
- mChannel->setComponent(comp);
- auto setAllocated = [this, comp] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != ALLOCATING) {
- state->set(RELEASED);
- return UNKNOWN_ERROR;
- }
- state->set(ALLOCATED);
- state->comp = comp;
- return OK;
- };
- if (tryAndReportOnError(setAllocated) != OK) {
- return;
- }
- mCallback->onComponentAllocated(comp->intf()->getName().c_str());
-}
-
-void CCodec::initiateConfigureComponent(const sp<AMessage> &format) {
- auto checkAllocated = [this] {
- Mutexed<State>::Locked state(mState);
- return (state->get() != ALLOCATED) ? UNKNOWN_ERROR : OK;
- };
- if (tryAndReportOnError(checkAllocated) != OK) {
- return;
- }
-
- sp<AMessage> msg(new AMessage(kWhatConfigure, this));
- msg->setMessage("format", format);
- msg->post();
-}
-
-void CCodec::configure(const sp<AMessage> &msg) {
- std::shared_ptr<C2ComponentInterface> intf;
- auto checkAllocated = [this, &intf] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != ALLOCATED) {
- state->set(RELEASED);
- return UNKNOWN_ERROR;
- }
- intf = state->comp->intf();
- return OK;
- };
- if (tryAndReportOnError(checkAllocated) != OK) {
- return;
- }
-
- sp<AMessage> inputFormat(new AMessage);
- sp<AMessage> outputFormat(new AMessage);
- auto doConfig = [=] {
- AString mime;
- if (!msg->findString("mime", &mime)) {
- return BAD_VALUE;
- }
-
- int32_t encoder;
- if (!msg->findInt32("encoder", &encoder)) {
- encoder = false;
- }
-
- // TODO: read from intf()
- if ((!encoder) != (intf->getName().find("encoder") == std::string::npos)) {
- return UNKNOWN_ERROR;
- }
-
- sp<RefBase> obj;
- if (msg->findObject("native-window", &obj)) {
- sp<Surface> surface = static_cast<Surface *>(obj.get());
- setSurface(surface);
- }
-
- std::vector<std::unique_ptr<C2Param>> params;
- std::initializer_list<C2Param::Index> indices {
- C2PortMimeConfig::input::PARAM_TYPE,
- C2PortMimeConfig::output::PARAM_TYPE,
- };
- c2_status_t c2err = intf->query_vb(
- {},
- indices,
- C2_DONT_BLOCK,
- ¶ms);
- if (c2err != C2_OK) {
- ALOGE("Failed to query component interface: %d", c2err);
- return UNKNOWN_ERROR;
- }
- if (params.size() != indices.size()) {
- ALOGE("Component returns wrong number of params");
- return UNKNOWN_ERROR;
- }
- if (!params[0] || !params[1]) {
- ALOGE("Component returns null params");
- return UNKNOWN_ERROR;
- }
- inputFormat->setString("mime", ((C2PortMimeConfig *)params[0].get())->m.value);
- outputFormat->setString("mime", ((C2PortMimeConfig *)params[1].get())->m.value);
-
- // XXX: hack
- bool audio = mime.startsWithIgnoreCase("audio/");
- if (encoder) {
- if (audio) {
- inputFormat->setInt32("channel-count", 1);
- inputFormat->setInt32("sample-rate", 44100);
- outputFormat->setInt32("channel-count", 1);
- outputFormat->setInt32("sample-rate", 44100);
- } else {
- outputFormat->setInt32("width", 1080);
- outputFormat->setInt32("height", 1920);
- }
- } else {
- if (audio) {
- outputFormat->setInt32("channel-count", 2);
- outputFormat->setInt32("sample-rate", 44100);
- } else {
- int32_t tmp;
- if (msg->findInt32("width", &tmp)) {
- outputFormat->setInt32("width", tmp);
- }
- if (msg->findInt32("height", &tmp)) {
- outputFormat->setInt32("height", tmp);
- }
- }
- }
-
- // TODO
-
- return OK;
- };
- if (tryAndReportOnError(doConfig) != OK) {
- return;
- }
-
- {
- Mutexed<Formats>::Locked formats(mFormats);
- formats->inputFormat = inputFormat;
- formats->outputFormat = outputFormat;
- }
- mCallback->onComponentConfigured(inputFormat, outputFormat);
-}
-
-void CCodec::initiateCreateInputSurface() {
- status_t err = [this] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != ALLOCATED) {
- return UNKNOWN_ERROR;
- }
- // TODO: read it from intf() properly.
- if (state->comp->intf()->getName().find("encoder") == std::string::npos) {
- return INVALID_OPERATION;
- }
- return OK;
- }();
- if (err != OK) {
- mCallback->onInputSurfaceCreationFailed(err);
- return;
- }
-
- (new AMessage(kWhatCreateInputSurface, this))->post();
-}
-
-void CCodec::createInputSurface() {
- // TODO: get this from codec process
- sp<InputSurface> surface(InputSurface::Create());
-
- // TODO: get proper error code.
- status_t err = (surface == nullptr) ? UNKNOWN_ERROR : OK;
- if (err != OK) {
- ALOGE("Failed to initialize input surface: %d", err);
- mCallback->onInputSurfaceCreationFailed(err);
- return;
- }
-
- err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(surface));
- if (err != OK) {
- ALOGE("Failed to set up input surface: %d", err);
- mCallback->onInputSurfaceCreationFailed(err);
- return;
- }
-
- sp<AMessage> inputFormat;
- sp<AMessage> outputFormat;
- {
- Mutexed<Formats>::Locked formats(mFormats);
- inputFormat = formats->inputFormat;
- outputFormat = formats->outputFormat;
- }
- mCallback->onInputSurfaceCreated(
- inputFormat,
- outputFormat,
- new BufferProducerWrapper(new H2BGraphicBufferProducer(surface)));
-}
-
-status_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) {
- status_t err = mChannel->setInputSurface(surface);
- if (err != OK) {
- return err;
- }
-
- // TODO: configure |surface| with other settings.
- return OK;
-}
-
-void CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) {
- sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
- msg->setObject("surface", surface);
- msg->post();
-}
-
-void CCodec::setInputSurface(const sp<PersistentSurface> &surface) {
- status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
- surface->getBufferSource()));
- if (err != OK) {
- ALOGE("Failed to set up input surface: %d", err);
- mCallback->onInputSurfaceDeclined(err);
- return;
- }
-
- sp<AMessage> inputFormat;
- sp<AMessage> outputFormat;
- {
- Mutexed<Formats>::Locked formats(mFormats);
- inputFormat = formats->inputFormat;
- outputFormat = formats->outputFormat;
- }
- mCallback->onInputSurfaceAccepted(inputFormat, outputFormat);
-}
-
-void CCodec::initiateStart() {
- auto setStarting = [this] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != ALLOCATED) {
- return UNKNOWN_ERROR;
- }
- state->set(STARTING);
- return OK;
- };
- if (tryAndReportOnError(setStarting) != OK) {
- return;
- }
-
- (new AMessage(kWhatStart, this))->post();
-}
-
-void CCodec::start() {
- std::shared_ptr<C2Component> comp;
- auto checkStarting = [this, &comp] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != STARTING) {
- return UNKNOWN_ERROR;
- }
- comp = state->comp;
- return OK;
- };
- if (tryAndReportOnError(checkStarting) != OK) {
- return;
- }
-
- c2_status_t err = comp->start();
- if (err != C2_OK) {
- // TODO: convert err into status_t
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- return;
- }
- sp<AMessage> inputFormat;
- sp<AMessage> outputFormat;
- {
- Mutexed<Formats>::Locked formats(mFormats);
- inputFormat = formats->inputFormat;
- outputFormat = formats->outputFormat;
- }
- status_t err2 = mChannel->start(inputFormat, outputFormat);
- if (err2 != OK) {
- mCallback->onError(err2, ACTION_CODE_FATAL);
- return;
- }
-
- auto setRunning = [this] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != STARTING) {
- return UNKNOWN_ERROR;
- }
- state->set(RUNNING);
- return OK;
- };
- if (tryAndReportOnError(setRunning) != OK) {
- return;
- }
- mCallback->onStartCompleted();
-}
-
-void CCodec::initiateShutdown(bool keepComponentAllocated) {
- if (keepComponentAllocated) {
- initiateStop();
- } else {
- initiateRelease();
- }
-}
-
-void CCodec::initiateStop() {
- {
- Mutexed<State>::Locked state(mState);
- if (state->get() == ALLOCATED
- || state->get() == RELEASED
- || state->get() == STOPPING
- || state->get() == RELEASING) {
- // We're already stopped, released, or doing it right now.
- state.unlock();
- mCallback->onStopCompleted();
- state.lock();
- return;
- }
- state->set(STOPPING);
- }
-
- (new AMessage(kWhatStop, this))->post();
-}
-
-void CCodec::stop() {
- std::shared_ptr<C2Component> comp;
- {
- Mutexed<State>::Locked state(mState);
- if (state->get() == RELEASING) {
- state.unlock();
- // We're already stopped or release is in progress.
- mCallback->onStopCompleted();
- state.lock();
- return;
- } else if (state->get() != STOPPING) {
- state.unlock();
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- state.lock();
- return;
- }
- comp = state->comp;
- }
- mChannel->stop();
- status_t err = comp->stop();
- if (err != C2_OK) {
- // TODO: convert err into status_t
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- }
-
- {
- Mutexed<State>::Locked state(mState);
- if (state->get() == STOPPING) {
- state->set(ALLOCATED);
- }
- }
- mCallback->onStopCompleted();
-}
-
-void CCodec::initiateRelease(bool sendCallback /* = true */) {
- {
- Mutexed<State>::Locked state(mState);
- if (state->get() == RELEASED || state->get() == RELEASING) {
- // We're already released or doing it right now.
- if (sendCallback) {
- state.unlock();
- mCallback->onReleaseCompleted();
- state.lock();
- }
- return;
- }
- if (state->get() == ALLOCATING) {
- state->set(RELEASING);
- // With the altered state allocate() would fail and clean up.
- if (sendCallback) {
- state.unlock();
- mCallback->onReleaseCompleted();
- state.lock();
- }
- return;
- }
- state->set(RELEASING);
- }
-
- std::thread([this, sendCallback] { release(sendCallback); }).detach();
-}
-
-void CCodec::release(bool sendCallback) {
- std::shared_ptr<C2Component> comp;
- {
- Mutexed<State>::Locked state(mState);
- if (state->get() == RELEASED) {
- if (sendCallback) {
- state.unlock();
- mCallback->onReleaseCompleted();
- state.lock();
- }
- return;
- }
- comp = state->comp;
- }
- mChannel->stop();
- comp->release();
-
- {
- Mutexed<State>::Locked state(mState);
- state->set(RELEASED);
- state->comp.reset();
- }
- if (sendCallback) {
- mCallback->onReleaseCompleted();
- }
-}
-
-status_t CCodec::setSurface(const sp<Surface> &surface) {
- return mChannel->setSurface(surface);
-}
-
-void CCodec::signalFlush() {
- status_t err = [this] {
- Mutexed<State>::Locked state(mState);
- if (state->get() == FLUSHED) {
- return ALREADY_EXISTS;
- }
- if (state->get() != RUNNING) {
- return UNKNOWN_ERROR;
- }
- state->set(FLUSHING);
- return OK;
- }();
- switch (err) {
- case ALREADY_EXISTS:
- mCallback->onFlushCompleted();
- return;
- case OK:
- break;
- default:
- mCallback->onError(err, ACTION_CODE_FATAL);
- return;
- }
-
- (new AMessage(kWhatFlush, this))->post();
-}
-
-void CCodec::flush() {
- std::shared_ptr<C2Component> comp;
- auto checkFlushing = [this, &comp] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != FLUSHING) {
- return UNKNOWN_ERROR;
- }
- comp = state->comp;
- return OK;
- };
- if (tryAndReportOnError(checkFlushing) != OK) {
- return;
- }
-
- mChannel->stop();
-
- std::list<std::unique_ptr<C2Work>> flushedWork;
- c2_status_t err = comp->flush_sm(C2Component::FLUSH_COMPONENT, &flushedWork);
- if (err != C2_OK) {
- // TODO: convert err into status_t
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- }
-
- mChannel->flush(flushedWork);
-
- {
- Mutexed<State>::Locked state(mState);
- state->set(FLUSHED);
- }
- mCallback->onFlushCompleted();
-}
-
-void CCodec::signalResume() {
- auto setResuming = [this] {
- Mutexed<State>::Locked state(mState);
- if (state->get() != FLUSHED) {
- return UNKNOWN_ERROR;
- }
- state->set(RESUMING);
- return OK;
- };
- if (tryAndReportOnError(setResuming) != OK) {
- return;
- }
-
- (void)mChannel->start(nullptr, nullptr);
-
- {
- Mutexed<State>::Locked state(mState);
- if (state->get() != RESUMING) {
- state.unlock();
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- state.lock();
- return;
- }
- state->set(RUNNING);
- }
-}
-
-void CCodec::signalSetParameters(const sp<AMessage> &msg) {
- // TODO
- (void) msg;
-}
-
-void CCodec::signalEndOfInputStream() {
- // TODO
- mCallback->onSignaledInputEOS(INVALID_OPERATION);
-}
-
-void CCodec::signalRequestIDRFrame() {
- // TODO
-}
-
-void CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
- Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
- queue->splice(queue->end(), workItems);
- (new AMessage(kWhatWorkDone, this))->post();
-}
-
-void CCodec::onMessageReceived(const sp<AMessage> &msg) {
- TimePoint now = std::chrono::steady_clock::now();
- switch (msg->what()) {
- case kWhatAllocate: {
- // C2ComponentStore::createComponent() should return within 100ms.
- setDeadline(now + 150ms, "allocate");
- sp<RefBase> obj;
- CHECK(msg->findObject("codecInfo", &obj));
- allocate((MediaCodecInfo *)obj.get());
- break;
- }
- case kWhatConfigure: {
- // C2Component::commit_sm() should return within 5ms.
- setDeadline(now + 50ms, "configure");
- sp<AMessage> format;
- CHECK(msg->findMessage("format", &format));
- configure(format);
- break;
- }
- case kWhatStart: {
- // C2Component::start() should return within 500ms.
- setDeadline(now + 550ms, "start");
- start();
- break;
- }
- case kWhatStop: {
- // C2Component::stop() should return within 500ms.
- setDeadline(now + 550ms, "stop");
- stop();
- break;
- }
- case kWhatFlush: {
- // C2Component::flush_sm() should return within 5ms.
- setDeadline(now + 50ms, "flush");
- flush();
- break;
- }
- case kWhatCreateInputSurface: {
- // Surface operations may be briefly blocking.
- setDeadline(now + 100ms, "createInputSurface");
- createInputSurface();
- break;
- }
- case kWhatSetInputSurface: {
- // Surface operations may be briefly blocking.
- setDeadline(now + 100ms, "setInputSurface");
- sp<RefBase> obj;
- CHECK(msg->findObject("surface", &obj));
- sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
- setInputSurface(surface);
- break;
- }
- case kWhatWorkDone: {
- std::unique_ptr<C2Work> work;
- {
- Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
- if (queue->empty()) {
- break;
- }
- work.swap(queue->front());
- queue->pop_front();
- if (!queue->empty()) {
- (new AMessage(kWhatWorkDone, this))->post();
- }
- }
- mChannel->onWorkDone(work);
- break;
- }
- default: {
- ALOGE("unrecognized message");
- break;
- }
- }
- setDeadline(TimePoint::max(), "none");
-}
-
-void CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
- Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
- deadline->set(newDeadline, name);
-}
-
-void CCodec::initiateReleaseIfStuck() {
- std::string name;
- {
- Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
- if (deadline->get() >= std::chrono::steady_clock::now()) {
- // We're not stuck.
- return;
- }
- name = deadline->getName();
- }
-
- ALOGW("previous call to %s exceeded timeout", name.c_str());
- initiateRelease(false);
- mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
-}
-
-} // namespace android
-
-extern "C" android::CodecBase *CreateCodec() {
- return new android::CCodec;
-}
diff --git a/media/libstagefright/CCodecBufferChannel.cpp b/media/libstagefright/CCodecBufferChannel.cpp
deleted file mode 100644
index cbe4f16..0000000
--- a/media/libstagefright/CCodecBufferChannel.cpp
+++ /dev/null
@@ -1,1570 +0,0 @@
-/*
- * 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "CCodecBufferChannel"
-#include <utils/Log.h>
-
-#include <numeric>
-#include <thread>
-
-#include <C2AllocatorGralloc.h>
-#include <C2PlatformSupport.h>
-#include <C2BlockInternal.h>
-
-#include <android/hardware/cas/native/1.0/IDescrambler.h>
-#include <binder/MemoryDealer.h>
-#include <gui/Surface.h>
-#include <media/openmax/OMX_Core.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/MediaCodec.h>
-#include <media/MediaCodecBuffer.h>
-#include <system/window.h>
-
-#include "include/CCodecBufferChannel.h"
-#include "include/Codec2Buffer.h"
-#include "include/SecureBuffer.h"
-#include "include/SharedMemoryBuffer.h"
-
-namespace android {
-
-using hardware::hidl_handle;
-using hardware::hidl_string;
-using hardware::hidl_vec;
-using namespace hardware::cas::V1_0;
-using namespace hardware::cas::native::V1_0;
-
-using CasStatus = hardware::cas::V1_0::Status;
-
-/**
- * Base class for representation of buffers at one port.
- */
-class CCodecBufferChannel::Buffers {
-public:
- Buffers() = default;
- virtual ~Buffers() = default;
-
- /**
- * Set format for MediaCodec-facing buffers.
- */
- void setFormat(const sp<AMessage> &format) {
- CHECK(format != nullptr);
- mFormat = format;
- }
-
- /**
- * Returns true if the buffers are operating under array mode.
- */
- virtual bool isArrayMode() const { return false; }
-
- /**
- * Fills the vector with MediaCodecBuffer's if in array mode; otherwise,
- * no-op.
- */
- virtual void getArray(Vector<sp<MediaCodecBuffer>> *) const {}
-
-protected:
- // Format to be used for creating MediaCodec-facing buffers.
- sp<AMessage> mFormat;
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(Buffers);
-};
-
-class CCodecBufferChannel::InputBuffers : public CCodecBufferChannel::Buffers {
-public:
- InputBuffers() = default;
- virtual ~InputBuffers() = default;
-
- /**
- * Set a block pool to obtain input memory blocks.
- */
- void setPool(const std::shared_ptr<C2BlockPool> &pool) { mPool = pool; }
-
- /**
- * Get a new MediaCodecBuffer for input and its corresponding index.
- * Returns false if no new buffer can be obtained at the moment.
- */
- virtual bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) = 0;
-
- /**
- * Release the buffer obtained from requestNewBuffer() and get the
- * associated C2Buffer object back. Returns empty shared_ptr if the
- * buffer is not on file.
- */
- virtual std::shared_ptr<C2Buffer> releaseBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
-
- /**
- * Flush internal state. After this call, no index or buffer previously
- * returned from requestNewBuffer() is valid.
- */
- virtual void flush() = 0;
-
- /**
- * Return array-backed version of input buffers. The returned object
- * shall retain the internal state so that it will honor index and
- * buffer from previous calls of requestNewBuffer().
- */
- virtual std::unique_ptr<InputBuffers> toArrayMode() = 0;
-
-protected:
- // Pool to obtain blocks for input buffers.
- std::shared_ptr<C2BlockPool> mPool;
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(InputBuffers);
-};
-
-class CCodecBufferChannel::OutputBuffers : public CCodecBufferChannel::Buffers {
-public:
- OutputBuffers() = default;
- virtual ~OutputBuffers() = default;
-
- /**
- * Register output C2Buffer from the component and obtain corresponding
- * index and MediaCodecBuffer object. Returns false if registration
- * fails.
- */
- virtual bool registerBuffer(
- const std::shared_ptr<C2Buffer> &buffer,
- size_t *index,
- sp<MediaCodecBuffer> *clientBuffer) = 0;
-
- /**
- * Register codec specific data as a buffer to be consistent with
- * MediaCodec behavior.
- */
- virtual bool registerCsd(
- const C2StreamCsdInfo::output * /* csd */,
- size_t * /* index */,
- sp<MediaCodecBuffer> * /* clientBuffer */) = 0;
-
- /**
- * Release the buffer obtained from registerBuffer() and get the
- * associated C2Buffer object back. Returns empty shared_ptr if the
- * buffer is not on file.
- */
- virtual std::shared_ptr<C2Buffer> releaseBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
-
- /**
- * Flush internal state. After this call, no index or buffer previously
- * returned from registerBuffer() is valid.
- */
- virtual void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) = 0;
-
- /**
- * Return array-backed version of output buffers. The returned object
- * shall retain the internal state so that it will honor index and
- * buffer from previous calls of registerBuffer().
- */
- virtual std::unique_ptr<OutputBuffers> toArrayMode() = 0;
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers);
-};
-
-namespace {
-
-// TODO: get this info from component
-const static size_t kMinBufferArraySize = 16;
-const static size_t kLinearBufferSize = 524288;
-const static size_t kMaxGraphicBufferRefCount = 4;
-
-/**
- * Simple local buffer pool backed by std::vector.
- */
-class LocalBufferPool : public std::enable_shared_from_this<LocalBufferPool> {
-public:
- /**
- * Create a new LocalBufferPool object.
- *
- * \param poolCapacity max total size of buffers managed by this pool.
- *
- * \return a newly created pool object.
- */
- static std::shared_ptr<LocalBufferPool> Create(size_t poolCapacity) {
- return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(poolCapacity));
- }
-
- /**
- * Return an ABuffer object whose size is at least |capacity|.
- *
- * \param capacity requested capacity
- * \return nullptr if the pool capacity is reached
- * an ABuffer object otherwise.
- */
- sp<ABuffer> newBuffer(size_t capacity) {
- Mutex::Autolock lock(mMutex);
- auto it = std::find_if(
- mPool.begin(), mPool.end(),
- [capacity](const std::vector<uint8_t> &vec) {
- return vec.capacity() >= capacity;
- });
- if (it != mPool.end()) {
- sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
- mPool.erase(it);
- return buffer;
- }
- if (mUsedSize + capacity > mPoolCapacity) {
- while (!mPool.empty()) {
- mUsedSize -= mPool.back().capacity();
- mPool.pop_back();
- }
- if (mUsedSize + capacity > mPoolCapacity) {
- ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
- mUsedSize, capacity, mPoolCapacity);
- return nullptr;
- }
- }
- std::vector<uint8_t> vec(capacity);
- mUsedSize += vec.capacity();
- return new VectorBuffer(std::move(vec), shared_from_this());
- }
-
-private:
- /**
- * ABuffer backed by std::vector.
- */
- class VectorBuffer : public ::android::ABuffer {
- public:
- /**
- * Construct a VectorBuffer by taking the ownership of supplied vector.
- *
- * \param vec backing vector of the buffer. this object takes
- * ownership at construction.
- * \param pool a LocalBufferPool object to return the vector at
- * destruction.
- */
- VectorBuffer(std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
- : ABuffer(vec.data(), vec.capacity()),
- mVec(std::move(vec)),
- mPool(pool) {
- }
-
- ~VectorBuffer() override {
- std::shared_ptr<LocalBufferPool> pool = mPool.lock();
- if (pool) {
- // If pool is alive, return the vector back to the pool so that
- // it can be recycled.
- pool->returnVector(std::move(mVec));
- }
- }
-
- private:
- std::vector<uint8_t> mVec;
- std::weak_ptr<LocalBufferPool> mPool;
- };
-
- Mutex mMutex;
- size_t mPoolCapacity;
- size_t mUsedSize;
- std::list<std::vector<uint8_t>> mPool;
-
- /**
- * Private constructor to prevent constructing non-managed LocalBufferPool.
- */
- explicit LocalBufferPool(size_t poolCapacity)
- : mPoolCapacity(poolCapacity), mUsedSize(0) {
- }
-
- /**
- * Take back the ownership of vec from the destructed VectorBuffer and put
- * it in front of the pool.
- */
- void returnVector(std::vector<uint8_t> &&vec) {
- Mutex::Autolock lock(mMutex);
- mPool.push_front(std::move(vec));
- }
-
- DISALLOW_EVIL_CONSTRUCTORS(LocalBufferPool);
-};
-
-sp<GraphicBlockBuffer> AllocateGraphicBuffer(
- const std::shared_ptr<C2BlockPool> &pool,
- const sp<AMessage> &format,
- uint32_t pixelFormat,
- const C2MemoryUsage &usage,
- const std::shared_ptr<LocalBufferPool> &localBufferPool) {
- int32_t width, height;
- if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
- ALOGD("format lacks width or height");
- return nullptr;
- }
-
- std::shared_ptr<C2GraphicBlock> block;
- c2_status_t err = pool->fetchGraphicBlock(
- width, height, pixelFormat, usage, &block);
- if (err != C2_OK) {
- ALOGD("fetch graphic block failed: %d", err);
- return nullptr;
- }
-
- return GraphicBlockBuffer::Allocate(
- format,
- block,
- [localBufferPool](size_t capacity) {
- return localBufferPool->newBuffer(capacity);
- });
-}
-
-class BuffersArrayImpl;
-
-/**
- * Flexible buffer slots implementation.
- */
-class FlexBuffersImpl {
-public:
- FlexBuffersImpl() = default;
-
- /**
- * Assign an empty slot for a buffer and return the index. If there's no
- * empty slot, just add one at the end and return it.
- *
- * \param buffer[in] a new buffer to assign a slot.
- * \return index of the assigned slot.
- */
- size_t assignSlot(const sp<Codec2Buffer> &buffer) {
- for (size_t i = 0; i < mBuffers.size(); ++i) {
- if (mBuffers[i].clientBuffer.promote() == nullptr
- && mBuffers[i].compBuffer.expired()) {
- mBuffers[i].clientBuffer = buffer;
- return i;
- }
- }
- mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
- return mBuffers.size() - 1;
- }
-
- /**
- * Release the slot from the client, and get the C2Buffer object back from
- * the previously assigned buffer. Note that the slot is not completely free
- * until the returned C2Buffer object is freed.
- *
- * \param buffer[in] the buffer previously assigned a slot.
- * \return C2Buffer object from |buffer|.
- */
- std::shared_ptr<C2Buffer> releaseSlot(const sp<MediaCodecBuffer> &buffer) {
- sp<Codec2Buffer> c2Buffer;
- size_t index = mBuffers.size();
- for (size_t i = 0; i < mBuffers.size(); ++i) {
- if (mBuffers[i].clientBuffer.promote() == buffer) {
- c2Buffer = mBuffers[i].clientBuffer.promote();
- index = i;
- break;
- }
- }
- if (c2Buffer == nullptr) {
- ALOGD("No matching buffer found");
- return nullptr;
- }
- std::shared_ptr<C2Buffer> result = c2Buffer->asC2Buffer();
- mBuffers[index].compBuffer = result;
- return result;
- }
-
-private:
- friend class BuffersArrayImpl;
-
- struct Entry {
- wp<Codec2Buffer> clientBuffer;
- std::weak_ptr<C2Buffer> compBuffer;
- };
- std::vector<Entry> mBuffers;
-};
-
-/**
- * Static buffer slots implementation based on a fixed-size array.
- */
-class BuffersArrayImpl {
-public:
- /**
- * Initialize buffer array from the original |impl|. The buffers known by
- * the client is preserved, and the empty slots are populated so that the
- * array size is at least |minSize|.
- *
- * \param impl[in] FlexBuffersImpl object used so far.
- * \param minSize[in] minimum size of the buffer array.
- * \param allocate[in] function to allocate a client buffer for an empty slot.
- */
- void initialize(
- const FlexBuffersImpl &impl,
- size_t minSize,
- std::function<sp<Codec2Buffer>()> allocate) {
- for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
- sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer.promote();
- bool ownedByClient = (clientBuffer != nullptr);
- if (!ownedByClient) {
- clientBuffer = allocate();
- }
- mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
- }
- for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
- mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
- }
- }
-
- /**
- * Grab a buffer from the underlying array which matches the criteria.
- *
- * \param index[out] index of the slot.
- * \param buffer[out] the matching buffer.
- * \param match[in] a function to test whether the buffer matches the
- * criteria or not.
- * \return OK if successful,
- * NO_MEMORY if there's no available slot meets the criteria.
- */
- status_t grabBuffer(
- size_t *index,
- sp<Codec2Buffer> *buffer,
- std::function<bool(const sp<Codec2Buffer> &)> match =
- [](const sp<Codec2Buffer> &) { return true; }) {
- for (size_t i = 0; i < mBuffers.size(); ++i) {
- if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()
- && match(mBuffers[i].clientBuffer)) {
- mBuffers[i].ownedByClient = true;
- *buffer = mBuffers[i].clientBuffer;
- (*buffer)->meta()->clear();
- (*buffer)->setRange(0, (*buffer)->capacity());
- *index = i;
- return OK;
- }
- }
- return NO_MEMORY;
- }
-
- /**
- * Return the buffer from the client, and get the C2Buffer object back from
- * the buffer. Note that the slot is not completely free until the returned
- * C2Buffer object is freed.
- *
- * \param buffer[in] the buffer previously grabbed.
- * \return C2Buffer object from |buffer|.
- */
- std::shared_ptr<C2Buffer> returnBuffer(const sp<MediaCodecBuffer> &buffer) {
- sp<Codec2Buffer> c2Buffer;
- size_t index = mBuffers.size();
- for (size_t i = 0; i < mBuffers.size(); ++i) {
- if (mBuffers[i].clientBuffer == buffer) {
- if (!mBuffers[i].ownedByClient) {
- ALOGD("Client returned a buffer it does not own according to our record: %zu", i);
- }
- c2Buffer = mBuffers[i].clientBuffer;
- mBuffers[i].ownedByClient = false;
- index = i;
- break;
- }
- }
- if (c2Buffer == nullptr) {
- ALOGD("No matching buffer found");
- return nullptr;
- }
- std::shared_ptr<C2Buffer> result = c2Buffer->asC2Buffer();
- mBuffers[index].compBuffer = result;
- return result;
- }
-
- /**
- * Populate |array| with the underlying buffer array.
- *
- * \param array[out] an array to be filled with the underlying buffer array.
- */
- void getArray(Vector<sp<MediaCodecBuffer>> *array) const {
- array->clear();
- for (const Entry &entry : mBuffers) {
- array->push(entry.clientBuffer);
- }
- }
-
- /**
- * The client abandoned all known buffers, so reclaim the ownership.
- */
- void flush() {
- for (Entry &entry : mBuffers) {
- entry.ownedByClient = false;
- }
- }
-
-private:
- struct Entry {
- const sp<Codec2Buffer> clientBuffer;
- std::weak_ptr<C2Buffer> compBuffer;
- bool ownedByClient;
- };
- std::vector<Entry> mBuffers;
-};
-
-class InputBuffersArray : public CCodecBufferChannel::InputBuffers {
-public:
- InputBuffersArray() = default;
- ~InputBuffersArray() override = default;
-
- void initialize(
- const FlexBuffersImpl &impl,
- size_t minSize,
- std::function<sp<Codec2Buffer>()> allocate) {
- mImpl.initialize(impl, minSize, allocate);
- }
-
- bool isArrayMode() const final { return true; }
-
- std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
- return nullptr;
- }
-
- void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
- mImpl.getArray(array);
- }
-
- bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
- sp<Codec2Buffer> c2Buffer;
- status_t err = mImpl.grabBuffer(index, &c2Buffer);
- if (err == OK) {
- c2Buffer->setFormat(mFormat);
- *buffer = c2Buffer;
- return true;
- }
- return false;
- }
-
- std::shared_ptr<C2Buffer> releaseBuffer(const sp<MediaCodecBuffer> &buffer) override {
- return mImpl.returnBuffer(buffer);
- }
-
- void flush() override {
- mImpl.flush();
- }
-
-private:
- BuffersArrayImpl mImpl;
-};
-
-class LinearInputBuffers : public CCodecBufferChannel::InputBuffers {
-public:
- using CCodecBufferChannel::InputBuffers::InputBuffers;
-
- bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
- // TODO: proper max input size
- // TODO: read usage from intf
- sp<Codec2Buffer> newBuffer = alloc(kLinearBufferSize);
- if (newBuffer == nullptr) {
- return false;
- }
- *index = mImpl.assignSlot(newBuffer);
- *buffer = newBuffer;
- return true;
- }
-
- std::shared_ptr<C2Buffer> releaseBuffer(const sp<MediaCodecBuffer> &buffer) override {
- return mImpl.releaseSlot(buffer);
- }
-
- void flush() override {
- // This is no-op by default unless we're in array mode where we need to keep
- // track of the flushed work.
- }
-
- std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
- std::unique_ptr<InputBuffersArray> array(new InputBuffersArray);
- array->setFormat(mFormat);
- array->initialize(
- mImpl,
- kMinBufferArraySize,
- [this] () -> sp<Codec2Buffer> { return alloc(kLinearBufferSize); });
- return std::move(array);
- }
-
- virtual sp<Codec2Buffer> alloc(size_t size) const {
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- std::shared_ptr<C2LinearBlock> block;
-
- c2_status_t err = mPool->fetchLinearBlock(size, usage, &block);
- if (err != C2_OK) {
- return nullptr;
- }
-
- return LinearBlockBuffer::Allocate(mFormat, block);
- }
-
-private:
- FlexBuffersImpl mImpl;
-};
-
-class EncryptedLinearInputBuffers : public LinearInputBuffers {
-public:
- EncryptedLinearInputBuffers(
- bool secure,
- const sp<MemoryDealer> &dealer,
- const sp<ICrypto> &crypto,
- int32_t heapSeqNum)
- : mUsage({0, 0}),
- mDealer(dealer),
- mCrypto(crypto),
- mHeapSeqNum(heapSeqNum) {
- if (secure) {
- mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
- } else {
- mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- }
- for (size_t i = 0; i < kMinBufferArraySize; ++i) {
- sp<IMemory> memory = mDealer->allocate(kLinearBufferSize);
- if (memory == nullptr) {
- ALOGD("Failed to allocate memory from dealer: only %zu slots allocated", i);
- break;
- }
- mMemoryVector.push_back({std::weak_ptr<C2LinearBlock>(), memory});
- }
- }
-
- ~EncryptedLinearInputBuffers() override {
- }
-
- sp<Codec2Buffer> alloc(size_t size) const override {
- sp<IMemory> memory;
- for (const Entry &entry : mMemoryVector) {
- if (entry.block.expired()) {
- memory = entry.memory;
- break;
- }
- }
- if (memory == nullptr) {
- return nullptr;
- }
-
- std::shared_ptr<C2LinearBlock> block;
- c2_status_t err = mPool->fetchLinearBlock(size, mUsage, &block);
- if (err != C2_OK) {
- return nullptr;
- }
-
- return new EncryptedLinearBlockBuffer(mFormat, block, memory, mHeapSeqNum);
- }
-
-private:
- C2MemoryUsage mUsage;
- sp<MemoryDealer> mDealer;
- sp<ICrypto> mCrypto;
- int32_t mHeapSeqNum;
- struct Entry {
- std::weak_ptr<C2LinearBlock> block;
- sp<IMemory> memory;
- };
- std::vector<Entry> mMemoryVector;
-};
-
-class GraphicInputBuffers : public CCodecBufferChannel::InputBuffers {
-public:
- GraphicInputBuffers() : mLocalBufferPool(LocalBufferPool::Create(1920 * 1080 * 16)) {}
- ~GraphicInputBuffers() override = default;
-
- bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override {
- // TODO: proper max input size
- // TODO: read usage from intf
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- sp<GraphicBlockBuffer> newBuffer = AllocateGraphicBuffer(
- mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
- if (newBuffer == nullptr) {
- return false;
- }
- *index = mImpl.assignSlot(newBuffer);
- *buffer = newBuffer;
- return true;
- }
-
- std::shared_ptr<C2Buffer> releaseBuffer(const sp<MediaCodecBuffer> &buffer) override {
- return mImpl.releaseSlot(buffer);
- }
-
- void flush() override {
- // This is no-op by default unless we're in array mode where we need to keep
- // track of the flushed work.
- }
-
- std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
- std::unique_ptr<InputBuffersArray> array(new InputBuffersArray);
- array->setFormat(mFormat);
- array->initialize(
- mImpl,
- kMinBufferArraySize,
- [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- return AllocateGraphicBuffer(
- pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
- });
- return std::move(array);
- }
-
-private:
- FlexBuffersImpl mImpl;
- std::shared_ptr<LocalBufferPool> mLocalBufferPool;
-};
-
-class DummyInputBuffers : public CCodecBufferChannel::InputBuffers {
-public:
- DummyInputBuffers() = default;
-
- bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override {
- return false;
- }
-
- std::shared_ptr<C2Buffer> releaseBuffer(const sp<MediaCodecBuffer> &) override {
- return nullptr;
- }
-
- void flush() override {
- }
-
- std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode() final {
- return nullptr;
- }
-
- bool isArrayMode() const final { return true; }
-
- void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
- array->clear();
- }
-};
-
-class OutputBuffersArray : public CCodecBufferChannel::OutputBuffers {
-public:
- OutputBuffersArray() = default;
- ~OutputBuffersArray() override = default;
-
- void initialize(
- const FlexBuffersImpl &impl,
- size_t minSize,
- std::function<sp<Codec2Buffer>()> allocate) {
- mImpl.initialize(impl, minSize, allocate);
- }
-
- bool isArrayMode() const final { return true; }
-
- std::unique_ptr<CCodecBufferChannel::OutputBuffers> toArrayMode() final {
- return nullptr;
- }
-
- bool registerBuffer(
- const std::shared_ptr<C2Buffer> &buffer,
- size_t *index,
- sp<MediaCodecBuffer> *clientBuffer) final {
- sp<Codec2Buffer> c2Buffer;
- status_t err = mImpl.grabBuffer(
- index,
- &c2Buffer,
- [buffer](const sp<Codec2Buffer> &clientBuffer) {
- return clientBuffer->canCopy(buffer);
- });
- if (err != OK) {
- ALOGD("grabBuffer failed: %d", err);
- return false;
- }
- c2Buffer->setFormat(mFormat);
- if (!c2Buffer->copy(buffer)) {
- ALOGD("copy buffer failed");
- return false;
- }
- *clientBuffer = c2Buffer;
- return true;
- }
-
- bool registerCsd(
- const C2StreamCsdInfo::output *csd,
- size_t *index,
- sp<MediaCodecBuffer> *clientBuffer) final {
- sp<Codec2Buffer> c2Buffer;
- status_t err = mImpl.grabBuffer(
- index,
- &c2Buffer,
- [csd](const sp<Codec2Buffer> &clientBuffer) {
- return clientBuffer->base() != nullptr
- && clientBuffer->capacity() >= csd->flexCount();
- });
- if (err != OK) {
- return false;
- }
- // TODO: proper format update
- sp<ABuffer> csdBuffer = ABuffer::CreateAsCopy(csd->m.value, csd->flexCount());
- mFormat = mFormat->dup();
- mFormat->setBuffer("csd-0", csdBuffer);
-
- memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
- c2Buffer->setRange(0, csd->flexCount());
- c2Buffer->setFormat(mFormat);
- *clientBuffer = c2Buffer;
- return true;
- }
-
- std::shared_ptr<C2Buffer> releaseBuffer(const sp<MediaCodecBuffer> &buffer) final {
- return mImpl.returnBuffer(buffer);
- }
-
- void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) override {
- (void) flushedWork;
- mImpl.flush();
- }
-
- void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
- mImpl.getArray(array);
- }
-
-private:
- BuffersArrayImpl mImpl;
-};
-
-class FlexOutputBuffers : public CCodecBufferChannel::OutputBuffers {
-public:
- using CCodecBufferChannel::OutputBuffers::OutputBuffers;
-
- bool registerBuffer(
- const std::shared_ptr<C2Buffer> &buffer,
- size_t *index,
- sp<MediaCodecBuffer> *clientBuffer) override {
- sp<Codec2Buffer> newBuffer = wrap(buffer);
- newBuffer->setFormat(mFormat);
- *index = mImpl.assignSlot(newBuffer);
- *clientBuffer = newBuffer;
- return true;
- }
-
- bool registerCsd(
- const C2StreamCsdInfo::output *csd,
- size_t *index,
- sp<MediaCodecBuffer> *clientBuffer) final {
- // TODO: proper format update
- sp<ABuffer> csdBuffer = ABuffer::CreateAsCopy(csd->m.value, csd->flexCount());
- mFormat = mFormat->dup();
- mFormat->setBuffer("csd-0", csdBuffer);
-
- sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(mFormat, csdBuffer);
- *index = mImpl.assignSlot(newBuffer);
- *clientBuffer = newBuffer;
- return true;
- }
-
- std::shared_ptr<C2Buffer> releaseBuffer(
- const sp<MediaCodecBuffer> &buffer) override {
- return mImpl.releaseSlot(buffer);
- }
-
- void flush(
- const std::list<std::unique_ptr<C2Work>> &flushedWork) override {
- (void) flushedWork;
- // This is no-op by default unless we're in array mode where we need to keep
- // track of the flushed work.
- }
-
- std::unique_ptr<CCodecBufferChannel::OutputBuffers> toArrayMode() override {
- std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray);
- array->setFormat(mFormat);
- array->initialize(
- mImpl,
- kMinBufferArraySize,
- [this]() { return allocateArrayBuffer(); });
- return std::move(array);
- }
-
- /**
- * Return an appropriate Codec2Buffer object for the type of buffers.
- *
- * \param buffer C2Buffer object to wrap.
- *
- * \return appropriate Codec2Buffer object to wrap |buffer|.
- */
- virtual sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) = 0;
-
- /**
- * Return an appropriate Codec2Buffer object for the type of buffers, to be
- * used as an empty array buffer.
- *
- * \return appropriate Codec2Buffer object which can copy() from C2Buffers.
- */
- virtual sp<Codec2Buffer> allocateArrayBuffer() = 0;
-
-private:
- FlexBuffersImpl mImpl;
-};
-
-class LinearOutputBuffers : public FlexOutputBuffers {
-public:
- using FlexOutputBuffers::FlexOutputBuffers;
-
- sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override {
- if (buffer == nullptr) {
- return new DummyContainerBuffer(mFormat, buffer);
- }
- if (buffer->data().type() != C2BufferData::LINEAR) {
- // We expect linear output buffers from the component.
- return nullptr;
- }
- if (buffer->data().linearBlocks().size() != 1u) {
- // We expect one and only one linear block from the component.
- return nullptr;
- }
- return ConstLinearBlockBuffer::Allocate(mFormat, buffer);
- }
-
- sp<Codec2Buffer> allocateArrayBuffer() override {
- // TODO: proper max output size
- return new LocalLinearBuffer(mFormat, new ABuffer(kLinearBufferSize));
- }
-};
-
-class GraphicOutputBuffers : public FlexOutputBuffers {
-public:
- using FlexOutputBuffers::FlexOutputBuffers;
-
- sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override {
- return new DummyContainerBuffer(mFormat, buffer);
- }
-
- sp<Codec2Buffer> allocateArrayBuffer() override {
- return new DummyContainerBuffer(mFormat);
- }
-};
-
-class RawGraphicOutputBuffers : public FlexOutputBuffers {
-public:
- RawGraphicOutputBuffers()
- : mLocalBufferPool(LocalBufferPool::Create(1920 * 1080 * 16)) {
- }
- ~RawGraphicOutputBuffers() override = default;
-
- sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override {
- return ConstGraphicBlockBuffer::Allocate(
- mFormat,
- buffer,
- [lbp = mLocalBufferPool](size_t capacity) {
- return lbp->newBuffer(capacity);
- });
- }
-
- sp<Codec2Buffer> allocateArrayBuffer() override {
- return ConstGraphicBlockBuffer::AllocateEmpty(
- mFormat,
- [lbp = mLocalBufferPool](size_t capacity) {
- return lbp->newBuffer(capacity);
- });
- }
-
-private:
- std::shared_ptr<LocalBufferPool> mLocalBufferPool;
-};
-
-} // namespace
-
-CCodecBufferChannel::QueueGuard::QueueGuard(
- CCodecBufferChannel::QueueSync &sync) : mSync(sync) {
- std::unique_lock<std::mutex> l(mSync.mMutex);
- // At this point it's guaranteed that mSync is not under state transition,
- // as we are holding its mutex.
- if (mSync.mCount == -1) {
- mRunning = false;
- } else {
- ++mSync.mCount;
- mRunning = true;
- }
-}
-
-CCodecBufferChannel::QueueGuard::~QueueGuard() {
- if (mRunning) {
- // We are not holding mutex at this point so that QueueSync::stop() can
- // keep holding the lock until mCount reaches zero.
- --mSync.mCount;
- }
-}
-
-void CCodecBufferChannel::QueueSync::start() {
- std::unique_lock<std::mutex> l(mMutex);
- // If stopped, it goes to running state; otherwise no-op.
- int32_t expected = -1;
- (void)mCount.compare_exchange_strong(expected, 0);
-}
-
-void CCodecBufferChannel::QueueSync::stop() {
- std::unique_lock<std::mutex> l(mMutex);
- if (mCount == -1) {
- // no-op
- return;
- }
- // Holding mutex here blocks creation of additional QueueGuard objects, so
- // mCount can only decrement. In other words, threads that acquired the lock
- // are allowed to finish execution but additional threads trying to acquire
- // the lock at this point will block, and then get QueueGuard at STOPPED
- // state.
- int32_t expected = 0;
- while (!mCount.compare_exchange_weak(expected, -1)) {
- std::this_thread::yield();
- }
-}
-
-CCodecBufferChannel::CCodecBufferChannel(
- const std::function<void(status_t, enum ActionCode)> &onError)
- : mHeapSeqNum(-1),
- mOnError(onError),
- mFrameIndex(0u),
- mFirstValidFrameIndex(0u) {
-}
-
-CCodecBufferChannel::~CCodecBufferChannel() {
- if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
- mCrypto->unsetHeap(mHeapSeqNum);
- }
-}
-
-void CCodecBufferChannel::setComponent(const std::shared_ptr<C2Component> &component) {
- mComponent = component;
-}
-
-status_t CCodecBufferChannel::setInputSurface(
- const std::shared_ptr<InputSurfaceWrapper> &surface) {
- ALOGV("setInputSurface");
- mInputSurface = surface;
- return OK;
-}
-
-status_t CCodecBufferChannel::queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer) {
- int64_t timeUs;
- CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-
- int32_t flags = 0;
- int32_t tmp = 0;
- if (buffer->meta()->findInt32("eos", &tmp) && tmp) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("input EOS");
- }
- if (buffer->meta()->findInt32("csd", &tmp) && tmp) {
- flags |= C2FrameData::FLAG_CODEC_CONFIG;
- }
- ALOGV("queueInputBuffer: buffer->size() = %zu", buffer->size());
- std::unique_ptr<C2Work> work(new C2Work);
- work->input.flags = (C2FrameData::flags_t)flags;
- work->input.ordinal.timestamp = timeUs;
- work->input.ordinal.frameIndex = mFrameIndex++;
- work->input.buffers.clear();
- {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- std::shared_ptr<C2Buffer> c2buffer = (*buffers)->releaseBuffer(buffer);
- if (!c2buffer) {
- return -ENOENT;
- }
- work->input.buffers.push_back(c2buffer);
- }
- // TODO: fill info's
-
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
-
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
- return mComponent->queue_nb(&items);
-}
-
-status_t CCodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
- QueueGuard guard(mSync);
- if (!guard.isRunning()) {
- ALOGW("No more buffers should be queued at current state.");
- return -ENOSYS;
- }
- return queueInputBufferInternal(buffer);
-}
-
-status_t CCodecBufferChannel::queueSecureInputBuffer(
- const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
- const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
- const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- AString *errorDetailMsg) {
- QueueGuard guard(mSync);
- if (!guard.isRunning()) {
- ALOGW("No more buffers should be queued at current state.");
- return -ENOSYS;
- }
-
- if (!hasCryptoOrDescrambler()) {
- return -ENOSYS;
- }
- sp<EncryptedLinearBlockBuffer> encryptedBuffer((EncryptedLinearBlockBuffer *)buffer.get());
-
- ssize_t result = -1;
- if (mCrypto != nullptr) {
- ICrypto::DestinationBuffer destination;
- if (secure) {
- destination.mType = ICrypto::kDestinationTypeNativeHandle;
- destination.mHandle = encryptedBuffer->handle();
- } else {
- destination.mType = ICrypto::kDestinationTypeSharedMemory;
- destination.mSharedMemory = mDecryptDestination;
- }
- ICrypto::SourceBuffer source;
- encryptedBuffer->fillSourceBuffer(&source);
- result = mCrypto->decrypt(
- key, iv, mode, pattern, source, buffer->offset(),
- subSamples, numSubSamples, destination, errorDetailMsg);
- if (result < 0) {
- return result;
- }
- if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
- encryptedBuffer->copyDecryptedContent(mDecryptDestination, result);
- }
- } else {
- // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
- // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
- hidl_vec<SubSample> hidlSubSamples;
- hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
-
- hardware::cas::native::V1_0::SharedBuffer srcBuffer;
- encryptedBuffer->fillSourceBuffer(&srcBuffer);
-
- DestinationBuffer dstBuffer;
- if (secure) {
- dstBuffer.type = BufferType::NATIVE_HANDLE;
- dstBuffer.secureMemory = hidl_handle(encryptedBuffer->handle());
- } else {
- dstBuffer.type = BufferType::SHARED_MEMORY;
- dstBuffer.nonsecureMemory = srcBuffer;
- }
-
- CasStatus status = CasStatus::OK;
- hidl_string detailedError;
-
- auto returnVoid = mDescrambler->descramble(
- key != NULL ? (ScramblingControl)key[0] : ScramblingControl::UNSCRAMBLED,
- hidlSubSamples,
- srcBuffer,
- 0,
- dstBuffer,
- 0,
- [&status, &result, &detailedError] (
- CasStatus _status, uint32_t _bytesWritten,
- const hidl_string& _detailedError) {
- status = _status;
- result = (ssize_t)_bytesWritten;
- detailedError = _detailedError;
- });
-
- if (!returnVoid.isOk() || status != CasStatus::OK || result < 0) {
- ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
- returnVoid.description().c_str(), status, result);
- return UNKNOWN_ERROR;
- }
-
- ALOGV("descramble succeeded, %zd bytes", result);
-
- if (dstBuffer.type == BufferType::SHARED_MEMORY) {
- encryptedBuffer->copyDecryptedContentFromMemory(result);
- }
- }
-
- buffer->setRange(0, result);
- return queueInputBufferInternal(buffer);
-}
-
-void CCodecBufferChannel::feedInputBufferIfAvailable() {
- sp<MediaCodecBuffer> inBuffer;
- size_t index;
- {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- if (!(*buffers)->requestNewBuffer(&index, &inBuffer)) {
- ALOGV("no new buffer available");
- inBuffer = nullptr;
- return;
- }
- }
- ALOGV("new input index = %zu", index);
- mCallback->onInputBufferAvailable(index, inBuffer);
-}
-
-status_t CCodecBufferChannel::renderOutputBuffer(
- const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
- ALOGV("renderOutputBuffer");
- feedInputBufferIfAvailable();
-
- std::shared_ptr<C2Buffer> c2Buffer;
- {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- c2Buffer = (*buffers)->releaseBuffer(buffer);
- }
-
- Mutexed<OutputSurface>::Locked output(mOutputSurface);
- if (output->surface == nullptr) {
- ALOGE("no surface");
- return OK;
- }
-
- std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
- if (blocks.size() != 1u) {
- ALOGE("# of graphic blocks expected to be 1, but %zu", blocks.size());
- return UNKNOWN_ERROR;
- }
-
- native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(blocks.front().handle());
- sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(
- grallocHandle,
- GraphicBuffer::CLONE_HANDLE,
- blocks.front().width(),
- blocks.front().height(),
- HAL_PIXEL_FORMAT_YCbCr_420_888,
- // TODO
- 1,
- (uint64_t)GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
- // TODO
- blocks.front().width()));
- native_handle_delete(grallocHandle);
-
- status_t result = output->surface->attachBuffer(graphicBuffer.get());
- if (result != OK) {
- ALOGE("attachBuffer failed: %d", result);
- return result;
- }
-
- // TODO: read and set crop
-
- result = native_window_set_buffers_timestamp(output->surface.get(), timestampNs);
- ALOGW_IF(result != OK, "failed to set buffer timestamp: %d", result);
-
- // TODO: fix after C2Fence implementation
-#if 0
- const C2Fence &fence = blocks.front().fence();
- result = ((ANativeWindow *)output->surface.get())->queueBuffer(
- output->surface.get(), graphicBuffer.get(), fence.valid() ? fence.fd() : -1);
-#else
- result = ((ANativeWindow *)output->surface.get())->queueBuffer(
- output->surface.get(), graphicBuffer.get(), -1);
-#endif
- if (result != OK) {
- ALOGE("queueBuffer failed: %d", result);
- return result;
- }
-
- // XXX: Hack to keep C2Buffers unreleased until the consumer is done
- // reading the content. Eventually IGBP-based C2BlockPool should handle
- // the lifecycle.
- output->bufferRefs.push_back(c2Buffer);
- if (output->bufferRefs.size() > output->maxBufferCount + 1) {
- output->bufferRefs.pop_front();
- ALOGV("%zu buffer refs remaining", output->bufferRefs.size());
- }
-
- return OK;
-}
-
-status_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
- ALOGV("discardBuffer: %p", buffer.get());
- {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- (void)(*buffers)->releaseBuffer(buffer);
- }
- {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- if((*buffers)->releaseBuffer(buffer)) {
- buffers.unlock();
- feedInputBufferIfAvailable();
- buffers.lock();
- }
- }
- return OK;
-}
-
-void CCodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
- array->clear();
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
-
- if (!(*buffers)->isArrayMode()) {
- *buffers = (*buffers)->toArrayMode();
- }
-
- (*buffers)->getArray(array);
-}
-
-void CCodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
- array->clear();
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
-
- if (!(*buffers)->isArrayMode()) {
- *buffers = (*buffers)->toArrayMode();
- }
-
- (*buffers)->getArray(array);
-}
-
-status_t CCodecBufferChannel::start(
- const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
- C2StreamFormatConfig::input iStreamFormat(0u);
- C2StreamFormatConfig::output oStreamFormat(0u);
- c2_status_t err = mComponent->intf()->query_vb(
- { &iStreamFormat, &oStreamFormat },
- {},
- C2_DONT_BLOCK,
- nullptr);
- if (err != C2_OK) {
- return UNKNOWN_ERROR;
- }
- bool secure = mComponent->intf()->getName().find(".secure") != std::string::npos;
-
- if (inputFormat != nullptr) {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
-
- bool graphic = (iStreamFormat.value == C2FormatVideo);
- if (graphic) {
- if (mInputSurface) {
- buffers->reset(new DummyInputBuffers);
- } else {
- buffers->reset(new GraphicInputBuffers);
- }
- } else {
- if (hasCryptoOrDescrambler()) {
- if (mDealer == nullptr) {
- mDealer = new MemoryDealer(
- align(kLinearBufferSize, MemoryDealer::getAllocationAlignment())
- * (kMinBufferArraySize + 1),
- "EncryptedLinearInputBuffers");
- mDecryptDestination = mDealer->allocate(kLinearBufferSize);
- }
- if (mCrypto != nullptr && mHeapSeqNum < 0) {
- mHeapSeqNum = mCrypto->setHeap(mDealer->getMemoryHeap());
- } else {
- mHeapSeqNum = -1;
- }
- buffers->reset(new EncryptedLinearInputBuffers(
- secure, mDealer, mCrypto, mHeapSeqNum));
- } else {
- buffers->reset(new LinearInputBuffers);
- }
- }
- (*buffers)->setFormat(inputFormat);
-
- ALOGV("graphic = %s", graphic ? "true" : "false");
- std::shared_ptr<C2BlockPool> pool;
- if (graphic) {
- err = GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, mComponent, &pool);
- } else {
- err = CreateCodec2BlockPool(C2PlatformAllocatorStore::ION,
- mComponent, &pool);
- }
- if (err == C2_OK) {
- (*buffers)->setPool(pool);
- } else {
- // TODO: error
- }
- }
-
- if (outputFormat != nullptr) {
- bool hasOutputSurface = false;
- {
- Mutexed<OutputSurface>::Locked output(mOutputSurface);
- hasOutputSurface = (output->surface != nullptr);
- }
-
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
-
- bool graphic = (oStreamFormat.value == C2FormatVideo);
- if (graphic) {
- if (hasOutputSurface) {
- buffers->reset(new GraphicOutputBuffers);
- } else {
- buffers->reset(new RawGraphicOutputBuffers);
- }
- } else {
- buffers->reset(new LinearOutputBuffers);
- }
- (*buffers)->setFormat(outputFormat);
- }
-
- mSync.start();
- if (mInputSurface == nullptr) {
- // TODO: use proper buffer depth instead of this random value
- for (size_t i = 0; i < kMinBufferArraySize; ++i) {
- size_t index;
- sp<MediaCodecBuffer> buffer;
- {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- if (!(*buffers)->requestNewBuffer(&index, &buffer)) {
- if (i == 0) {
- ALOGE("start: cannot allocate memory at all");
- return NO_MEMORY;
- } else {
- ALOGV("start: cannot allocate memory, only %zu buffers allocated", i);
- }
- break;
- }
- }
- mCallback->onInputBufferAvailable(index, buffer);
- }
- } else {
- (void)mInputSurface->connect(mComponent);
- }
- return OK;
-}
-
-void CCodecBufferChannel::stop() {
- mSync.stop();
- mFirstValidFrameIndex = mFrameIndex.load();
- if (mInputSurface != nullptr) {
- mInputSurface->disconnect();
- mInputSurface.reset();
- }
-}
-
-void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
- {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- (*buffers)->flush();
- }
- {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- (*buffers)->flush(flushedWork);
- }
-}
-
-void CCodecBufferChannel::onWorkDone(const std::unique_ptr<C2Work> &work) {
- if (work->result != C2_OK) {
- if (work->result == C2_NOT_FOUND) {
- // TODO: Define what flushed work's result is.
- ALOGD("flushed work; ignored.");
- return;
- }
- ALOGD("work failed to complete: %d", work->result);
- mOnError(work->result, ACTION_CODE_FATAL);
- return;
- }
-
- // NOTE: MediaCodec usage supposedly have only one worklet
- if (work->worklets.size() != 1u) {
- ALOGE("onWorkDone: incorrect number of worklets: %zu",
- work->worklets.size());
- mOnError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- return;
- }
-
- const std::unique_ptr<C2Worklet> &worklet = work->worklets.front();
- if ((worklet->output.ordinal.frameIndex - mFirstValidFrameIndex.load()).peek() < 0) {
- // Discard frames from previous generation.
- return;
- }
- std::shared_ptr<C2Buffer> buffer;
- // NOTE: MediaCodec usage supposedly have only one output stream.
- if (worklet->output.buffers.size() > 1u) {
- ALOGE("onWorkDone: incorrect number of output buffers: %zu",
- worklet->output.buffers.size());
- mOnError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- return;
- } else if (worklet->output.buffers.size() == 1u) {
- buffer = worklet->output.buffers[0];
- if (!buffer) {
- ALOGW("onWorkDone: nullptr found in buffers; ignored.");
- }
- }
-
- const C2StreamCsdInfo::output *csdInfo = nullptr;
- for (const std::unique_ptr<C2Param> &info : worklet->output.configUpdate) {
- if (info->coreIndex() == C2StreamCsdInfo::output::CORE_INDEX) {
- ALOGV("onWorkDone: csd found");
- csdInfo = static_cast<const C2StreamCsdInfo::output *>(info.get());
- }
- }
-
- int32_t flags = 0;
- if (worklet->output.flags & C2FrameData::FLAG_END_OF_STREAM) {
- flags |= MediaCodec::BUFFER_FLAG_EOS;
- ALOGV("onWorkDone: output EOS");
- }
-
- sp<MediaCodecBuffer> outBuffer;
- size_t index;
- if (csdInfo != nullptr) {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- if ((*buffers)->registerCsd(csdInfo, &index, &outBuffer)) {
- outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp.peek());
- outBuffer->meta()->setInt32("flags", flags | MediaCodec::BUFFER_FLAG_CODECCONFIG);
- ALOGV("onWorkDone: csd index = %zu", index);
-
- buffers.unlock();
- mCallback->onOutputBufferAvailable(index, outBuffer);
- buffers.lock();
- } else {
- ALOGE("onWorkDone: unable to register csd");
- buffers.unlock();
- mOnError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- buffers.lock();
- return;
- }
- }
-
- if (!buffer && !flags) {
- ALOGV("onWorkDone: Not reporting output buffer");
- return;
- }
-
- if (buffer) {
- for (const std::shared_ptr<const C2Info> &info : buffer->info()) {
- // TODO: properly translate these to metadata
- switch (info->coreIndex().coreIndex()) {
- case C2StreamPictureTypeMaskInfo::CORE_INDEX:
- if (((C2StreamPictureTypeMaskInfo *)info.get())->value & C2PictureTypeKeyFrame) {
- flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
- }
- break;
- default:
- break;
- }
- }
- }
-
- {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- if (!(*buffers)->registerBuffer(buffer, &index, &outBuffer)) {
- ALOGE("onWorkDone: unable to register output buffer");
- buffers.unlock();
- mOnError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- buffers.lock();
- return;
- }
- }
-
- outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp.peek());
- outBuffer->meta()->setInt32("flags", flags);
- ALOGV("onWorkDone: out buffer index = %zu", index);
- mCallback->onOutputBufferAvailable(index, outBuffer);
-}
-
-status_t CCodecBufferChannel::setSurface(const sp<Surface> &newSurface) {
- if (newSurface != nullptr) {
- newSurface->setScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- }
-
- Mutexed<OutputSurface>::Locked output(mOutputSurface);
-// if (newSurface == nullptr) {
-// if (*surface != nullptr) {
-// ALOGW("cannot unset a surface");
-// return INVALID_OPERATION;
-// }
-// return OK;
-// }
-//
-// if (*surface == nullptr) {
-// ALOGW("component was not configured with a surface");
-// return INVALID_OPERATION;
-// }
-
- output->surface = newSurface;
- output->bufferRefs.clear();
- // XXX: hack
- output->maxBufferCount = kMaxGraphicBufferRefCount;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/Codec2Buffer.cpp b/media/libstagefright/Codec2Buffer.cpp
deleted file mode 100644
index d2ef229..0000000
--- a/media/libstagefright/Codec2Buffer.cpp
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Copyright 2018, 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 "Codec2Buffer"
-#include <utils/Log.h>
-
-#include <hidlmemory/FrameworkUtils.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "include/Codec2Buffer.h"
-
-namespace android {
-
-// Codec2Buffer
-
-bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
- if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
- return false;
- }
- if (!buffer) {
- // Nothing to copy, so we can copy by doing nothing.
- return true;
- }
- if (buffer->data().type() != C2BufferData::LINEAR) {
- return false;
- }
- if (buffer->data().linearBlocks().size() == 0u) {
- // Nothing to copy, so we can copy by doing nothing.
- return true;
- } else if (buffer->data().linearBlocks().size() > 1u) {
- // We don't know how to copy more than one blocks.
- return false;
- }
- if (buffer->data().linearBlocks()[0].size() > capacity()) {
- // It won't fit.
- return false;
- }
- return true;
-}
-
-bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
- // We assume that all canCopyLinear() checks passed.
- if (!buffer || buffer->data().linearBlocks().size() == 0u) {
- setRange(0, 0);
- return true;
- }
- C2ReadView view = buffer->data().linearBlocks()[0].map().get();
- if (view.error() != C2_OK) {
- ALOGD("Error while mapping: %d", view.error());
- return false;
- }
- if (view.capacity() > capacity()) {
- ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
- view.capacity(), capacity());
- return false;
- }
- memcpy(base(), view.data(), view.capacity());
- setRange(0, view.capacity());
- return true;
-}
-
-// LocalLinearBuffer
-
-bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
- return canCopyLinear(buffer);
-}
-
-bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
- return copyLinear(buffer);
-}
-
-// DummyContainerBuffer
-
-DummyContainerBuffer::DummyContainerBuffer(
- const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
- : Codec2Buffer(format, new ABuffer(nullptr, 1)),
- mBufferRef(buffer) {
- setRange(0, buffer ? 1 : 0);
-}
-
-std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
- return std::move(mBufferRef);
-}
-
-bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
- return !mBufferRef;
-}
-
-bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
- mBufferRef = buffer;
- setRange(0, mBufferRef ? 1 : 0);
- return true;
-}
-
-// LinearBlockBuffer
-
-// static
-sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
- const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
- C2WriteView writeView(block->map().get());
- if (writeView.error() != C2_OK) {
- return nullptr;
- }
- return new LinearBlockBuffer(format, std::move(writeView), block);
-}
-
-std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
- return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
-}
-
-bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
- return canCopyLinear(buffer);
-}
-
-bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
- return copyLinear(buffer);
-}
-
-LinearBlockBuffer::LinearBlockBuffer(
- const sp<AMessage> &format,
- C2WriteView&& writeView,
- const std::shared_ptr<C2LinearBlock> &block)
- : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
- mWriteView(writeView),
- mBlock(block) {
-}
-
-// ConstLinearBlockBuffer
-
-// static
-sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
- const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
- if (!buffer
- || buffer->data().type() != C2BufferData::LINEAR
- || buffer->data().linearBlocks().size() != 1u) {
- return nullptr;
- }
- C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
- if (readView.error() != C2_OK) {
- return nullptr;
- }
- return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
-}
-
-ConstLinearBlockBuffer::ConstLinearBlockBuffer(
- const sp<AMessage> &format,
- C2ReadView&& readView,
- const std::shared_ptr<C2Buffer> &buffer)
- : Codec2Buffer(format, new ABuffer(
- // NOTE: ABuffer only takes non-const pointer but this data is
- // supposed to be read-only.
- const_cast<uint8_t *>(readView.data()), readView.capacity())),
- mReadView(readView),
- mBufferRef(buffer) {
-}
-
-std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
- return std::move(mBufferRef);
-}
-
-// GraphicView2MediaImageConverter
-
-namespace {
-
-class GraphicView2MediaImageConverter {
-public:
- explicit GraphicView2MediaImageConverter(const C2GraphicView &view)
- : mInitCheck(NO_INIT),
- mView(view),
- mWidth(view.width()),
- mHeight(view.height()),
- mAllocatedDepth(0),
- mBackBufferSize(0),
- mMediaImage(new ABuffer(sizeof(MediaImage2))) {
- if (view.error() != C2_OK) {
- ALOGD("Converter: view.error() = %d", view.error());
- mInitCheck = BAD_VALUE;
- return;
- }
- MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
- const C2PlanarLayout &layout = view.layout();
- if (layout.numPlanes == 0) {
- ALOGD("Converter: 0 planes");
- mInitCheck = BAD_VALUE;
- return;
- }
- mAllocatedDepth = layout.planes[0].allocatedDepth;
- uint32_t bitDepth = layout.planes[0].bitDepth;
-
- switch (layout.type) {
- case C2PlanarLayout::TYPE_YUV:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; break;
- case C2PlanarLayout::TYPE_YUVA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA; break;
- case C2PlanarLayout::TYPE_RGB:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB; break;
- case C2PlanarLayout::TYPE_RGBA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA; break;
- default:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; break;
- }
- mediaImage->mNumPlanes = layout.numPlanes;
- mediaImage->mWidth = mWidth;
- mediaImage->mHeight = mHeight;
- mediaImage->mBitDepth = bitDepth;
- mediaImage->mBitDepthAllocated = mAllocatedDepth;
-
- uint32_t bufferSize = 0;
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- if (plane.rightShift != 0) {
- ALOGV("rightShift value of %u unsupported", plane.rightShift);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (plane.endianness != C2PlaneInfo::NATIVE) {
- ALOGV("endianness value of %u unsupported", plane.endianness);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
- ALOGV("different allocatedDepth/bitDepth per plane unsupported");
- mInitCheck = BAD_VALUE;
- return;
- }
- bufferSize += mWidth * mHeight
- / plane.rowSampling / plane.colSampling * (plane.allocatedDepth / 8);
- }
-
- mBackBufferSize = bufferSize;
- mInitCheck = OK;
- }
-
- status_t initCheck() const { return mInitCheck; }
-
- uint32_t backBufferSize() const { return mBackBufferSize; }
-
- /**
- * Convert C2GraphicView to MediaImage2. Note that if not wrapped, the content
- * is not copied over in this function --- the caller should use
- * CopyGraphicView2MediaImage() function to do that explicitly.
- *
- * \param view[in] source C2GraphicView object.
- * \param alloc[in] allocator function for ABuffer.
- * \param mediaImage[out] destination MediaImage2 object.
- * \param buffer[out] new buffer object.
- * \param wrapped[out] whether we wrapped around existing map or
- * allocated a new buffer
- *
- * \return true if conversion succeeds,
- * false otherwise; all output params should be ignored.
- */
- sp<ABuffer> wrap() {
- MediaImage2 *mediaImage = getMediaImage();
- const C2PlanarLayout &layout = mView.layout();
- if (layout.numPlanes == 1) {
- const C2PlaneInfo &plane = layout.planes[0];
- ssize_t offset = plane.minOffset(mWidth, mHeight);
- mediaImage->mPlane[0].mOffset = -offset;
- mediaImage->mPlane[0].mColInc = plane.colInc;
- mediaImage->mPlane[0].mRowInc = plane.rowInc;
- mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
- mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
- return new ABuffer(
- const_cast<uint8_t *>(mView.data()[0] + offset),
- plane.maxOffset(mWidth, mHeight) - offset + 1);
- }
- const uint8_t *minPtr = mView.data()[0];
- const uint8_t *maxPtr = mView.data()[0];
- int32_t planeSize = 0;
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- ssize_t minOffset = plane.minOffset(mWidth, mHeight);
- ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
- if (minPtr > mView.data()[i] + minOffset) {
- minPtr = mView.data()[i] + minOffset;
- }
- if (maxPtr < mView.data()[i] + maxOffset) {
- maxPtr = mView.data()[i] + maxOffset;
- }
- planeSize += std::abs(plane.rowInc) * mHeight
- / plane.rowSampling / plane.colSampling * (mAllocatedDepth / 8);
- }
-
- if ((maxPtr - minPtr + 1) <= planeSize) {
- // FIXME: this is risky as reading/writing data out of bound results in
- // an undefined behavior.
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
- mediaImage->mPlane[i].mColInc = plane.colInc;
- mediaImage->mPlane[i].mRowInc = plane.rowInc;
- mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
- mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
- }
- return new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr + 1);
- }
-
- return nullptr;
- }
-
- bool setBackBuffer(const sp<ABuffer> &backBuffer) {
- if (backBuffer->capacity() < mBackBufferSize) {
- return false;
- }
- backBuffer->setRange(0, mBackBufferSize);
-
- const C2PlanarLayout &layout = mView.layout();
- MediaImage2 *mediaImage = getMediaImage();
- uint32_t offset = 0;
- // TODO: keep interleaved planes together
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- mediaImage->mPlane[i].mOffset = offset;
- mediaImage->mPlane[i].mColInc = mAllocatedDepth / 8;
- mediaImage->mPlane[i].mRowInc =
- mediaImage->mPlane[i].mColInc * mWidth / plane.colSampling;
- mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
- mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
- offset += mediaImage->mPlane[i].mRowInc * mHeight / plane.rowSampling;
- }
- mBackBuffer = backBuffer;
- return true;
- }
-
- /**
- * Copy C2GraphicView to MediaImage2. This function assumes that |mediaImage| is
- * an output from GraphicView2MediaImage(), so it mostly skips sanity check.
- *
- * \param view[in] source C2GraphicView object.
- * \param mediaImage[in] destination MediaImage2 object.
- * \param buffer[out] new buffer object.
- */
- void copy() {
- // TODO: more efficient copying --- e.g. one row at a time, copying
- // interleaved planes together, etc.
- const C2PlanarLayout &layout = mView.layout();
- MediaImage2 *mediaImage = getMediaImage();
- uint8_t *dst = mBackBuffer->base();
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- const uint8_t *src = mView.data()[i];
- int32_t planeW = mWidth / plane.colSampling;
- int32_t planeH = mHeight / plane.rowSampling;
- for (int32_t row = 0; row < planeH; ++row) {
- for(int32_t col = 0; col < planeW; ++col) {
- memcpy(dst, src, mAllocatedDepth / 8);
- dst += mediaImage->mPlane[i].mColInc;
- src += plane.colInc;
- }
- dst -= mediaImage->mPlane[i].mColInc * planeW;
- dst += mediaImage->mPlane[i].mRowInc;
- src -= plane.colInc * planeW;
- src += plane.rowInc;
- }
- }
- }
-
- const sp<ABuffer> &imageData() const { return mMediaImage; }
-
-private:
- status_t mInitCheck;
-
- const C2GraphicView mView;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mAllocatedDepth;
- uint32_t mBackBufferSize;
- sp<ABuffer> mMediaImage;
- std::function<sp<ABuffer>(size_t)> mAlloc;
-
- sp<ABuffer> mBackBuffer;
-
- MediaImage2 *getMediaImage() {
- return (MediaImage2 *)mMediaImage->base();
- }
-};
-
-} // namespace
-
-// GraphicBlockBuffer
-
-// static
-sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
- const sp<AMessage> &format,
- const std::shared_ptr<C2GraphicBlock> &block,
- std::function<sp<ABuffer>(size_t)> alloc) {
- C2GraphicView view(block->map().get());
- if (view.error() != C2_OK) {
- ALOGD("C2GraphicBlock::map failed: %d", view.error());
- return nullptr;
- }
- GraphicView2MediaImageConverter converter(view);
- if (converter.initCheck() != OK) {
- ALOGD("Converter init failed: %d", converter.initCheck());
- return nullptr;
- }
- bool wrapped = true;
- sp<ABuffer> buffer = converter.wrap();
- if (buffer == nullptr) {
- buffer = alloc(converter.backBufferSize());
- if (!converter.setBackBuffer(buffer)) {
- ALOGD("Converter failed to set back buffer");
- return nullptr;
- }
- wrapped = false;
- }
- return new GraphicBlockBuffer(
- format,
- buffer,
- std::move(view),
- block,
- converter.imageData(),
- wrapped);
-}
-
-GraphicBlockBuffer::GraphicBlockBuffer(
- const sp<AMessage> &format,
- const sp<ABuffer> &buffer,
- C2GraphicView &&view,
- const std::shared_ptr<C2GraphicBlock> &block,
- const sp<ABuffer> &imageData,
- bool wrapped)
- : Codec2Buffer(format, buffer),
- mView(view),
- mBlock(block),
- mImageData(imageData),
- mWrapped(wrapped) {
- meta()->setBuffer("image-data", imageData);
-}
-
-std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
- uint32_t width = mView.width();
- uint32_t height = mView.height();
- if (!mWrapped) {
- MediaImage2 *mediaImage = imageData();
- const C2PlanarLayout &layout = mView.layout();
- for (uint32_t i = 0; i < mediaImage->mNumPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- int32_t planeW = width / plane.colSampling;
- int32_t planeH = height / plane.rowSampling;
- const uint8_t *src = base() + mediaImage->mPlane[i].mOffset;
- uint8_t *dst = mView.data()[i];
- for (int32_t row = 0; row < planeH; ++row) {
- for (int32_t col = 0; col < planeW; ++col) {
- memcpy(dst, src, mediaImage->mBitDepthAllocated / 8);
- src += mediaImage->mPlane[i].mColInc;
- dst += plane.colInc;
- }
- src -= mediaImage->mPlane[i].mColInc * planeW;
- dst -= plane.colInc * planeW;
- src += mediaImage->mPlane[i].mRowInc;
- dst += plane.rowInc;
- }
- }
- }
- return C2Buffer::CreateGraphicBuffer(
- mBlock->share(C2Rect(width, height), C2Fence()));
-}
-
-// ConstGraphicBlockBuffer
-
-// static
-sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
- const sp<AMessage> &format,
- const std::shared_ptr<C2Buffer> &buffer,
- std::function<sp<ABuffer>(size_t)> alloc) {
- if (!buffer
- || buffer->data().type() != C2BufferData::GRAPHIC
- || buffer->data().graphicBlocks().size() != 1u) {
- ALOGD("C2Buffer precond fail");
- return nullptr;
- }
- std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
- buffer->data().graphicBlocks()[0].map().get()));
- std::unique_ptr<const C2GraphicView> holder;
-
- GraphicView2MediaImageConverter converter(*view);
- if (converter.initCheck() != OK) {
- ALOGD("Converter init failed: %d", converter.initCheck());
- return nullptr;
- }
- bool wrapped = true;
- sp<ABuffer> aBuffer = converter.wrap();
- if (aBuffer == nullptr) {
- aBuffer = alloc(converter.backBufferSize());
- if (!converter.setBackBuffer(aBuffer)) {
- ALOGD("Converter failed to set back buffer");
- return nullptr;
- }
- wrapped = false;
- converter.copy();
- // We don't need the view.
- holder = std::move(view);
- }
- return new ConstGraphicBlockBuffer(
- format,
- aBuffer,
- std::move(view),
- buffer,
- converter.imageData(),
- wrapped);
-}
-
-// static
-sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
- const sp<AMessage> &format,
- std::function<sp<ABuffer>(size_t)> alloc) {
- int32_t width, height;
- if (!format->findInt32("width", &width)
- || !format->findInt32("height", &height)) {
- ALOGD("format had no width / height");
- return nullptr;
- }
- sp<ABuffer> aBuffer(alloc(width * height * 4));
- return new ConstGraphicBlockBuffer(
- format,
- aBuffer,
- nullptr,
- nullptr,
- nullptr,
- false);
-}
-
-ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
- const sp<AMessage> &format,
- const sp<ABuffer> &aBuffer,
- std::unique_ptr<const C2GraphicView> &&view,
- const std::shared_ptr<C2Buffer> &buffer,
- const sp<ABuffer> &imageData,
- bool wrapped)
- : Codec2Buffer(format, aBuffer),
- mView(std::move(view)),
- mBufferRef(buffer),
- mWrapped(wrapped) {
- if (imageData != nullptr) {
- meta()->setBuffer("image-data", imageData);
- }
-}
-
-std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
- mView.reset();
- return std::move(mBufferRef);
-}
-
-bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
- if (mWrapped || mBufferRef) {
- ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
- mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
- return false;
- }
- if (!buffer) {
- // Nothing to copy, so we can copy by doing nothing.
- return true;
- }
- if (buffer->data().type() != C2BufferData::GRAPHIC) {
- ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
- return false;
- }
- if (buffer->data().graphicBlocks().size() == 0) {
- return true;
- } else if (buffer->data().graphicBlocks().size() != 1u) {
- ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
- return false;
- }
- GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get());
- if (converter.initCheck() != OK) {
- ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
- return false;
- }
- if (converter.backBufferSize() > capacity()) {
- ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
- converter.backBufferSize(), capacity());
- return false;
- }
- return true;
-}
-
-bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
- if (!buffer || buffer->data().graphicBlocks().size() == 0) {
- setRange(0, 0);
- return true;
- }
- GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get());
- if (converter.initCheck() != OK) {
- ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
- return false;
- }
- sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
- if (!converter.setBackBuffer(aBuffer)) {
- ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
- return false;
- }
- converter.copy();
- meta()->setBuffer("image-data", converter.imageData());
- mBufferRef = buffer;
- return true;
-}
-
-// EncryptedLinearBlockBuffer
-
-EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
- const sp<AMessage> &format,
- const std::shared_ptr<C2LinearBlock> &block,
- const sp<IMemory> &memory,
- int32_t heapSeqNum)
- : Codec2Buffer(format, new ABuffer(memory->pointer(), memory->size())),
- mBlock(block),
- mMemory(memory),
- mHeapSeqNum(heapSeqNum) {
-}
-
-std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
- return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
-}
-
-void EncryptedLinearBlockBuffer::fillSourceBuffer(
- ICrypto::SourceBuffer *source) {
- source->mSharedMemory = mMemory;
- source->mHeapSeqNum = mHeapSeqNum;
-}
-
-void EncryptedLinearBlockBuffer::fillSourceBuffer(
- hardware::cas::native::V1_0::SharedBuffer *source) {
- ssize_t offset;
- size_t size;
-
- mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
- source->heapBase = *mHidlMemory;
- source->offset = offset;
- source->size = size;
-}
-
-bool EncryptedLinearBlockBuffer::copyDecryptedContent(
- const sp<IMemory> &decrypted, size_t length) {
- C2WriteView view = mBlock->map().get();
- if (view.error() != C2_OK) {
- return false;
- }
- if (view.size() < length) {
- return false;
- }
- memcpy(view.data(), decrypted->pointer(), length);
- return true;
-}
-
-bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
- return copyDecryptedContent(mMemory, length);
-}
-
-native_handle_t *EncryptedLinearBlockBuffer::handle() const {
- return const_cast<native_handle_t *>(mBlock->handle());
-}
-
-} // namespace android
diff --git a/media/libstagefright/Codec2InfoBuilder.cpp b/media/libstagefright/Codec2InfoBuilder.cpp
deleted file mode 100644
index bd749c4..0000000
--- a/media/libstagefright/Codec2InfoBuilder.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2018 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 "Codec2InfoBuilder"
-#include <log/log.h>
-
-#include <C2Component.h>
-#include <C2PlatformSupport.h>
-#include <C2V4l2Support.h>
-
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-#include <media/stagefright/Codec2InfoBuilder.h>
-
-namespace android {
-
-using ConstTraitsPtr = std::shared_ptr<const C2Component::Traits>;
-
-struct ProfileLevel {
- uint32_t profile;
- uint32_t level;
-};
-static const ProfileLevel kAvcProfileLevels[] = {
- { 0x01, 0x0001 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1 },
- { 0x01, 0x0002 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
- { 0x01, 0x0004 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
- { 0x01, 0x0008 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
- { 0x01, 0x0010 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
- { 0x01, 0x0020 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 },
- { 0x01, 0x0040 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
- { 0x01, 0x0080 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
- { 0x01, 0x0100 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3 },
- { 0x01, 0x0200 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
- { 0x01, 0x0400 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
- { 0x01, 0x0800 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4 },
- { 0x01, 0x1000 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
- { 0x01, 0x2000 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 },
- { 0x01, 0x4000 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5 },
- { 0x01, 0x8000 }, // { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 },
-
- { 0x02, 0x0001 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1 },
- { 0x02, 0x0002 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b },
- { 0x02, 0x0004 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11 },
- { 0x02, 0x0008 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12 },
- { 0x02, 0x0010 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13 },
- { 0x02, 0x0020 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2 },
- { 0x02, 0x0040 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21 },
- { 0x02, 0x0080 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22 },
- { 0x02, 0x0100 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3 },
- { 0x02, 0x0200 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31 },
- { 0x02, 0x0400 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32 },
- { 0x02, 0x0800 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel4 },
- { 0x02, 0x1000 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41 },
- { 0x02, 0x2000 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel42 },
- { 0x02, 0x4000 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel5 },
- { 0x02, 0x8000 }, // { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel51 },
-
- { 0x04, 0x0001 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1 },
- { 0x04, 0x0002 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1b },
- { 0x04, 0x0004 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel11 },
- { 0x04, 0x0008 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel12 },
- { 0x04, 0x0010 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel13 },
- { 0x04, 0x0020 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel2 },
- { 0x04, 0x0040 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel21 },
- { 0x04, 0x0080 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel22 },
- { 0x04, 0x0100 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel3 },
- { 0x04, 0x0200 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel31 },
- { 0x04, 0x0400 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel32 },
- { 0x04, 0x0800 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel4 },
- { 0x04, 0x1000 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel41 },
- { 0x04, 0x2000 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel42 },
- { 0x04, 0x4000 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel5 },
- { 0x04, 0x8000 }, // { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel51 },
-};
-
-status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
- // Obtain C2ComponentStore
- std::shared_ptr<C2ComponentStore> store = GetCodec2PlatformComponentStore();
- if (store == nullptr) {
- ALOGE("Cannot find a component store.");
- return NO_INIT;
- }
-
- std::vector<ConstTraitsPtr> traits = store->listComponents();
-
- if (property_get_bool("debug.stagefright.ccodec_v4l2", false)) {
- std::shared_ptr<C2ComponentStore> v4l2Store = GetCodec2VDAComponentStore();
- if (v4l2Store == nullptr) {
- ALOGD("Cannot find a V4L2 component store.");
- // non-fatal.
- } else {
- std::vector<ConstTraitsPtr> v4l2Traits = v4l2Store->listComponents();
- traits.insert(traits.end(), v4l2Traits.begin(), v4l2Traits.end());
- }
- }
-
- MediaCodecsXmlParser parser(
- MediaCodecsXmlParser::defaultSearchDirs,
- "media_codecs_c2.xml");
- if (parser.getParsingStatus() != OK) {
- ALOGD("XML parser no good");
- return OK;
- }
- for (const ConstTraitsPtr &trait : traits) {
- if (parser.getCodecMap().count(trait->name.c_str()) == 0) {
- ALOGD("%s not found in xml", trait->name.c_str());
- continue;
- }
- const MediaCodecsXmlParser::CodecProperties &codec = parser.getCodecMap().at(trait->name);
- std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
- codecInfo->setName(trait->name.c_str());
- codecInfo->setOwner("dummy");
- // TODO: get this from trait->kind
- bool encoder = (trait->name.find("encoder") != std::string::npos);
- codecInfo->setEncoder(encoder);
- codecInfo->setRank(trait->rank);
- for (auto typeIt = codec.typeMap.begin(); typeIt != codec.typeMap.end(); ++typeIt) {
- const std::string &mediaType = typeIt->first;
- const MediaCodecsXmlParser::AttributeMap &attrMap = typeIt->second;
- std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
- codecInfo->addMime(mediaType.c_str());
- for (auto attrIt = attrMap.begin(); attrIt != attrMap.end(); ++attrIt) {
- std::string key, value;
- std::tie(key, value) = *attrIt;
- if (key.find("feature-") == 0 && key.find("feature-bitrate-modes") != 0) {
- caps->addDetail(key.c_str(), std::stoi(value));
- } else {
- caps->addDetail(key.c_str(), value.c_str());
- }
- }
- // TODO: get this from intf(), and apply to other codecs as well.
- if (mediaType.find("video/avc") != std::string::npos && !encoder) {
- for (const auto& pl : kAvcProfileLevels) {
- caps->addProfileLevel(pl.profile, pl.level);
- }
- }
- // TODO: get this from intf().
- if (mediaType.find("video") != std::string::npos && !encoder) {
- caps->addColorFormat(0x7F420888); // COLOR_FormatYUV420Flexible
- }
- }
- }
- return OK;
-}
-
-} // namespace android
-
-extern "C" android::MediaCodecListBuilderBase *CreateBuilder() {
- return new android::Codec2InfoBuilder;
-}
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 27b9a5d..4a7d6ca 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -307,6 +307,26 @@
return OK;
}
+status_t NuMediaExtractor::getExifOffsetSize(off64_t *offset, size_t *size) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mImpl == NULL) {
+ return -EINVAL;
+ }
+
+ sp<MetaData> meta = mImpl->getMetaData();
+
+ int64_t exifOffset, exifSize;
+ if (meta->findInt64(kKeyExifOffset, &exifOffset)
+ && meta->findInt64(kKeyExifSize, &exifSize)) {
+ *offset = (off64_t) exifOffset;
+ *size = (size_t) exifSize;
+
+ return OK;
+ }
+ return ERROR_UNSUPPORTED;
+}
+
status_t NuMediaExtractor::selectTrack(size_t index,
int64_t startTimeUs, MediaSource::ReadOptions::SeekMode mode) {
Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index 388ed6b..4f46be7 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -6,6 +6,7 @@
},
srcs: [
+ "Conversion.cpp",
"FrameDropper.cpp",
"GraphicBufferSource.cpp",
"WProducerListener.cpp",
@@ -42,8 +43,9 @@
],
export_shared_lib_headers: [
- "libstagefright_foundation",
+ "libgui",
"libhidlmemory",
+ "libstagefright_foundation",
],
cflags: [
diff --git a/media/libstagefright/bqhelper/Conversion.cpp b/media/libstagefright/bqhelper/Conversion.cpp
new file mode 100644
index 0000000..ffed005
--- /dev/null
+++ b/media/libstagefright/bqhelper/Conversion.cpp
@@ -0,0 +1,1542 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/stagefright/bqhelper/Conversion.h>
+
+namespace android {
+namespace conversion {
+
+// native_handle_t helper functions.
+
+/**
+ * \brief Take an fd and create a native handle containing only the given fd.
+ * The created handle will need to be deleted manually with
+ * `native_handle_delete()`.
+ *
+ * \param[in] fd The source file descriptor (of type `int`).
+ * \return The create `native_handle_t*` that contains the given \p fd. If the
+ * supplied \p fd is negative, the created native handle will contain no file
+ * descriptors.
+ *
+ * If the native handle cannot be created, the return value will be
+ * `nullptr`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+native_handle_t* native_handle_create_from_fd(int fd) {
+ if (fd < 2) {
+ return native_handle_create(0, 0);
+ }
+ native_handle_t* nh = native_handle_create(1, 0);
+ if (nh == nullptr) {
+ return nullptr;
+ }
+ nh->data[0] = fd;
+ return nh;
+}
+
+/**
+ * \brief Extract a file descriptor from a native handle.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \param[in] index The index of the file descriptor in \p nh to read from. This
+ * input has the default value of `0`.
+ * \return The `index`-th file descriptor in \p nh. If \p nh does not have
+ * enough file descriptors, the returned value will be `-1`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+int native_handle_read_fd(native_handle_t const* nh, int index) {
+ return ((nh == nullptr) || (nh->numFds == 0) ||
+ (nh->numFds <= index) || (index < 0)) ?
+ -1 : nh->data[index];
+}
+
+/**
+ * Conversion functions
+ * ====================
+ *
+ * There are two main directions of conversion:
+ * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
+ * input. The wrapper has type `TargetType`.
+ * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
+ * corresponds to the input. The lifetime of the output does not depend on the
+ * lifetime of the input.
+ * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
+ * that cannot be copied and/or moved efficiently, or when there are multiple
+ * output arguments.
+ * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
+ * `TargetType` that cannot be copied and/or moved efficiently, or when there
+ * are multiple output arguments.
+ *
+ * `wrapIn()` and `convertTo()` functions will take output arguments before
+ * input arguments. Some of these functions might return a value to indicate
+ * success or error.
+ *
+ * In converting or wrapping something as a Treble type that contains a
+ * `hidl_handle`, `native_handle_t*` will need to be created and returned as
+ * an additional output argument, hence only `wrapIn()` or `convertTo()` would
+ * be available. The caller must call `native_handle_delete()` to deallocate the
+ * returned native handle when it is no longer needed.
+ *
+ * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
+ * not perform duplication of file descriptors, while `toTargetType()` and
+ * `convertTo()` do.
+ */
+
+/**
+ * \brief Convert `Return<void>` to `binder::Status`.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `binder::Status`.
+ */
+// convert: Return<void> -> ::android::binder::Status
+::android::binder::Status toBinderStatus(
+ Return<void> const& t) {
+ return ::android::binder::Status::fromExceptionCode(
+ t.isOk() ? OK : UNKNOWN_ERROR,
+ t.description().c_str());
+}
+
+/**
+ * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `status_t`.
+ */
+// convert: Return<void> -> status_t
+status_t toStatusT(Return<void> const& t) {
+ return t.isOk() ? OK : UNKNOWN_ERROR;
+}
+
+/**
+ * \brief Wrap `native_handle_t*` in `hidl_handle`.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \return The `hidl_handle` that points to \p nh.
+ */
+// wrap: native_handle_t* -> hidl_handle
+hidl_handle inHidlHandle(native_handle_t const* nh) {
+ return hidl_handle(nh);
+}
+
+/**
+ * \brief Convert `int32_t` to `Dataspace`.
+ *
+ * \param[in] l The source `int32_t`.
+ * \result The corresponding `Dataspace`.
+ */
+// convert: int32_t -> Dataspace
+Dataspace toHardwareDataspace(int32_t l) {
+ return static_cast<Dataspace>(l);
+}
+
+/**
+ * \brief Convert `Dataspace` to `int32_t`.
+ *
+ * \param[in] t The source `Dataspace`.
+ * \result The corresponding `int32_t`.
+ */
+// convert: Dataspace -> int32_t
+int32_t toRawDataspace(Dataspace const& t) {
+ return static_cast<int32_t>(t);
+}
+
+/**
+ * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that points to the buffer.
+ */
+// wrap: void*, size_t -> hidl_vec<uint8_t>
+hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
+ hidl_vec<uint8_t> t;
+ t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
+ return t;
+}
+
+/**
+ * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
+ */
+// convert: void*, size_t -> hidl_vec<uint8_t>
+hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
+ hidl_vec<uint8_t> t;
+ t.resize(size);
+ uint8_t const* src = static_cast<uint8_t const*>(l);
+ std::copy(src, src + size, t.data());
+ return t;
+}
+
+/**
+ * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
+ *
+ * \param[out] t The wrapper of type `AnwBuffer`.
+ * \param[in] l The source `GraphicBuffer`.
+ */
+// wrap: GraphicBuffer -> AnwBuffer
+void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
+ t->attr.width = l.getWidth();
+ t->attr.height = l.getHeight();
+ t->attr.stride = l.getStride();
+ t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
+ t->attr.layerCount = l.getLayerCount();
+ t->attr.usage = l.getUsage();
+ t->attr.id = l.getId();
+ t->attr.generationNumber = l.getGenerationNumber();
+ t->nativeHandle = hidl_handle(l.handle);
+}
+
+/**
+ * \brief Convert `AnwBuffer` to `GraphicBuffer`.
+ *
+ * \param[out] l The destination `GraphicBuffer`.
+ * \param[in] t The source `AnwBuffer`.
+ *
+ * This function will duplicate all file descriptors in \p t.
+ */
+// convert: AnwBuffer -> GraphicBuffer
+// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
+bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
+ native_handle_t* handle = t.nativeHandle == nullptr ?
+ nullptr : native_handle_clone(t.nativeHandle);
+
+ size_t const numInts = 12 + (handle ? handle->numInts : 0);
+ int32_t* ints = new int32_t[numInts];
+
+ size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
+ int* fds = new int[numFds];
+
+ ints[0] = 'GBFR';
+ ints[1] = static_cast<int32_t>(t.attr.width);
+ ints[2] = static_cast<int32_t>(t.attr.height);
+ ints[3] = static_cast<int32_t>(t.attr.stride);
+ ints[4] = static_cast<int32_t>(t.attr.format);
+ ints[5] = static_cast<int32_t>(t.attr.layerCount);
+ ints[6] = static_cast<int32_t>(t.attr.usage);
+ ints[7] = static_cast<int32_t>(t.attr.id >> 32);
+ ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
+ ints[9] = static_cast<int32_t>(t.attr.generationNumber);
+ ints[10] = 0;
+ ints[11] = 0;
+ if (handle) {
+ ints[10] = static_cast<int32_t>(handle->numFds);
+ ints[11] = static_cast<int32_t>(handle->numInts);
+ int* intsStart = handle->data + handle->numFds;
+ std::copy(handle->data, intsStart, fds);
+ std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
+ }
+
+ void const* constBuffer = static_cast<void const*>(ints);
+ size_t size = numInts * sizeof(int32_t);
+ int const* constFds = static_cast<int const*>(fds);
+ status_t status = l->unflatten(constBuffer, size, constFds, numFds);
+
+ delete [] fds;
+ delete [] ints;
+ native_handle_delete(handle);
+ return status == NO_ERROR;
+}
+
+/**
+ * Conversion functions for types outside media
+ * ============================================
+ *
+ * Some objects in libui and libgui that were made to go through binder calls do
+ * not expose ways to read or write their fields to the public. To pass an
+ * object of this kind through the HIDL boundary, translation functions need to
+ * work around the access restriction by using the publicly available
+ * `flatten()` and `unflatten()` functions.
+ *
+ * All `flatten()` and `unflatten()` overloads follow the same convention as
+ * follows:
+ *
+ * status_t flatten(ObjectType const& object,
+ * [OtherType const& other, ...]
+ * void*& buffer, size_t& size,
+ * int*& fds, size_t& numFds)
+ *
+ * status_t unflatten(ObjectType* object,
+ * [OtherType* other, ...,]
+ * void*& buffer, size_t& size,
+ * int*& fds, size_t& numFds)
+ *
+ * The number of `other` parameters varies depending on the `ObjectType`. For
+ * example, in the process of unflattening an object that contains
+ * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
+ * be created.
+ *
+ * The last four parameters always work the same way in all overloads of
+ * `flatten()` and `unflatten()`:
+ * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
+ * `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
+ * `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
+ * size (in ints) of the fd buffer pointed to by `fds`.
+ * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
+ * from, `size` is the size (in bytes) of the non-fd buffer pointed to by
+ * `buffer`, `fds` is the pointer to the fd buffer to be read from, and
+ * `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
+ * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
+ * will be advanced, while `size` and `numFds` will be decreased to reflect
+ * how much storage/data of the two buffers (fd and non-fd) have been used.
+ * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
+ * `numFds` are invalid.
+ *
+ * The return value of a successful `flatten()` or `unflatten()` call will be
+ * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
+ *
+ * For each object type that supports flattening, there will be two accompanying
+ * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
+ * return the size of the non-fd buffer that the object will need for
+ * flattening. `getFdCount()` will return the size of the fd buffer that the
+ * object will need for flattening.
+ *
+ * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
+ * `flatten()` and `unflatten()`, are similar to functions of the same name in
+ * the abstract class `Flattenable`. The only difference is that functions in
+ * this file are not member functions of the object type. For example, we write
+ *
+ * flatten(x, buffer, size, fds, numFds)
+ *
+ * instead of
+ *
+ * x.flatten(buffer, size, fds, numFds)
+ *
+ * because we cannot modify the type of `x`.
+ *
+ * There is one exception to the naming convention: `hidl_handle` that
+ * represents a fence. The four functions for this "Fence" type have the word
+ * "Fence" attched to their names because the object type, which is
+ * `hidl_handle`, does not carry the special meaning that the object itself can
+ * only contain zero or one file descriptor.
+ */
+
+// Ref: frameworks/native/libs/ui/Fence.cpp
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten a fence.
+ *
+ * \param[in] fence The input fence of type `hidl_handle`.
+ * \return The required size of the flat buffer.
+ *
+ * The current version of this function always returns 4, which is the number of
+ * bytes required to store the number of file descriptors contained in the fd
+ * part of the flat buffer.
+ */
+size_t getFenceFlattenedSize(hidl_handle const& /* fence */) {
+ return 4;
+};
+
+/**
+ * \brief Return the number of file descriptors contained in a fence.
+ *
+ * \param[in] fence The input fence of type `hidl_handle`.
+ * \return `0` if \p fence does not contain a valid file descriptor, or `1`
+ * otherwise.
+ */
+size_t getFenceFdCount(hidl_handle const& fence) {
+ return native_handle_read_fd(fence) == -1 ? 0 : 1;
+}
+
+/**
+ * \brief Unflatten `Fence` to `hidl_handle`.
+ *
+ * \param[out] fence The destination `hidl_handle`.
+ * \param[out] nh The underlying native handle.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will point to a newly created
+ * native handle, which needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+ if (size < 4) {
+ return NO_MEMORY;
+ }
+
+ uint32_t numFdsInHandle;
+ FlattenableUtils::read(buffer, size, numFdsInHandle);
+
+ if (numFdsInHandle > 1) {
+ return BAD_VALUE;
+ }
+
+ if (numFds < numFdsInHandle) {
+ return NO_MEMORY;
+ }
+
+ if (numFdsInHandle) {
+ *nh = native_handle_create_from_fd(*fds);
+ if (*nh == nullptr) {
+ return NO_MEMORY;
+ }
+ *fence = *nh;
+ ++fds;
+ --numFds;
+ } else {
+ *nh = nullptr;
+ *fence = hidl_handle();
+ }
+
+ return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `hidl_handle` as `Fence`.
+ *
+ * \param[in] t The source `hidl_handle`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t flattenFence(hidl_handle const& fence,
+ void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+ if (size < getFenceFlattenedSize(fence) ||
+ numFds < getFenceFdCount(fence)) {
+ return NO_MEMORY;
+ }
+ // Cast to uint32_t since the size of a size_t can vary between 32- and
+ // 64-bit processes
+ FlattenableUtils::write(buffer, size,
+ static_cast<uint32_t>(getFenceFdCount(fence)));
+ int fd = native_handle_read_fd(fence);
+ if (fd != -1) {
+ *fds = fd;
+ ++fds;
+ --numFds;
+ }
+ return NO_ERROR;
+}
+
+/**
+ * \brief Wrap `Fence` in `hidl_handle`.
+ *
+ * \param[out] t The wrapper of type `hidl_handle`.
+ * \param[out] nh The native handle pointed to by \p t.
+ * \param[in] l The source `Fence`.
+ *
+ * On success, \p nh will hold a newly created native handle, which must be
+ * deleted manually with `native_handle_delete()` afterwards.
+ */
+// wrap: Fence -> hidl_handle
+bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l) {
+ size_t const baseSize = l.getFlattenedSize();
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ return false;
+ }
+
+ size_t const baseNumFds = l.getFdCount();
+ std::unique_ptr<int[]> baseFds(
+ new (std::nothrow) int[baseNumFds]);
+ if (!baseFds) {
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ int* fds = static_cast<int*>(baseFds.get());
+ size_t numFds = baseNumFds;
+ if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ int const* constFds = static_cast<int const*>(baseFds.get());
+ numFds = baseNumFds;
+ if (unflattenFence(t, nh, constBuffer, size, constFds, numFds)
+ != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * \brief Convert `hidl_handle` to `Fence`.
+ *
+ * \param[out] l The destination `Fence`. `l` must not have been used
+ * (`l->isValid()` must return `false`) before this function is called.
+ * \param[in] t The source `hidl_handle`.
+ *
+ * If \p t contains a valid file descriptor, it will be duplicated.
+ */
+// convert: hidl_handle -> Fence
+bool convertTo(Fence* l, hidl_handle const& t) {
+ int fd = native_handle_read_fd(t);
+ if (fd != -1) {
+ fd = dup(fd);
+ if (fd == -1) {
+ return false;
+ }
+ }
+ native_handle_t* nh = native_handle_create_from_fd(fd);
+ if (nh == nullptr) {
+ if (fd != -1) {
+ close(fd);
+ }
+ return false;
+ }
+
+ size_t const baseSize = getFenceFlattenedSize(t);
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ native_handle_delete(nh);
+ return false;
+ }
+
+ size_t const baseNumFds = getFenceFdCount(t);
+ std::unique_ptr<int[]> baseFds(
+ new (std::nothrow) int[baseNumFds]);
+ if (!baseFds) {
+ native_handle_delete(nh);
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ int* fds = static_cast<int*>(baseFds.get());
+ size_t numFds = baseNumFds;
+ if (flattenFence(hidl_handle(nh), buffer, size, fds, numFds) != NO_ERROR) {
+ native_handle_delete(nh);
+ return false;
+ }
+ native_handle_delete(nh);
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ int const* constFds = static_cast<int const*>(baseFds.get());
+ numFds = baseNumFds;
+ if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `FenceTimeSnapshot`.
+ *
+ * \param[in] t The input `FenceTimeSnapshot`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(
+ HGraphicBufferProducer::FenceTimeSnapshot const& t) {
+ constexpr size_t min = sizeof(t.state);
+ switch (t.state) {
+ case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
+ return min;
+ case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
+ return min + getFenceFlattenedSize(t.fence);
+ case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
+ return min + sizeof(
+ ::android::FenceTime::Snapshot::signalTime);
+ }
+ return 0;
+}
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `FenceTimeSnapshot`.
+ *
+ * \param[in] t The input `FenceTimeSnapshot`.
+ * \return The number of file descriptors contained in \p snapshot.
+ */
+size_t getFdCount(
+ HGraphicBufferProducer::FenceTimeSnapshot const& t) {
+ return t.state ==
+ HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE ?
+ getFenceFdCount(t.fence) : 0;
+}
+
+/**
+ * \brief Flatten `FenceTimeSnapshot`.
+ *
+ * \param[in] t The source `FenceTimeSnapshot`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate the file descriptor in `t.fence` if `t.state ==
+ * FENCE`.
+ */
+status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
+ void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+ if (size < getFlattenedSize(t)) {
+ return NO_MEMORY;
+ }
+
+ switch (t.state) {
+ case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
+ FlattenableUtils::write(buffer, size,
+ ::android::FenceTime::Snapshot::State::EMPTY);
+ return NO_ERROR;
+ case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
+ FlattenableUtils::write(buffer, size,
+ ::android::FenceTime::Snapshot::State::FENCE);
+ return flattenFence(t.fence, buffer, size, fds, numFds);
+ case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
+ FlattenableUtils::write(buffer, size,
+ ::android::FenceTime::Snapshot::State::SIGNAL_TIME);
+ FlattenableUtils::write(buffer, size, t.signalTimeNs);
+ return NO_ERROR;
+ }
+ return NO_ERROR;
+}
+
+/**
+ * \brief Unflatten `FenceTimeSnapshot`.
+ *
+ * \param[out] t The destination `FenceTimeSnapshot`.
+ * \param[out] nh The underlying native handle.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR` and the constructed snapshot contains a
+ * file descriptor, \p nh will be created to hold that file descriptor. In this
+ * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
+ */
+status_t unflatten(
+ HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+ if (size < sizeof(t->state)) {
+ return NO_MEMORY;
+ }
+
+ *nh = nullptr;
+ ::android::FenceTime::Snapshot::State state;
+ FlattenableUtils::read(buffer, size, state);
+ switch (state) {
+ case ::android::FenceTime::Snapshot::State::EMPTY:
+ t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY;
+ return NO_ERROR;
+ case ::android::FenceTime::Snapshot::State::FENCE:
+ t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE;
+ return unflattenFence(&t->fence, nh, buffer, size, fds, numFds);
+ case ::android::FenceTime::Snapshot::State::SIGNAL_TIME:
+ t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME;
+ if (size < sizeof(t->signalTimeNs)) {
+ return NO_MEMORY;
+ }
+ FlattenableUtils::read(buffer, size, t->signalTimeNs);
+ return NO_ERROR;
+ }
+ return NO_ERROR;
+}
+
+// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
+
+/**
+ * \brief Return a lower bound on the size of the non-fd buffer required to
+ * flatten `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return A lower bound on the size of the flat buffer.
+ */
+constexpr size_t minFlattenedSize(
+ HGraphicBufferProducer::FrameEventsDelta const& /* t */) {
+ return sizeof(uint64_t) + // mFrameNumber
+ sizeof(uint8_t) + // mIndex
+ sizeof(uint8_t) + // mAddPostCompositeCalled
+ sizeof(uint8_t) + // mAddRetireCalled
+ sizeof(uint8_t) + // mAddReleaseCalled
+ sizeof(nsecs_t) + // mPostedTime
+ sizeof(nsecs_t) + // mRequestedPresentTime
+ sizeof(nsecs_t) + // mLatchTime
+ sizeof(nsecs_t) + // mFirstRefreshStartTime
+ sizeof(nsecs_t); // mLastRefreshStartTime
+}
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(
+ HGraphicBufferProducer::FrameEventsDelta const& t) {
+ return minFlattenedSize(t) +
+ getFlattenedSize(t.gpuCompositionDoneFence) +
+ getFlattenedSize(t.displayPresentFence) +
+ getFlattenedSize(t.displayRetireFence) +
+ getFlattenedSize(t.releaseFence);
+};
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+ HGraphicBufferProducer::FrameEventsDelta const& t) {
+ return getFdCount(t.gpuCompositionDoneFence) +
+ getFdCount(t.displayPresentFence) +
+ getFdCount(t.displayRetireFence) +
+ getFdCount(t.releaseFence);
+};
+
+/**
+ * \brief Unflatten `FrameEventsDelta`.
+ *
+ * \param[out] t The destination `FrameEventsDelta`.
+ * \param[out] nh The underlying array of native handles.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
+ * populated with `nullptr` or newly created handles. Each non-null slot in \p
+ * nh will need to be deleted manually with `native_handle_delete()`.
+ */
+status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
+ std::vector<native_handle_t*>* nh,
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+ if (size < minFlattenedSize(*t)) {
+ return NO_MEMORY;
+ }
+ FlattenableUtils::read(buffer, size, t->frameNumber);
+
+ // These were written as uint8_t for alignment.
+ uint8_t temp = 0;
+ FlattenableUtils::read(buffer, size, temp);
+ size_t index = static_cast<size_t>(temp);
+ if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+ return BAD_VALUE;
+ }
+ t->index = static_cast<uint32_t>(index);
+
+ FlattenableUtils::read(buffer, size, temp);
+ t->addPostCompositeCalled = static_cast<bool>(temp);
+ FlattenableUtils::read(buffer, size, temp);
+ t->addRetireCalled = static_cast<bool>(temp);
+ FlattenableUtils::read(buffer, size, temp);
+ t->addReleaseCalled = static_cast<bool>(temp);
+
+ FlattenableUtils::read(buffer, size, t->postedTimeNs);
+ FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
+ FlattenableUtils::read(buffer, size, t->latchTimeNs);
+ FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
+ FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
+ FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
+
+ // Fences
+ HGraphicBufferProducer::FenceTimeSnapshot* tSnapshot[4];
+ tSnapshot[0] = &t->gpuCompositionDoneFence;
+ tSnapshot[1] = &t->displayPresentFence;
+ tSnapshot[2] = &t->displayRetireFence;
+ tSnapshot[3] = &t->releaseFence;
+ nh->resize(4);
+ for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
+ status_t status = unflatten(
+ tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
+ buffer, size, fds, numFds);
+ if (status != NO_ERROR) {
+ while (snapshotIndex > 0) {
+ --snapshotIndex;
+ if ((*nh)[snapshotIndex] != nullptr) {
+ native_handle_delete((*nh)[snapshotIndex]);
+ }
+ }
+ return status;
+ }
+ }
+ return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `FrameEventsDelta`.
+ *
+ * \param[in] t The source `FrameEventsDelta`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate file descriptors contained in \p t.
+ */
+// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
+// FrameEventsDelta::flatten
+status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
+ void*& buffer, size_t& size, int*& fds, size_t numFds) {
+ // Check that t.index is within a valid range.
+ if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
+ || t.index > std::numeric_limits<uint8_t>::max()) {
+ return BAD_VALUE;
+ }
+
+ FlattenableUtils::write(buffer, size, t.frameNumber);
+
+ // These are static_cast to uint8_t for alignment.
+ FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
+ FlattenableUtils::write(
+ buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
+ FlattenableUtils::write(
+ buffer, size, static_cast<uint8_t>(t.addRetireCalled));
+ FlattenableUtils::write(
+ buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
+
+ FlattenableUtils::write(buffer, size, t.postedTimeNs);
+ FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
+ FlattenableUtils::write(buffer, size, t.latchTimeNs);
+ FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
+ FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
+ FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
+
+ // Fences
+ HGraphicBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
+ tSnapshot[0] = &t.gpuCompositionDoneFence;
+ tSnapshot[1] = &t.displayPresentFence;
+ tSnapshot[2] = &t.displayRetireFence;
+ tSnapshot[3] = &t.releaseFence;
+ for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
+ status_t status = flatten(
+ *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ }
+ return NO_ERROR;
+}
+
+// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(
+ HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
+ size_t size = 4 + // mDeltas.size()
+ sizeof(t.compositorTiming);
+ for (size_t i = 0; i < t.deltas.size(); ++i) {
+ size += getFlattenedSize(t.deltas[i]);
+ }
+ return size;
+}
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+ HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
+ size_t numFds = 0;
+ for (size_t i = 0; i < t.deltas.size(); ++i) {
+ numFds += getFdCount(t.deltas[i]);
+ }
+ return numFds;
+}
+
+/**
+ * \brief Unflatten `FrameEventHistoryDelta`.
+ *
+ * \param[out] t The destination `FrameEventHistoryDelta`.
+ * \param[out] nh The underlying array of arrays of native handles.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
+ * newly created handles. The second dimension of \p nh will be 4. Each non-null
+ * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
+ */
+status_t unflatten(
+ HGraphicBufferProducer::FrameEventHistoryDelta* t,
+ std::vector<std::vector<native_handle_t*> >* nh,
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+ if (size < 4) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::read(buffer, size, t->compositorTiming);
+
+ uint32_t deltaCount = 0;
+ FlattenableUtils::read(buffer, size, deltaCount);
+ if (static_cast<size_t>(deltaCount) >
+ ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+ return BAD_VALUE;
+ }
+ t->deltas.resize(deltaCount);
+ nh->resize(deltaCount);
+ for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
+ status_t status = unflatten(
+ &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
+ buffer, size, fds, numFds);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ }
+ return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `FrameEventHistoryDelta`.
+ *
+ * \param[in] t The source `FrameEventHistoryDelta`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate file descriptors contained in \p t.
+ */
+status_t flatten(
+ HGraphicBufferProducer::FrameEventHistoryDelta const& t,
+ void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+ if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+ return BAD_VALUE;
+ }
+ if (size < getFlattenedSize(t)) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::write(buffer, size, t.compositorTiming);
+
+ FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
+ for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
+ status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ }
+ return NO_ERROR;
+}
+
+/**
+ * \brief Wrap `::android::FrameEventHistoryData` in
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \param[out] nh The array of array of native handles that are referred to by
+ * members of \p t.
+ * \param[in] l The source `::android::FrameEventHistoryDelta`.
+ *
+ * On success, each member of \p nh will be either `nullptr` or a newly created
+ * native handle. All the non-`nullptr` elements must be deleted individually
+ * with `native_handle_delete()`.
+ */
+bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
+ std::vector<std::vector<native_handle_t*> >* nh,
+ ::android::FrameEventHistoryDelta const& l) {
+
+ size_t const baseSize = l.getFlattenedSize();
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ return false;
+ }
+
+ size_t const baseNumFds = l.getFdCount();
+ std::unique_ptr<int[]> baseFds(
+ new (std::nothrow) int[baseNumFds]);
+ if (!baseFds) {
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ int* fds = baseFds.get();
+ size_t numFds = baseNumFds;
+ if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ int const* constFds = static_cast<int const*>(baseFds.get());
+ numFds = baseNumFds;
+ if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
+ * `::android::FrameEventHistoryDelta`.
+ *
+ * \param[out] l The destination `::android::FrameEventHistoryDelta`.
+ * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * This function will duplicate all file descriptors contained in \p t.
+ */
+bool convertTo(
+ ::android::FrameEventHistoryDelta* l,
+ HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
+
+ size_t const baseSize = getFlattenedSize(t);
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ return false;
+ }
+
+ size_t const baseNumFds = getFdCount(t);
+ std::unique_ptr<int[]> baseFds(
+ new (std::nothrow) int[baseNumFds]);
+ if (!baseFds) {
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ int* fds = static_cast<int*>(baseFds.get());
+ size_t numFds = baseNumFds;
+ if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ int const* constFds = static_cast<int const*>(baseFds.get());
+ numFds = baseNumFds;
+ if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+// Ref: frameworks/native/libs/ui/Region.cpp
+
+/**
+ * \brief Return the size of the buffer required to flatten `Region`.
+ *
+ * \param[in] t The input `Region`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(Region const& t) {
+ return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
+}
+
+/**
+ * \brief Unflatten `Region`.
+ *
+ * \param[out] t The destination `Region`.
+ * \param[in,out] buffer The pointer to the flat buffer.
+ * \param[in,out] size The size of the flat buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t unflatten(Region* t, void const*& buffer, size_t& size) {
+ if (size < sizeof(uint32_t)) {
+ return NO_MEMORY;
+ }
+
+ uint32_t numRects = 0;
+ FlattenableUtils::read(buffer, size, numRects);
+ if (size < numRects * sizeof(Rect)) {
+ return NO_MEMORY;
+ }
+ if (numRects > (UINT32_MAX / sizeof(Rect))) {
+ return NO_MEMORY;
+ }
+
+ t->resize(numRects);
+ for (size_t r = 0; r < numRects; ++r) {
+ ::android::Rect rect(::android::Rect::EMPTY_RECT);
+ status_t status = rect.unflatten(buffer, size);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ FlattenableUtils::advance(buffer, size, sizeof(rect));
+ (*t)[r] = Rect{
+ static_cast<int32_t>(rect.left),
+ static_cast<int32_t>(rect.top),
+ static_cast<int32_t>(rect.right),
+ static_cast<int32_t>(rect.bottom)};
+ }
+ return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `Region`.
+ *
+ * \param[in] t The source `Region`.
+ * \param[in,out] buffer The pointer to the flat buffer.
+ * \param[in,out] size The size of the flat buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t flatten(Region const& t, void*& buffer, size_t& size) {
+ if (size < getFlattenedSize(t)) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
+ for (size_t r = 0; r < t.size(); ++r) {
+ ::android::Rect rect(
+ static_cast<int32_t>(t[r].left),
+ static_cast<int32_t>(t[r].top),
+ static_cast<int32_t>(t[r].right),
+ static_cast<int32_t>(t[r].bottom));
+ status_t status = rect.flatten(buffer, size);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ FlattenableUtils::advance(buffer, size, sizeof(rect));
+ }
+ return NO_ERROR;
+}
+
+/**
+ * \brief Convert `::android::Region` to `Region`.
+ *
+ * \param[out] t The destination `Region`.
+ * \param[in] l The source `::android::Region`.
+ */
+// convert: ::android::Region -> Region
+bool convertTo(Region* t, ::android::Region const& l) {
+ size_t const baseSize = l.getFlattenedSize();
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ if (l.flatten(buffer, size) != NO_ERROR) {
+ return false;
+ }
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ if (unflatten(t, constBuffer, size) != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * \brief Convert `Region` to `::android::Region`.
+ *
+ * \param[out] l The destination `::android::Region`.
+ * \param[in] t The source `Region`.
+ */
+// convert: Region -> ::android::Region
+bool convertTo(::android::Region* l, Region const& t) {
+ size_t const baseSize = getFlattenedSize(t);
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ if (flatten(t, buffer, size) != NO_ERROR) {
+ return false;
+ }
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ if (l->unflatten(constBuffer, size) != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
+// BGraphicBufferProducer::QueueBufferInput
+
+/**
+ * \brief Return a lower bound on the size of the buffer required to flatten
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return A lower bound on the size of the flat buffer.
+ */
+constexpr size_t minFlattenedSize(
+ HGraphicBufferProducer::QueueBufferInput const& /* t */) {
+ return sizeof(int64_t) + // timestamp
+ sizeof(int) + // isAutoTimestamp
+ sizeof(android_dataspace) + // dataSpace
+ sizeof(::android::Rect) + // crop
+ sizeof(int) + // scalingMode
+ sizeof(uint32_t) + // transform
+ sizeof(uint32_t) + // stickyTransform
+ sizeof(bool); // getFrameTimestamps
+}
+
+/**
+ * \brief Return the size of the buffer required to flatten
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t) {
+ return minFlattenedSize(t) +
+ getFenceFlattenedSize(t.fence) +
+ getFlattenedSize(t.surfaceDamage) +
+ sizeof(HdrMetadata::validTypes);
+}
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+ HGraphicBufferProducer::QueueBufferInput const& t) {
+ return getFenceFdCount(t.fence);
+}
+
+/**
+ * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The native handle cloned from `t.fence`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate the file descriptor in `t.fence`. */
+status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
+ native_handle_t** nh,
+ void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+ if (size < getFlattenedSize(t)) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::write(buffer, size, t.timestamp);
+ FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
+ FlattenableUtils::write(buffer, size,
+ static_cast<android_dataspace_t>(t.dataSpace));
+ FlattenableUtils::write(buffer, size, ::android::Rect(
+ static_cast<int32_t>(t.crop.left),
+ static_cast<int32_t>(t.crop.top),
+ static_cast<int32_t>(t.crop.right),
+ static_cast<int32_t>(t.crop.bottom)));
+ FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
+ FlattenableUtils::write(buffer, size, t.transform);
+ FlattenableUtils::write(buffer, size, t.stickyTransform);
+ FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
+
+ *nh = t.fence.getNativeHandle() == nullptr ?
+ nullptr : native_handle_clone(t.fence);
+ status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = flatten(t.surfaceDamage, buffer, size);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
+ return NO_ERROR;
+}
+
+/**
+ * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The underlying native handle for `t->fence`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR` and `t->fence` contains a valid file
+ * descriptor, \p nh will be a newly created native handle holding that file
+ * descriptor. \p nh needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+status_t unflatten(
+ HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+ if (size < minFlattenedSize(*t)) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::read(buffer, size, t->timestamp);
+ int lIsAutoTimestamp;
+ FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
+ t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
+ android_dataspace_t lDataSpace;
+ FlattenableUtils::read(buffer, size, lDataSpace);
+ t->dataSpace = static_cast<Dataspace>(lDataSpace);
+ Rect lCrop;
+ FlattenableUtils::read(buffer, size, lCrop);
+ t->crop = Rect{
+ static_cast<int32_t>(lCrop.left),
+ static_cast<int32_t>(lCrop.top),
+ static_cast<int32_t>(lCrop.right),
+ static_cast<int32_t>(lCrop.bottom)};
+ int lScalingMode;
+ FlattenableUtils::read(buffer, size, lScalingMode);
+ t->scalingMode = static_cast<int32_t>(lScalingMode);
+ FlattenableUtils::read(buffer, size, t->transform);
+ FlattenableUtils::read(buffer, size, t->stickyTransform);
+ FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
+
+ status_t status = unflattenFence(&(t->fence), nh,
+ buffer, size, fds, numFds);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ // HdrMetadata ignored
+ return unflatten(&(t->surfaceDamage), buffer, size);
+}
+
+/**
+ * \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The underlying native handle for `t->fence`.
+ * \param[in] l The source `BGraphicBufferProducer::QueueBufferInput`.
+ *
+ * If the return value is `true` and `t->fence` contains a valid file
+ * descriptor, \p nh will be a newly created native handle holding that file
+ * descriptor. \p nh needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+bool wrapAs(
+ HGraphicBufferProducer::QueueBufferInput* t,
+ native_handle_t** nh,
+ BGraphicBufferProducer::QueueBufferInput const& l) {
+
+ size_t const baseSize = l.getFlattenedSize();
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ return false;
+ }
+
+ size_t const baseNumFds = l.getFdCount();
+ std::unique_ptr<int[]> baseFds(
+ new (std::nothrow) int[baseNumFds]);
+ if (!baseFds) {
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ int* fds = baseFds.get();
+ size_t numFds = baseNumFds;
+ if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ int const* constFds = static_cast<int const*>(baseFds.get());
+ numFds = baseNumFds;
+ if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
+ * `BGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * If `t.fence` has a valid file descriptor, it will be duplicated.
+ */
+bool convertTo(
+ BGraphicBufferProducer::QueueBufferInput* l,
+ HGraphicBufferProducer::QueueBufferInput const& t) {
+
+ size_t const baseSize = getFlattenedSize(t);
+ std::unique_ptr<uint8_t[]> baseBuffer(
+ new (std::nothrow) uint8_t[baseSize]);
+ if (!baseBuffer) {
+ return false;
+ }
+
+ size_t const baseNumFds = getFdCount(t);
+ std::unique_ptr<int[]> baseFds(
+ new (std::nothrow) int[baseNumFds]);
+ if (!baseFds) {
+ return false;
+ }
+
+ void* buffer = static_cast<void*>(baseBuffer.get());
+ size_t size = baseSize;
+ int* fds = baseFds.get();
+ size_t numFds = baseNumFds;
+ native_handle_t* nh;
+ if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
+ return false;
+ }
+
+ void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+ size = baseSize;
+ int const* constFds = static_cast<int const*>(baseFds.get());
+ numFds = baseNumFds;
+ if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
+ if (nh != nullptr) {
+ native_handle_close(nh);
+ native_handle_delete(nh);
+ }
+ return false;
+ }
+
+ native_handle_delete(nh);
+ return true;
+}
+
+// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
+// BGraphicBufferProducer::QueueBufferOutput
+
+/**
+ * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
+ * `HGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::QueueBufferOutput`.
+ * \param[out] nh The array of array of native handles that are referred to by
+ * members of \p t.
+ * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * On success, each member of \p nh will be either `nullptr` or a newly created
+ * native handle. All the non-`nullptr` elements must be deleted individually
+ * with `native_handle_delete()`.
+ */
+// wrap: BGraphicBufferProducer::QueueBufferOutput ->
+// HGraphicBufferProducer::QueueBufferOutput
+bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
+ std::vector<std::vector<native_handle_t*> >* nh,
+ BGraphicBufferProducer::QueueBufferOutput const& l) {
+ if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
+ return false;
+ }
+ t->width = l.width;
+ t->height = l.height;
+ t->transformHint = l.transformHint;
+ t->numPendingBuffers = l.numPendingBuffers;
+ t->nextFrameNumber = l.nextFrameNumber;
+ t->bufferReplaced = l.bufferReplaced;
+ return true;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
+ * `BGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * This function will duplicate all file descriptors contained in \p t.
+ */
+// convert: HGraphicBufferProducer::QueueBufferOutput ->
+// BGraphicBufferProducer::QueueBufferOutput
+bool convertTo(
+ BGraphicBufferProducer::QueueBufferOutput* l,
+ HGraphicBufferProducer::QueueBufferOutput const& t) {
+ if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
+ return false;
+ }
+ l->width = t.width;
+ l->height = t.height;
+ l->transformHint = t.transformHint;
+ l->numPendingBuffers = t.numPendingBuffers;
+ l->nextFrameNumber = t.nextFrameNumber;
+ l->bufferReplaced = t.bufferReplaced;
+ return true;
+}
+
+/**
+ * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
+ * `HGraphicBufferProducer::DisconnectMode`.
+ *
+ * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
+ * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
+ */
+HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
+ BGraphicBufferProducer::DisconnectMode l) {
+ switch (l) {
+ case BGraphicBufferProducer::DisconnectMode::Api:
+ return HGraphicBufferProducer::DisconnectMode::API;
+ case BGraphicBufferProducer::DisconnectMode::AllLocal:
+ return HGraphicBufferProducer::DisconnectMode::ALL_LOCAL;
+ }
+ return HGraphicBufferProducer::DisconnectMode::API;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
+ * `BGraphicBufferProducer::DisconnectMode`.
+ *
+ * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
+ * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
+ */
+BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
+ HGraphicBufferProducer::DisconnectMode t) {
+ switch (t) {
+ case HGraphicBufferProducer::DisconnectMode::API:
+ return BGraphicBufferProducer::DisconnectMode::Api;
+ case HGraphicBufferProducer::DisconnectMode::ALL_LOCAL:
+ return BGraphicBufferProducer::DisconnectMode::AllLocal;
+ }
+ return BGraphicBufferProducer::DisconnectMode::Api;
+}
+
+} // namespace conversion
+} // namespace android
+
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/Conversion.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/Conversion.h
index c15fafa..60d8c1e 100644
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/Conversion.h
+++ b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/Conversion.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef MEDIA_STAGEFRIGHT_CONVERSION_H_
-#define MEDIA_STAGEFRIGHT_CONVERSION_H_
+#ifndef MEDIA_STAGEFRIGHT_BQHELPER_CONVERSION_H_
+#define MEDIA_STAGEFRIGHT_BQHELPER_CONVERSION_H_
#include <vector>
#include <list>
@@ -83,17 +83,7 @@
*
* This function does not duplicate the file descriptor.
*/
-inline native_handle_t* native_handle_create_from_fd(int fd) {
- if (fd < 2) {
- return native_handle_create(0, 0);
- }
- native_handle_t* nh = native_handle_create(1, 0);
- if (nh == nullptr) {
- return nullptr;
- }
- nh->data[0] = fd;
- return nh;
-}
+native_handle_t* native_handle_create_from_fd(int fd);
/**
* \brief Extract a file descriptor from a native handle.
@@ -106,11 +96,7 @@
*
* This function does not duplicate the file descriptor.
*/
-inline int native_handle_read_fd(native_handle_t const* nh, int index = 0) {
- return ((nh == nullptr) || (nh->numFds == 0) ||
- (nh->numFds <= index) || (index < 0)) ?
- -1 : nh->data[index];
-}
+int native_handle_read_fd(native_handle_t const* nh, int index = 0);
/**
* Conversion functions
@@ -151,12 +137,7 @@
* \return The corresponding `binder::Status`.
*/
// convert: Return<void> -> ::android::binder::Status
-inline ::android::binder::Status toBinderStatus(
- Return<void> const& t) {
- return ::android::binder::Status::fromExceptionCode(
- t.isOk() ? OK : UNKNOWN_ERROR,
- t.description().c_str());
-}
+::android::binder::Status toBinderStatus(Return<void> const& t);
/**
* \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
@@ -165,9 +146,7 @@
* \return The corresponding `status_t`.
*/
// convert: Return<void> -> status_t
-inline status_t toStatusT(Return<void> const& t) {
- return t.isOk() ? OK : UNKNOWN_ERROR;
-}
+status_t toStatusT(Return<void> const& t);
/**
* \brief Wrap `native_handle_t*` in `hidl_handle`.
@@ -176,9 +155,7 @@
* \return The `hidl_handle` that points to \p nh.
*/
// wrap: native_handle_t* -> hidl_handle
-inline hidl_handle inHidlHandle(native_handle_t const* nh) {
- return hidl_handle(nh);
-}
+hidl_handle inHidlHandle(native_handle_t const* nh);
/**
* \brief Convert `int32_t` to `Dataspace`.
@@ -187,9 +164,7 @@
* \result The corresponding `Dataspace`.
*/
// convert: int32_t -> Dataspace
-inline Dataspace toHardwareDataspace(int32_t l) {
- return static_cast<Dataspace>(l);
-}
+Dataspace toHardwareDataspace(int32_t l);
/**
* \brief Convert `Dataspace` to `int32_t`.
@@ -198,9 +173,7 @@
* \result The corresponding `int32_t`.
*/
// convert: Dataspace -> int32_t
-inline int32_t toRawDataspace(Dataspace const& t) {
- return static_cast<int32_t>(t);
-}
+int32_t toRawDataspace(Dataspace const& t);
/**
* \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
@@ -210,11 +183,7 @@
* \return A `hidl_vec<uint8_t>` that points to the buffer.
*/
// wrap: void*, size_t -> hidl_vec<uint8_t>
-inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
- hidl_vec<uint8_t> t;
- t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
- return t;
-}
+hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size);
/**
* \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
@@ -224,13 +193,7 @@
* \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
*/
// convert: void*, size_t -> hidl_vec<uint8_t>
-inline hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
- hidl_vec<uint8_t> t;
- t.resize(size);
- uint8_t const* src = static_cast<uint8_t const*>(l);
- std::copy(src, src + size, t.data());
- return t;
-}
+hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size);
/**
* \brief Wrap `GraphicBuffer` in `AnwBuffer`.
@@ -239,17 +202,7 @@
* \param[in] l The source `GraphicBuffer`.
*/
// wrap: GraphicBuffer -> AnwBuffer
-inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
- t->attr.width = l.getWidth();
- t->attr.height = l.getHeight();
- t->attr.stride = l.getStride();
- t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
- t->attr.layerCount = l.getLayerCount();
- t->attr.usage = l.getUsage();
- t->attr.id = l.getId();
- t->attr.generationNumber = l.getGenerationNumber();
- t->nativeHandle = hidl_handle(l.handle);
-}
+void wrapAs(AnwBuffer* t, GraphicBuffer const& l);
/**
* \brief Convert `AnwBuffer` to `GraphicBuffer`.
@@ -261,46 +214,7 @@
*/
// convert: AnwBuffer -> GraphicBuffer
// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
-inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
- native_handle_t* handle = t.nativeHandle == nullptr ?
- nullptr : native_handle_clone(t.nativeHandle);
-
- size_t const numInts = 12 + (handle ? handle->numInts : 0);
- int32_t* ints = new int32_t[numInts];
-
- size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
- int* fds = new int[numFds];
-
- ints[0] = 'GBFR';
- ints[1] = static_cast<int32_t>(t.attr.width);
- ints[2] = static_cast<int32_t>(t.attr.height);
- ints[3] = static_cast<int32_t>(t.attr.stride);
- ints[4] = static_cast<int32_t>(t.attr.format);
- ints[5] = static_cast<int32_t>(t.attr.layerCount);
- ints[6] = static_cast<int32_t>(t.attr.usage);
- ints[7] = static_cast<int32_t>(t.attr.id >> 32);
- ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
- ints[9] = static_cast<int32_t>(t.attr.generationNumber);
- ints[10] = 0;
- ints[11] = 0;
- if (handle) {
- ints[10] = static_cast<int32_t>(handle->numFds);
- ints[11] = static_cast<int32_t>(handle->numInts);
- int* intsStart = handle->data + handle->numFds;
- std::copy(handle->data, intsStart, fds);
- std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
- }
-
- void const* constBuffer = static_cast<void const*>(ints);
- size_t size = numInts * sizeof(int32_t);
- int const* constFds = static_cast<int const*>(fds);
- status_t status = l->unflatten(constBuffer, size, constFds, numFds);
-
- delete [] fds;
- delete [] ints;
- native_handle_delete(handle);
- return status == NO_ERROR;
-}
+bool convertTo(GraphicBuffer* l, AnwBuffer const& t);
/**
* Conversion functions for types outside media
@@ -387,9 +301,7 @@
* bytes required to store the number of file descriptors contained in the fd
* part of the flat buffer.
*/
-inline size_t getFenceFlattenedSize(hidl_handle const& /* fence */) {
- return 4;
-};
+size_t getFenceFlattenedSize(hidl_handle const& fence);
/**
* \brief Return the number of file descriptors contained in a fence.
@@ -398,9 +310,7 @@
* \return `0` if \p fence does not contain a valid file descriptor, or `1`
* otherwise.
*/
-inline size_t getFenceFdCount(hidl_handle const& fence) {
- return native_handle_read_fd(fence) == -1 ? 0 : 1;
-}
+size_t getFenceFdCount(hidl_handle const& fence);
/**
* \brief Unflatten `Fence` to `hidl_handle`.
@@ -417,38 +327,8 @@
* native handle, which needs to be deleted with `native_handle_delete()`
* afterwards.
*/
-inline status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < 4) {
- return NO_MEMORY;
- }
-
- uint32_t numFdsInHandle;
- FlattenableUtils::read(buffer, size, numFdsInHandle);
-
- if (numFdsInHandle > 1) {
- return BAD_VALUE;
- }
-
- if (numFds < numFdsInHandle) {
- return NO_MEMORY;
- }
-
- if (numFdsInHandle) {
- *nh = native_handle_create_from_fd(*fds);
- if (*nh == nullptr) {
- return NO_MEMORY;
- }
- *fence = *nh;
- ++fds;
- --numFds;
- } else {
- *nh = nullptr;
- *fence = hidl_handle();
- }
-
- return NO_ERROR;
-}
+status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
/**
* \brief Flatten `hidl_handle` as `Fence`.
@@ -460,24 +340,8 @@
* \param[in,out] numFds The size of the flat fd buffer.
* \return `NO_ERROR` on success; other value on failure.
*/
-inline status_t flattenFence(hidl_handle const& fence,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (size < getFenceFlattenedSize(fence) ||
- numFds < getFenceFdCount(fence)) {
- return NO_MEMORY;
- }
- // Cast to uint32_t since the size of a size_t can vary between 32- and
- // 64-bit processes
- FlattenableUtils::write(buffer, size,
- static_cast<uint32_t>(getFenceFdCount(fence)));
- int fd = native_handle_read_fd(fence);
- if (fd != -1) {
- *fds = fd;
- ++fds;
- --numFds;
- }
- return NO_ERROR;
-}
+status_t flattenFence(hidl_handle const& fence,
+ void*& buffer, size_t& size, int*& fds, size_t& numFds);
/**
* \brief Wrap `Fence` in `hidl_handle`.
@@ -490,40 +354,7 @@
* deleted manually with `native_handle_delete()` afterwards.
*/
// wrap: Fence -> hidl_handle
-inline bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l) {
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = l.getFdCount();
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = static_cast<int*>(baseFds.get());
- size_t numFds = baseNumFds;
- if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (unflattenFence(t, nh, constBuffer, size, constFds, numFds)
- != NO_ERROR) {
- return false;
- }
-
- return true;
-}
+bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l);
/**
* \brief Convert `hidl_handle` to `Fence`.
@@ -535,58 +366,7 @@
* If \p t contains a valid file descriptor, it will be duplicated.
*/
// convert: hidl_handle -> Fence
-inline bool convertTo(Fence* l, hidl_handle const& t) {
- int fd = native_handle_read_fd(t);
- if (fd != -1) {
- fd = dup(fd);
- if (fd == -1) {
- return false;
- }
- }
- native_handle_t* nh = native_handle_create_from_fd(fd);
- if (nh == nullptr) {
- if (fd != -1) {
- close(fd);
- }
- return false;
- }
-
- size_t const baseSize = getFenceFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- native_handle_delete(nh);
- return false;
- }
-
- size_t const baseNumFds = getFenceFdCount(t);
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- native_handle_delete(nh);
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = static_cast<int*>(baseFds.get());
- size_t numFds = baseNumFds;
- if (flattenFence(hidl_handle(nh), buffer, size, fds, numFds) != NO_ERROR) {
- native_handle_delete(nh);
- return false;
- }
- native_handle_delete(nh);
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
+bool convertTo(Fence* l, hidl_handle const& t);
// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
@@ -597,20 +377,7 @@
* \param[in] t The input `FenceTimeSnapshot`.
* \return The required size of the flat buffer.
*/
-inline size_t getFlattenedSize(
- HGraphicBufferProducer::FenceTimeSnapshot const& t) {
- constexpr size_t min = sizeof(t.state);
- switch (t.state) {
- case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
- return min;
- case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
- return min + getFenceFlattenedSize(t.fence);
- case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
- return min + sizeof(
- ::android::FenceTime::Snapshot::signalTime);
- }
- return 0;
-}
+size_t getFlattenedSize(HGraphicBufferProducer::FenceTimeSnapshot const& t);
/**
* \brief Return the number of file descriptors contained in
@@ -619,12 +386,7 @@
* \param[in] t The input `FenceTimeSnapshot`.
* \return The number of file descriptors contained in \p snapshot.
*/
-inline size_t getFdCount(
- HGraphicBufferProducer::FenceTimeSnapshot const& t) {
- return t.state ==
- HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE ?
- getFenceFdCount(t.fence) : 0;
-}
+size_t getFdCount(HGraphicBufferProducer::FenceTimeSnapshot const& t);
/**
* \brief Flatten `FenceTimeSnapshot`.
@@ -639,29 +401,8 @@
* This function will duplicate the file descriptor in `t.fence` if `t.state ==
* FENCE`.
*/
-inline status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- switch (t.state) {
- case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
- FlattenableUtils::write(buffer, size,
- ::android::FenceTime::Snapshot::State::EMPTY);
- return NO_ERROR;
- case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
- FlattenableUtils::write(buffer, size,
- ::android::FenceTime::Snapshot::State::FENCE);
- return flattenFence(t.fence, buffer, size, fds, numFds);
- case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
- FlattenableUtils::write(buffer, size,
- ::android::FenceTime::Snapshot::State::SIGNAL_TIME);
- FlattenableUtils::write(buffer, size, t.signalTimeNs);
- return NO_ERROR;
- }
- return NO_ERROR;
-}
+status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
+ void*& buffer, size_t& size, int*& fds, size_t& numFds);
/**
* \brief Unflatten `FenceTimeSnapshot`.
@@ -678,72 +419,20 @@
* file descriptor, \p nh will be created to hold that file descriptor. In this
* case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
*/
-inline status_t unflatten(
+status_t unflatten(
HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < sizeof(t->state)) {
- return NO_MEMORY;
- }
-
- *nh = nullptr;
- ::android::FenceTime::Snapshot::State state;
- FlattenableUtils::read(buffer, size, state);
- switch (state) {
- case ::android::FenceTime::Snapshot::State::EMPTY:
- t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY;
- return NO_ERROR;
- case ::android::FenceTime::Snapshot::State::FENCE:
- t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE;
- return unflattenFence(&t->fence, nh, buffer, size, fds, numFds);
- case ::android::FenceTime::Snapshot::State::SIGNAL_TIME:
- t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME;
- if (size < sizeof(t->signalTimeNs)) {
- return NO_MEMORY;
- }
- FlattenableUtils::read(buffer, size, t->signalTimeNs);
- return NO_ERROR;
- }
- return NO_ERROR;
-}
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
/**
- * \brief Return a lower bound on the size of the non-fd buffer required to
- * flatten `FrameEventsDelta`.
- *
- * \param[in] t The input `FrameEventsDelta`.
- * \return A lower bound on the size of the flat buffer.
- */
-constexpr size_t minFlattenedSize(
- HGraphicBufferProducer::FrameEventsDelta const& /* t */) {
- return sizeof(uint64_t) + // mFrameNumber
- sizeof(uint8_t) + // mIndex
- sizeof(uint8_t) + // mAddPostCompositeCalled
- sizeof(uint8_t) + // mAddRetireCalled
- sizeof(uint8_t) + // mAddReleaseCalled
- sizeof(nsecs_t) + // mPostedTime
- sizeof(nsecs_t) + // mRequestedPresentTime
- sizeof(nsecs_t) + // mLatchTime
- sizeof(nsecs_t) + // mFirstRefreshStartTime
- sizeof(nsecs_t); // mLastRefreshStartTime
-}
-
-/**
* \brief Return the size of the non-fd buffer required to flatten
* `FrameEventsDelta`.
*
* \param[in] t The input `FrameEventsDelta`.
* \return The required size of the flat buffer.
*/
-inline size_t getFlattenedSize(
- HGraphicBufferProducer::FrameEventsDelta const& t) {
- return minFlattenedSize(t) +
- getFlattenedSize(t.gpuCompositionDoneFence) +
- getFlattenedSize(t.displayPresentFence) +
- getFlattenedSize(t.displayRetireFence) +
- getFlattenedSize(t.releaseFence);
-};
+size_t getFlattenedSize(HGraphicBufferProducer::FrameEventsDelta const& t);
/**
* \brief Return the number of file descriptors contained in
@@ -752,13 +441,7 @@
* \param[in] t The input `FrameEventsDelta`.
* \return The number of file descriptors contained in \p t.
*/
-inline size_t getFdCount(
- HGraphicBufferProducer::FrameEventsDelta const& t) {
- return getFdCount(t.gpuCompositionDoneFence) +
- getFdCount(t.displayPresentFence) +
- getFdCount(t.displayRetireFence) +
- getFdCount(t.releaseFence);
-};
+size_t getFdCount(HGraphicBufferProducer::FrameEventsDelta const& t);
/**
* \brief Unflatten `FrameEventsDelta`.
@@ -775,60 +458,9 @@
* populated with `nullptr` or newly created handles. Each non-null slot in \p
* nh will need to be deleted manually with `native_handle_delete()`.
*/
-inline status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
+status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
std::vector<native_handle_t*>* nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < minFlattenedSize(*t)) {
- return NO_MEMORY;
- }
- FlattenableUtils::read(buffer, size, t->frameNumber);
-
- // These were written as uint8_t for alignment.
- uint8_t temp = 0;
- FlattenableUtils::read(buffer, size, temp);
- size_t index = static_cast<size_t>(temp);
- if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
- return BAD_VALUE;
- }
- t->index = static_cast<uint32_t>(index);
-
- FlattenableUtils::read(buffer, size, temp);
- t->addPostCompositeCalled = static_cast<bool>(temp);
- FlattenableUtils::read(buffer, size, temp);
- t->addRetireCalled = static_cast<bool>(temp);
- FlattenableUtils::read(buffer, size, temp);
- t->addReleaseCalled = static_cast<bool>(temp);
-
- FlattenableUtils::read(buffer, size, t->postedTimeNs);
- FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
- FlattenableUtils::read(buffer, size, t->latchTimeNs);
- FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
- FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
- FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
-
- // Fences
- HGraphicBufferProducer::FenceTimeSnapshot* tSnapshot[4];
- tSnapshot[0] = &t->gpuCompositionDoneFence;
- tSnapshot[1] = &t->displayPresentFence;
- tSnapshot[2] = &t->displayRetireFence;
- tSnapshot[3] = &t->releaseFence;
- nh->resize(4);
- for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
- status_t status = unflatten(
- tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
- buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- while (snapshotIndex > 0) {
- --snapshotIndex;
- if ((*nh)[snapshotIndex] != nullptr) {
- native_handle_delete((*nh)[snapshotIndex]);
- }
- }
- return status;
- }
- }
- return NO_ERROR;
-}
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
/**
* \brief Flatten `FrameEventsDelta`.
@@ -844,47 +476,8 @@
*/
// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
// FrameEventsDelta::flatten
-inline status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
- void*& buffer, size_t& size, int*& fds, size_t numFds) {
- // Check that t.index is within a valid range.
- if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
- || t.index > std::numeric_limits<uint8_t>::max()) {
- return BAD_VALUE;
- }
-
- FlattenableUtils::write(buffer, size, t.frameNumber);
-
- // These are static_cast to uint8_t for alignment.
- FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
- FlattenableUtils::write(
- buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
- FlattenableUtils::write(
- buffer, size, static_cast<uint8_t>(t.addRetireCalled));
- FlattenableUtils::write(
- buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
-
- FlattenableUtils::write(buffer, size, t.postedTimeNs);
- FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
- FlattenableUtils::write(buffer, size, t.latchTimeNs);
- FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
- FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
- FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
-
- // Fences
- HGraphicBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
- tSnapshot[0] = &t.gpuCompositionDoneFence;
- tSnapshot[1] = &t.displayPresentFence;
- tSnapshot[2] = &t.displayRetireFence;
- tSnapshot[3] = &t.releaseFence;
- for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
- status_t status = flatten(
- *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
+status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
+ void*& buffer, size_t& size, int*& fds, size_t numFds);
// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
@@ -895,15 +488,8 @@
* \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
* \return The required size of the flat buffer.
*/
-inline size_t getFlattenedSize(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
- size_t size = 4 + // mDeltas.size()
- sizeof(t.compositorTiming);
- for (size_t i = 0; i < t.deltas.size(); ++i) {
- size += getFlattenedSize(t.deltas[i]);
- }
- return size;
-}
+size_t getFlattenedSize(
+ HGraphicBufferProducer::FrameEventHistoryDelta const& t);
/**
* \brief Return the number of file descriptors contained in
@@ -912,14 +498,8 @@
* \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
* \return The number of file descriptors contained in \p t.
*/
-inline size_t getFdCount(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
- size_t numFds = 0;
- for (size_t i = 0; i < t.deltas.size(); ++i) {
- numFds += getFdCount(t.deltas[i]);
- }
- return numFds;
-}
+size_t getFdCount(
+ HGraphicBufferProducer::FrameEventHistoryDelta const& t);
/**
* \brief Unflatten `FrameEventHistoryDelta`.
@@ -936,34 +516,10 @@
* newly created handles. The second dimension of \p nh will be 4. Each non-null
* slot in \p nh will need to be deleted manually with `native_handle_delete()`.
*/
-inline status_t unflatten(
+status_t unflatten(
HGraphicBufferProducer::FrameEventHistoryDelta* t,
std::vector<std::vector<native_handle_t*> >* nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < 4) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, t->compositorTiming);
-
- uint32_t deltaCount = 0;
- FlattenableUtils::read(buffer, size, deltaCount);
- if (static_cast<size_t>(deltaCount) >
- ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
- return BAD_VALUE;
- }
- t->deltas.resize(deltaCount);
- nh->resize(deltaCount);
- for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
- status_t status = unflatten(
- &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
- buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
/**
* \brief Flatten `FrameEventHistoryDelta`.
@@ -977,27 +533,9 @@
*
* This function will duplicate file descriptors contained in \p t.
*/
-inline status_t flatten(
+status_t flatten(
HGraphicBufferProducer::FrameEventHistoryDelta const& t,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
- return BAD_VALUE;
- }
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, t.compositorTiming);
-
- FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
- for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
- status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
+ void*& buffer, size_t& size, int*& fds, size_t& numFds);
/**
* \brief Wrap `::android::FrameEventHistoryData` in
@@ -1013,42 +551,9 @@
* native handle. All the non-`nullptr` elements must be deleted individually
* with `native_handle_delete()`.
*/
-inline bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
+bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
std::vector<std::vector<native_handle_t*> >* nh,
- ::android::FrameEventHistoryDelta const& l) {
-
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = l.getFdCount();
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = baseFds.get();
- size_t numFds = baseNumFds;
- if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
+ ::android::FrameEventHistoryDelta const& l);
/**
* \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
@@ -1059,42 +564,9 @@
*
* This function will duplicate all file descriptors contained in \p t.
*/
-inline bool convertTo(
+bool convertTo(
::android::FrameEventHistoryDelta* l,
- HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
-
- size_t const baseSize = getFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = getFdCount(t);
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = static_cast<int*>(baseFds.get());
- size_t numFds = baseNumFds;
- if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
+ HGraphicBufferProducer::FrameEventHistoryDelta const& t);
// Ref: frameworks/native/libs/ui/Region.cpp
@@ -1104,9 +576,7 @@
* \param[in] t The input `Region`.
* \return The required size of the flat buffer.
*/
-inline size_t getFlattenedSize(Region const& t) {
- return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
-}
+size_t getFlattenedSize(Region const& t);
/**
* \brief Unflatten `Region`.
@@ -1116,36 +586,7 @@
* \param[in,out] size The size of the flat buffer.
* \return `NO_ERROR` on success; other value on failure.
*/
-inline status_t unflatten(Region* t, void const*& buffer, size_t& size) {
- if (size < sizeof(uint32_t)) {
- return NO_MEMORY;
- }
-
- uint32_t numRects = 0;
- FlattenableUtils::read(buffer, size, numRects);
- if (size < numRects * sizeof(Rect)) {
- return NO_MEMORY;
- }
- if (numRects > (UINT32_MAX / sizeof(Rect))) {
- return NO_MEMORY;
- }
-
- t->resize(numRects);
- for (size_t r = 0; r < numRects; ++r) {
- ::android::Rect rect(::android::Rect::EMPTY_RECT);
- status_t status = rect.unflatten(buffer, size);
- if (status != NO_ERROR) {
- return status;
- }
- FlattenableUtils::advance(buffer, size, sizeof(rect));
- (*t)[r] = Rect{
- static_cast<int32_t>(rect.left),
- static_cast<int32_t>(rect.top),
- static_cast<int32_t>(rect.right),
- static_cast<int32_t>(rect.bottom)};
- }
- return NO_ERROR;
-}
+status_t unflatten(Region* t, void const*& buffer, size_t& size);
/**
* \brief Flatten `Region`.
@@ -1155,26 +596,7 @@
* \param[in,out] size The size of the flat buffer.
* \return `NO_ERROR` on success; other value on failure.
*/
-inline status_t flatten(Region const& t, void*& buffer, size_t& size) {
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
- for (size_t r = 0; r < t.size(); ++r) {
- ::android::Rect rect(
- static_cast<int32_t>(t[r].left),
- static_cast<int32_t>(t[r].top),
- static_cast<int32_t>(t[r].right),
- static_cast<int32_t>(t[r].bottom));
- status_t status = rect.flatten(buffer, size);
- if (status != NO_ERROR) {
- return status;
- }
- FlattenableUtils::advance(buffer, size, sizeof(rect));
- }
- return NO_ERROR;
-}
+status_t flatten(Region const& t, void*& buffer, size_t& size);
/**
* \brief Convert `::android::Region` to `Region`.
@@ -1183,28 +605,7 @@
* \param[in] l The source `::android::Region`.
*/
// convert: ::android::Region -> Region
-inline bool convertTo(Region* t, ::android::Region const& l) {
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- if (l.flatten(buffer, size) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- if (unflatten(t, constBuffer, size) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
+bool convertTo(Region* t, ::android::Region const& l);
/**
* \brief Convert `Region` to `::android::Region`.
@@ -1213,64 +614,19 @@
* \param[in] t The source `Region`.
*/
// convert: Region -> ::android::Region
-inline bool convertTo(::android::Region* l, Region const& t) {
- size_t const baseSize = getFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- if (flatten(t, buffer, size) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- if (l->unflatten(constBuffer, size) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
+bool convertTo(::android::Region* l, Region const& t);
// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
// BGraphicBufferProducer::QueueBufferInput
/**
- * \brief Return a lower bound on the size of the buffer required to flatten
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
- * \return A lower bound on the size of the flat buffer.
- */
-constexpr size_t minFlattenedSize(
- HGraphicBufferProducer::QueueBufferInput const& /* t */) {
- return sizeof(int64_t) + // timestamp
- sizeof(int) + // isAutoTimestamp
- sizeof(android_dataspace) + // dataSpace
- sizeof(::android::Rect) + // crop
- sizeof(int) + // scalingMode
- sizeof(uint32_t) + // transform
- sizeof(uint32_t) + // stickyTransform
- sizeof(bool); // getFrameTimestamps
-}
-
-/**
* \brief Return the size of the buffer required to flatten
* `HGraphicBufferProducer::QueueBufferInput`.
*
* \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
* \return The required size of the flat buffer.
*/
-inline size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t) {
- return minFlattenedSize(t) +
- getFenceFlattenedSize(t.fence) +
- getFlattenedSize(t.surfaceDamage) +
- sizeof(HdrMetadata::validTypes);
-}
+size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t);
/**
* \brief Return the number of file descriptors contained in
@@ -1279,11 +635,8 @@
* \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
* \return The number of file descriptors contained in \p t.
*/
-inline size_t getFdCount(
- HGraphicBufferProducer::QueueBufferInput const& t) {
- return getFenceFdCount(t.fence);
-}
-
+size_t getFdCount(
+ HGraphicBufferProducer::QueueBufferInput const& t);
/**
* \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
*
@@ -1296,40 +649,9 @@
* \return `NO_ERROR` on success; other value on failure.
*
* This function will duplicate the file descriptor in `t.fence`. */
-inline status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
+status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
native_handle_t** nh,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, t.timestamp);
- FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
- FlattenableUtils::write(buffer, size,
- static_cast<android_dataspace_t>(t.dataSpace));
- FlattenableUtils::write(buffer, size, ::android::Rect(
- static_cast<int32_t>(t.crop.left),
- static_cast<int32_t>(t.crop.top),
- static_cast<int32_t>(t.crop.right),
- static_cast<int32_t>(t.crop.bottom)));
- FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
- FlattenableUtils::write(buffer, size, t.transform);
- FlattenableUtils::write(buffer, size, t.stickyTransform);
- FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
-
- *nh = t.fence.getNativeHandle() == nullptr ?
- nullptr : native_handle_clone(t.fence);
- status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- status = flatten(t.surfaceDamage, buffer, size);
- if (status != NO_ERROR) {
- return status;
- }
- FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
- return NO_ERROR;
-}
+ void*& buffer, size_t& size, int*& fds, size_t& numFds);
/**
* \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
@@ -1347,42 +669,9 @@
* descriptor. \p nh needs to be deleted with `native_handle_delete()`
* afterwards.
*/
-inline status_t unflatten(
+status_t unflatten(
HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < minFlattenedSize(*t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, t->timestamp);
- int lIsAutoTimestamp;
- FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
- t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
- android_dataspace_t lDataSpace;
- FlattenableUtils::read(buffer, size, lDataSpace);
- t->dataSpace = static_cast<Dataspace>(lDataSpace);
- Rect lCrop;
- FlattenableUtils::read(buffer, size, lCrop);
- t->crop = Rect{
- static_cast<int32_t>(lCrop.left),
- static_cast<int32_t>(lCrop.top),
- static_cast<int32_t>(lCrop.right),
- static_cast<int32_t>(lCrop.bottom)};
- int lScalingMode;
- FlattenableUtils::read(buffer, size, lScalingMode);
- t->scalingMode = static_cast<int32_t>(lScalingMode);
- FlattenableUtils::read(buffer, size, t->transform);
- FlattenableUtils::read(buffer, size, t->stickyTransform);
- FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
-
- status_t status = unflattenFence(&(t->fence), nh,
- buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- // HdrMetadata ignored
- return unflatten(&(t->surfaceDamage), buffer, size);
-}
+ void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
/**
* \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
@@ -1398,43 +687,10 @@
* descriptor. \p nh needs to be deleted with `native_handle_delete()`
* afterwards.
*/
-inline bool wrapAs(
+bool wrapAs(
HGraphicBufferProducer::QueueBufferInput* t,
native_handle_t** nh,
- BGraphicBufferProducer::QueueBufferInput const& l) {
-
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = l.getFdCount();
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = baseFds.get();
- size_t numFds = baseNumFds;
- if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
+ BGraphicBufferProducer::QueueBufferInput const& l);
/**
* \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
@@ -1445,48 +701,9 @@
*
* If `t.fence` has a valid file descriptor, it will be duplicated.
*/
-inline bool convertTo(
+bool convertTo(
BGraphicBufferProducer::QueueBufferInput* l,
- HGraphicBufferProducer::QueueBufferInput const& t) {
-
- size_t const baseSize = getFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = getFdCount(t);
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = baseFds.get();
- size_t numFds = baseNumFds;
- native_handle_t* nh;
- if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
- if (nh != nullptr) {
- native_handle_close(nh);
- native_handle_delete(nh);
- }
- return false;
- }
-
- native_handle_delete(nh);
- return true;
-}
+ HGraphicBufferProducer::QueueBufferInput const& t);
// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
// BGraphicBufferProducer::QueueBufferOutput
@@ -1507,20 +724,9 @@
*/
// wrap: BGraphicBufferProducer::QueueBufferOutput ->
// HGraphicBufferProducer::QueueBufferOutput
-inline bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
+bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
std::vector<std::vector<native_handle_t*> >* nh,
- BGraphicBufferProducer::QueueBufferOutput const& l) {
- if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
- return false;
- }
- t->width = l.width;
- t->height = l.height;
- t->transformHint = l.transformHint;
- t->numPendingBuffers = l.numPendingBuffers;
- t->nextFrameNumber = l.nextFrameNumber;
- t->bufferReplaced = l.bufferReplaced;
- return true;
-}
+ BGraphicBufferProducer::QueueBufferOutput const& l);
/**
* \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
@@ -1533,20 +739,9 @@
*/
// convert: HGraphicBufferProducer::QueueBufferOutput ->
// BGraphicBufferProducer::QueueBufferOutput
-inline bool convertTo(
+bool convertTo(
BGraphicBufferProducer::QueueBufferOutput* l,
- HGraphicBufferProducer::QueueBufferOutput const& t) {
- if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
- return false;
- }
- l->width = t.width;
- l->height = t.height;
- l->transformHint = t.transformHint;
- l->numPendingBuffers = t.numPendingBuffers;
- l->nextFrameNumber = t.nextFrameNumber;
- l->bufferReplaced = t.bufferReplaced;
- return true;
-}
+ HGraphicBufferProducer::QueueBufferOutput const& t);
/**
* \brief Convert `BGraphicBufferProducer::DisconnectMode` to
@@ -1555,16 +750,8 @@
* \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
* \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
*/
-inline HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
- BGraphicBufferProducer::DisconnectMode l) {
- switch (l) {
- case BGraphicBufferProducer::DisconnectMode::Api:
- return HGraphicBufferProducer::DisconnectMode::API;
- case BGraphicBufferProducer::DisconnectMode::AllLocal:
- return HGraphicBufferProducer::DisconnectMode::ALL_LOCAL;
- }
- return HGraphicBufferProducer::DisconnectMode::API;
-}
+HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
+ BGraphicBufferProducer::DisconnectMode l);
/**
* \brief Convert `HGraphicBufferProducer::DisconnectMode` to
@@ -1573,18 +760,10 @@
* \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
* \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
*/
-inline BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
- HGraphicBufferProducer::DisconnectMode t) {
- switch (t) {
- case HGraphicBufferProducer::DisconnectMode::API:
- return BGraphicBufferProducer::DisconnectMode::Api;
- case HGraphicBufferProducer::DisconnectMode::ALL_LOCAL:
- return BGraphicBufferProducer::DisconnectMode::AllLocal;
- }
- return BGraphicBufferProducer::DisconnectMode::Api;
-}
+BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
+ HGraphicBufferProducer::DisconnectMode t);
} // namespace conversion
} // namespace android
-#endif // MEDIA_STAGEFRIGHT_CONVERSION_H_
+#endif // MEDIA_STAGEFRIGHT_BQHELPER_CONVERSION_H_
diff --git a/media/libstagefright/codec2/vndk/Android.bp b/media/libstagefright/codec2/vndk/Android.bp
index 95e7c39..8966933 100644
--- a/media/libstagefright/codec2/vndk/Android.bp
+++ b/media/libstagefright/codec2/vndk/Android.bp
@@ -5,10 +5,12 @@
"internal",
],
- vendor_available: false,
vndk: {
enabled: true,
},
+
+ // TODO: Remove this when this module is moved back to frameworks/av.
+ vendor_available: true,
}
cc_library_shared {
diff --git a/media/libstagefright/codecs/aacdec/Android.bp b/media/libstagefright/codecs/aacdec/Android.bp
index 9931e2d..7352854 100644
--- a/media/libstagefright/codecs/aacdec/Android.bp
+++ b/media/libstagefright/codecs/aacdec/Android.bp
@@ -1,45 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2aacdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: [
- "C2SoftAac.cpp",
- "DrcPresModeWrap.cpp",
- ],
-
- cflags: ["-Werror"],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libFraunhoferAAC",
- ],
-
- shared_libs: [
- "libcutils",
- "libion",
- "liblog",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libutils",
- ],
-}
-
-cc_library_shared {
name: "libstagefright_soft_aacdec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
deleted file mode 100644
index 6bd15a5..0000000
--- a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * 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 "C2SoftAac"
-#include <utils/Log.h>
-
-#include "C2SoftAac.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/misc.h>
-
-#include <inttypes.h>
-#include <math.h>
-#include <numeric>
-
-#define FILEREAD_MAX_LAYERS 2
-
-#define DRC_DEFAULT_MOBILE_REF_LEVEL 64 /* 64*-0.25dB = -16 dB below full scale for mobile conf */
-#define DRC_DEFAULT_MOBILE_DRC_CUT 127 /* maximum compression of dynamic range for mobile conf */
-#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
-#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1 /* switch for heavy compression for mobile conf */
-#define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
-#define MAX_CHANNEL_COUNT 8 /* maximum number of audio channels that can be decoded */
-// names of properties that can be used to override the default DRC settings
-#define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level"
-#define PROP_DRC_OVERRIDE_CUT "aac_drc_cut"
-#define PROP_DRC_OVERRIDE_BOOST "aac_drc_boost"
-#define PROP_DRC_OVERRIDE_HEAVY "aac_drc_heavy"
-#define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level"
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.aac.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftAac::C2SoftAac(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mAACDecoder(NULL),
- mStreamInfo(NULL),
- mIsADTS(false),
- mSignalledError(false),
- mOutputDelayRingBuffer(NULL) {
-}
-
-C2SoftAac::~C2SoftAac() {
- onRelease();
-}
-
-c2_status_t C2SoftAac::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_CORRUPTED;
-}
-
-c2_status_t C2SoftAac::onStop() {
- drainDecoder();
- // reset the "configured" state
- mOutputDelayCompensated = 0;
- mOutputDelayRingBufferWritePos = 0;
- mOutputDelayRingBufferReadPos = 0;
- mOutputDelayRingBufferFilled = 0;
- mBuffersInfo.clear();
-
- // To make the codec behave the same before and after a reset, we need to invalidate the
- // streaminfo struct. This does that:
- mStreamInfo->sampleRate = 0; // TODO: mStreamInfo is read only
-
- mSignalledError = false;
-
- return C2_OK;
-}
-
-void C2SoftAac::onReset() {
- (void)onStop();
-}
-
-void C2SoftAac::onRelease() {
- if (mAACDecoder) {
- aacDecoder_Close(mAACDecoder);
- mAACDecoder = NULL;
- }
- if (mOutputDelayRingBuffer) {
- delete[] mOutputDelayRingBuffer;
- mOutputDelayRingBuffer = NULL;
- }
-}
-
-status_t C2SoftAac::initDecoder() {
- ALOGV("initDecoder()");
- status_t status = UNKNOWN_ERROR;
- mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1);
- if (mAACDecoder != NULL) {
- mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder);
- if (mStreamInfo != NULL) {
- status = OK;
- }
- }
-
- mOutputDelayCompensated = 0;
- mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax;
- mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize];
- mOutputDelayRingBufferWritePos = 0;
- mOutputDelayRingBufferReadPos = 0;
- mOutputDelayRingBufferFilled = 0;
-
- if (mAACDecoder == NULL) {
- ALOGE("AAC decoder is null. TODO: Can not call aacDecoder_SetParam in the following code");
- }
-
- //aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE, 0);
-
- //init DRC wrapper
- mDrcWrap.setDecoderHandle(mAACDecoder);
- mDrcWrap.submitStreamData(mStreamInfo);
-
- // for streams that contain metadata, use the mobile profile DRC settings unless overridden by platform properties
- // TODO: change the DRC settings depending on audio output device type (HDMI, loadspeaker, headphone)
- char value[PROPERTY_VALUE_MAX];
- // DRC_PRES_MODE_WRAP_DESIRED_TARGET
- if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) {
- unsigned refLevel = atoi(value);
- ALOGV("AAC decoder using desired DRC target reference level of %d instead of %d", refLevel,
- DRC_DEFAULT_MOBILE_REF_LEVEL);
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, refLevel);
- } else {
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, DRC_DEFAULT_MOBILE_REF_LEVEL);
- }
- // DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
- if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) {
- unsigned cut = atoi(value);
- ALOGV("AAC decoder using desired DRC attenuation factor of %d instead of %d", cut,
- DRC_DEFAULT_MOBILE_DRC_CUT);
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, cut);
- } else {
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT);
- }
- // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
- if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) {
- unsigned boost = atoi(value);
- ALOGV("AAC decoder using desired DRC boost factor of %d instead of %d", boost,
- DRC_DEFAULT_MOBILE_DRC_BOOST);
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, boost);
- } else {
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
- }
- // DRC_PRES_MODE_WRAP_DESIRED_HEAVY
- if (property_get(PROP_DRC_OVERRIDE_HEAVY, value, NULL)) {
- unsigned heavy = atoi(value);
- ALOGV("AAC decoder using desried DRC heavy compression switch of %d instead of %d", heavy,
- DRC_DEFAULT_MOBILE_DRC_HEAVY);
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, heavy);
- } else {
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
- }
- // DRC_PRES_MODE_WRAP_ENCODER_TARGET
- if (property_get(PROP_DRC_OVERRIDE_ENC_LEVEL, value, NULL)) {
- unsigned encoderRefLevel = atoi(value);
- ALOGV("AAC decoder using encoder-side DRC reference level of %d instead of %d",
- encoderRefLevel, DRC_DEFAULT_MOBILE_ENC_LEVEL);
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, encoderRefLevel);
- } else {
- mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, DRC_DEFAULT_MOBILE_ENC_LEVEL);
- }
-
- // By default, the decoder creates a 5.1 channel downmix signal.
- // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
- aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
-
- return status;
-}
-
-bool C2SoftAac::outputDelayRingBufferPutSamples(INT_PCM *samples, int32_t numSamples) {
- if (numSamples == 0) {
- return true;
- }
- if (outputDelayRingBufferSpaceLeft() < numSamples) {
- ALOGE("RING BUFFER WOULD OVERFLOW");
- return false;
- }
- if (mOutputDelayRingBufferWritePos + numSamples <= mOutputDelayRingBufferSize
- && (mOutputDelayRingBufferReadPos <= mOutputDelayRingBufferWritePos
- || mOutputDelayRingBufferReadPos > mOutputDelayRingBufferWritePos + numSamples)) {
- // faster memcopy loop without checks, if the preconditions allow this
- for (int32_t i = 0; i < numSamples; i++) {
- mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos++] = samples[i];
- }
-
- if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
- mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
- }
- } else {
- ALOGV("slow C2SoftAac::outputDelayRingBufferPutSamples()");
-
- for (int32_t i = 0; i < numSamples; i++) {
- mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos] = samples[i];
- mOutputDelayRingBufferWritePos++;
- if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
- mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
- }
- }
- }
- mOutputDelayRingBufferFilled += numSamples;
- return true;
-}
-
-int32_t C2SoftAac::outputDelayRingBufferGetSamples(INT_PCM *samples, int32_t numSamples) {
-
- if (numSamples > mOutputDelayRingBufferFilled) {
- ALOGE("RING BUFFER WOULD UNDERRUN");
- return -1;
- }
-
- if (mOutputDelayRingBufferReadPos + numSamples <= mOutputDelayRingBufferSize
- && (mOutputDelayRingBufferWritePos < mOutputDelayRingBufferReadPos
- || mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferReadPos + numSamples)) {
- // faster memcopy loop without checks, if the preconditions allow this
- if (samples != 0) {
- for (int32_t i = 0; i < numSamples; i++) {
- samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos++];
- }
- } else {
- mOutputDelayRingBufferReadPos += numSamples;
- }
- if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
- mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
- }
- } else {
- ALOGV("slow C2SoftAac::outputDelayRingBufferGetSamples()");
-
- for (int32_t i = 0; i < numSamples; i++) {
- if (samples != 0) {
- samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos];
- }
- mOutputDelayRingBufferReadPos++;
- if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
- mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
- }
- }
- }
- mOutputDelayRingBufferFilled -= numSamples;
- return numSamples;
-}
-
-int32_t C2SoftAac::outputDelayRingBufferSamplesAvailable() {
- return mOutputDelayRingBufferFilled;
-}
-
-int32_t C2SoftAac::outputDelayRingBufferSpaceLeft() {
- return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable();
-}
-
-void C2SoftAac::drainRingBuffer(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool,
- bool eos) {
- while (!mBuffersInfo.empty() && outputDelayRingBufferSamplesAvailable()
- >= mStreamInfo->frameSize * mStreamInfo->numChannels) {
- Info &outInfo = mBuffersInfo.front();
- ALOGV("outInfo.frameIndex = %" PRIu64, outInfo.frameIndex);
- int samplesize = mStreamInfo->numChannels * sizeof(int16_t);
-
- int available = outputDelayRingBufferSamplesAvailable();
- int numFrames = outInfo.decodedSizes.size();
- int numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels);
- if (available < numSamples) {
- if (eos) {
- numSamples = available;
- } else {
- break;
- }
- }
- ALOGV("%d samples available (%d), or %d frames",
- numSamples, available, numFrames);
- ALOGV("getting %d from ringbuffer", numSamples);
-
- std::shared_ptr<C2LinearBlock> block;
- std::function<void(const std::unique_ptr<C2Work>&)> fillWork =
- [&block, numSamples, pool, this]()
- -> std::function<void(const std::unique_ptr<C2Work>&)> {
- auto fillEmptyWork = [](const std::unique_ptr<C2Work> &work, c2_status_t err) {
- work->result = err;
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
-
- using namespace std::placeholders;
- if (numSamples == 0) {
- return std::bind(fillEmptyWork, _1, C2_OK);
- }
-
- // TODO: error handling, proper usage, etc.
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(
- numSamples * sizeof(int16_t), usage, &block);
- if (err != C2_OK) {
- ALOGD("failed to fetch a linear block (%d)", err);
- mSignalledError = true;
- return std::bind(fillEmptyWork, _1, C2_NO_MEMORY);
- }
- C2WriteView wView = block->map().get();
- // TODO
- INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(wView.data());
- int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples);
- if (ns != numSamples) {
- ALOGE("not a complete frame of samples available");
- mSignalledError = true;
- return std::bind(fillEmptyWork, _1, C2_CORRUPTED);
- }
- return [buffer = createLinearBuffer(block)](const std::unique_ptr<C2Work> &work) {
- work->result = C2_OK;
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
- }();
-
- if (work && work->input.ordinal.frameIndex == c2_cntr64_t(outInfo.frameIndex)) {
- fillWork(work);
- } else {
- finish(outInfo.frameIndex, fillWork);
- }
-
- ALOGV("out timestamp %" PRIu64 " / %u", outInfo.timestamp, block ? block->capacity() : 0);
- mBuffersInfo.pop_front();
- }
-}
-
-void C2SoftAac::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->workletsProcessed = 0u;
- work->result = C2_OK;
- if (mSignalledError) {
- return;
- }
-
- UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
- UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
- UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
-
- INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
- C2ReadView view = work->input.buffers[0]->data().linearBlocks().front().map().get();
- size_t offset = 0u;
- size_t size = view.capacity();
-
- bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
- bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
-
- //TODO
-#if 0
- if (mInputBufferCount == 0 && !codecConfig) {
- ALOGW("first buffer should have FLAG_CODEC_CONFIG set");
- codecConfig = true;
- }
-#endif
- if (codecConfig) {
- // const_cast because of libAACdec method signature.
- inBuffer[0] = const_cast<UCHAR *>(view.data() + offset);
- inBufferLength[0] = size;
-
- AAC_DECODER_ERROR decoderErr =
- aacDecoder_ConfigRaw(mAACDecoder,
- inBuffer,
- inBufferLength);
-
- if (decoderErr != AAC_DEC_OK) {
- ALOGE("aacDecoder_ConfigRaw decoderErr = 0x%4.4x", decoderErr);
- mSignalledError = true;
- // TODO: error
- return;
- }
-
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets.front()->output.buffers.clear();
-
- return;
- }
-
- Info inInfo;
- inInfo.frameIndex = work->input.ordinal.frameIndex.peeku();
- inInfo.timestamp = work->input.ordinal.timestamp.peeku();
- inInfo.bufferSize = size;
- inInfo.decodedSizes.clear();
- while (size > 0u) {
- ALOGV("size = %zu", size);
- if (mIsADTS) {
- size_t adtsHeaderSize = 0;
- // skip 30 bits, aac_frame_length follows.
- // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
-
- const uint8_t *adtsHeader = view.data() + offset;
-
- bool signalError = false;
- if (size < 7) {
- ALOGE("Audio data too short to contain even the ADTS header. "
- "Got %zu bytes.", size);
- hexdump(adtsHeader, size);
- signalError = true;
- } else {
- bool protectionAbsent = (adtsHeader[1] & 1);
-
- unsigned aac_frame_length =
- ((adtsHeader[3] & 3) << 11)
- | (adtsHeader[4] << 3)
- | (adtsHeader[5] >> 5);
-
- if (size < aac_frame_length) {
- ALOGE("Not enough audio data for the complete frame. "
- "Got %zu bytes, frame size according to the ADTS "
- "header is %u bytes.",
- size, aac_frame_length);
- hexdump(adtsHeader, size);
- signalError = true;
- } else {
- adtsHeaderSize = (protectionAbsent ? 7 : 9);
- if (aac_frame_length < adtsHeaderSize) {
- signalError = true;
- } else {
- // const_cast because of libAACdec method signature.
- inBuffer[0] = const_cast<UCHAR *>(adtsHeader + adtsHeaderSize);
- inBufferLength[0] = aac_frame_length - adtsHeaderSize;
-
- offset += adtsHeaderSize;
- size -= adtsHeaderSize;
- }
- }
- }
-
- if (signalError) {
- mSignalledError = true;
- // TODO: notify(OMX_EventError, OMX_ErrorStreamCorrupt, ERROR_MALFORMED, NULL);
- return;
- }
- } else {
- // const_cast because of libAACdec method signature.
- inBuffer[0] = const_cast<UCHAR *>(view.data() + offset);
- inBufferLength[0] = size;
- }
-
- // Fill and decode
- bytesValid[0] = inBufferLength[0];
-
- INT prevSampleRate = mStreamInfo->sampleRate;
- INT prevNumChannels = mStreamInfo->numChannels;
-
- aacDecoder_Fill(mAACDecoder,
- inBuffer,
- inBufferLength,
- bytesValid);
-
- // run DRC check
- mDrcWrap.submitStreamData(mStreamInfo);
- mDrcWrap.update();
-
- UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
- size -= inBufferUsedLength;
- offset += inBufferUsedLength;
-
- AAC_DECODER_ERROR decoderErr;
- do {
- if (outputDelayRingBufferSpaceLeft() <
- (mStreamInfo->frameSize * mStreamInfo->numChannels)) {
- ALOGV("skipping decode: not enough space left in ringbuffer");
- break;
- }
-
- int numConsumed = mStreamInfo->numTotalBytes;
- decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
- tmpOutBuffer,
- 2048 * MAX_CHANNEL_COUNT,
- 0 /* flags */);
-
- numConsumed = mStreamInfo->numTotalBytes - numConsumed;
-
- if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
- break;
- }
- inInfo.decodedSizes.push_back(numConsumed);
-
- if (decoderErr != AAC_DEC_OK) {
- ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
- }
-
- if (bytesValid[0] != 0) {
- ALOGE("bytesValid[0] != 0 should never happen");
- mSignalledError = true;
- // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- return;
- }
-
- size_t numOutBytes =
- mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
-
- if (decoderErr == AAC_DEC_OK) {
- if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
- mStreamInfo->frameSize * mStreamInfo->numChannels)) {
- mSignalledError = true;
- // TODO: notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- return;
- }
- } else {
- ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr);
-
- memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow
-
- if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
- mStreamInfo->frameSize * mStreamInfo->numChannels)) {
- mSignalledError = true;
- // TODO: notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- return;
- }
-
- // Discard input buffer.
- size = 0;
-
- aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
-
- // After an error, replace bufferSize with the sum of the
- // decodedSizes to resynchronize the in/out lists.
- inInfo.decodedSizes.pop_back();
- inInfo.bufferSize = std::accumulate(
- inInfo.decodedSizes.begin(), inInfo.decodedSizes.end(), 0);
-
- // fall through
- }
-
- /*
- * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
- * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
- * rate system and the sampling rate in the final output is actually
- * doubled compared with the core AAC decoder sampling rate.
- *
- * Explicit signalling is done by explicitly defining SBR audio object
- * type in the bitstream. Implicit signalling is done by embedding
- * SBR content in AAC extension payload specific to SBR, and hence
- * requires an AAC decoder to perform pre-checks on actual audio frames.
- *
- * Thus, we could not say for sure whether a stream is
- * AAC+/eAAC+ until the first data frame is decoded.
- */
- if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
- // TODO:
-#if 0
- if ((mInputBufferCount > 2) && (mOutputBufferCount <= 1)) {
- ALOGW("Invalid AAC stream");
- mSignalledError = true;
- // TODO: notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- return false;
- }
-#endif
- }
- ALOGV("size = %zu", size);
- } while (decoderErr == AAC_DEC_OK);
- }
-
- int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
-
- mBuffersInfo.push_back(std::move(inInfo));
-
- if (!eos && mOutputDelayCompensated < outputDelay) {
- // discard outputDelay at the beginning
- int32_t toCompensate = outputDelay - mOutputDelayCompensated;
- int32_t discard = outputDelayRingBufferSamplesAvailable();
- if (discard > toCompensate) {
- discard = toCompensate;
- }
- int32_t discarded = outputDelayRingBufferGetSamples(0, discard);
- mOutputDelayCompensated += discarded;
- return;
- }
-
- if (eos) {
- drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
- } else {
- drainRingBuffer(work, pool, false /* not EOS */);
- }
-}
-
-c2_status_t C2SoftAac::drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work) {
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- bool eos = (drainMode == DRAIN_COMPONENT_WITH_EOS);
-
- drainDecoder();
- drainRingBuffer(work, pool, eos);
-
- if (eos) {
- auto fillEmptyWork = [](const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
- while (mBuffersInfo.size() > 1u) {
- finish(mBuffersInfo.front().frameIndex, fillEmptyWork);
- mBuffersInfo.pop_front();
- }
- if (work->workletsProcessed == 0u) {
- fillEmptyWork(work);
- }
- mBuffersInfo.clear();
- }
-
- return C2_OK;
-}
-
-c2_status_t C2SoftAac::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- return drainInternal(drainMode, pool, nullptr);
-}
-
-c2_status_t C2SoftAac::onFlush_sm() {
- drainDecoder();
- mBuffersInfo.clear();
-
- int avail;
- while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) {
- if (avail > mStreamInfo->frameSize * mStreamInfo->numChannels) {
- avail = mStreamInfo->frameSize * mStreamInfo->numChannels;
- }
- int32_t ns = outputDelayRingBufferGetSamples(0, avail);
- if (ns != avail) {
- ALOGW("not a complete frame of samples available");
- break;
- }
- }
- mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos;
-
- return C2_OK;
-}
-
-void C2SoftAac::drainDecoder() {
- // flush decoder until outputDelay is compensated
- while (mOutputDelayCompensated > 0) {
- // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
- INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
-
- // run DRC check
- mDrcWrap.submitStreamData(mStreamInfo);
- mDrcWrap.update();
-
- AAC_DECODER_ERROR decoderErr =
- aacDecoder_DecodeFrame(mAACDecoder,
- tmpOutBuffer,
- 2048 * MAX_CHANNEL_COUNT,
- AACDEC_FLUSH);
- if (decoderErr != AAC_DEC_OK) {
- ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
- }
-
- int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels;
- if (tmpOutBufferSamples > mOutputDelayCompensated) {
- tmpOutBufferSamples = mOutputDelayCompensated;
- }
- outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples);
-
- mOutputDelayCompensated -= tmpOutBufferSamples;
- }
-}
-
-class C2SoftAacDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAac(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftAacDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftAacDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/aacdec/C2SoftAac.h b/media/libstagefright/codecs/aacdec/C2SoftAac.h
deleted file mode 100644
index b877635..0000000
--- a/media/libstagefright/codecs/aacdec/C2SoftAac.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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 C2_SOFT_AAC_H_
-#define C2_SOFT_AAC_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-#include "aacdecoder_lib.h"
-#include "DrcPresModeWrap.h"
-
-namespace android {
-
-struct C2SoftAac : public SimpleC2Component {
- C2SoftAac(const char *name, c2_node_id_t id);
- virtual ~C2SoftAac();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- enum {
- kNumDelayBlocksMax = 8,
- };
-
- HANDLE_AACDECODER mAACDecoder;
- CStreamInfo *mStreamInfo;
- bool mIsADTS;
- bool mIsFirst;
- size_t mInputBufferCount;
- size_t mOutputBufferCount;
- bool mSignalledError;
- struct Info {
- uint64_t frameIndex;
- size_t bufferSize;
- uint64_t timestamp;
- std::vector<int32_t> decodedSizes;
- };
- std::list<Info> mBuffersInfo;
-
- CDrcPresModeWrapper mDrcWrap;
-
- enum {
- NONE,
- AWAITING_DISABLED,
- AWAITING_ENABLED
- } mOutputPortSettingsChange;
-
- void initPorts();
- status_t initDecoder();
- bool isConfigured() const;
- void drainDecoder();
-
- void drainRingBuffer(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool,
- bool eos);
- c2_status_t drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work);
-
-// delay compensation
- bool mEndOfInput;
- bool mEndOfOutput;
- int32_t mOutputDelayCompensated;
- int32_t mOutputDelayRingBufferSize;
- short *mOutputDelayRingBuffer;
- int32_t mOutputDelayRingBufferWritePos;
- int32_t mOutputDelayRingBufferReadPos;
- int32_t mOutputDelayRingBufferFilled;
- bool outputDelayRingBufferPutSamples(INT_PCM *samples, int numSamples);
- int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
- int32_t outputDelayRingBufferSamplesAvailable();
- int32_t outputDelayRingBufferSpaceLeft();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftAac);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_AAC_H_
diff --git a/media/libstagefright/codecs/aacenc/Android.bp b/media/libstagefright/codecs/aacenc/Android.bp
index 9386c6e..9342351 100644
--- a/media/libstagefright/codecs/aacenc/Android.bp
+++ b/media/libstagefright/codecs/aacenc/Android.bp
@@ -1,42 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2aacenc",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftAacEnc.cpp"],
-
- cflags: ["-Werror"],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libFraunhoferAAC",
- ],
-
- shared_libs: [
- "libcutils",
- "libion",
- "liblog",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libutils",
- ],
-}
-
-cc_library_shared {
name: "libstagefright_soft_aacenc",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
deleted file mode 100644
index 70f6817..0000000
--- a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_NDEBUG 0
-#define LOG_TAG "C2SoftAacEnc"
-#include <utils/Log.h>
-
-#include <inttypes.h>
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-#include <media/stagefright/foundation/hexdump.h>
-
-#include "C2SoftAacEnc.h"
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.aac.encoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftAacEnc::C2SoftAacEnc(
- const char *name,
- c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mAACEncoder(NULL),
- mNumChannels(1),
- mSampleRate(44100),
- mBitRate(64000),
- mSBRMode(-1),
- mSBRRatio(0),
- mAACProfile(AOT_AAC_LC),
- mNumBytesPerInputFrame(0u),
- mOutBufferSize(0u),
- mSentCodecSpecificData(false),
- mInputSize(0),
- mInputTimeUs(-1ll),
- mSignalledError(false) {
-}
-
-C2SoftAacEnc::~C2SoftAacEnc() {
- onReset();
-}
-
-c2_status_t C2SoftAacEnc::onInit() {
- status_t err = initEncoder();
- return err == OK ? C2_OK : C2_CORRUPTED;
-}
-
-status_t C2SoftAacEnc::initEncoder() {
- if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
- ALOGE("Failed to init AAC encoder");
- return UNKNOWN_ERROR;
- }
- return setAudioParams();
-}
-
-c2_status_t C2SoftAacEnc::onStop() {
- mSentCodecSpecificData = false;
- mInputSize = 0u;
- mInputTimeUs = -1ll;
- mSignalledError = false;
- return C2_OK;
-}
-
-void C2SoftAacEnc::onReset() {
- (void)onStop();
- aacEncClose(&mAACEncoder);
-}
-
-void C2SoftAacEnc::onRelease() {
- // no-op
-}
-
-c2_status_t C2SoftAacEnc::onFlush_sm() {
- mSentCodecSpecificData = false;
- mInputSize = 0u;
- return C2_OK;
-}
-
-static CHANNEL_MODE getChannelMode(uint32_t nChannels) {
- CHANNEL_MODE chMode = MODE_INVALID;
- switch (nChannels) {
- case 1: chMode = MODE_1; break;
- case 2: chMode = MODE_2; break;
- case 3: chMode = MODE_1_2; break;
- case 4: chMode = MODE_1_2_1; break;
- case 5: chMode = MODE_1_2_2; break;
- case 6: chMode = MODE_1_2_2_1; break;
- default: chMode = MODE_INVALID;
- }
- return chMode;
-}
-
-//static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
-// if (profile == OMX_AUDIO_AACObjectLC) {
-// return AOT_AAC_LC;
-// } else if (profile == OMX_AUDIO_AACObjectHE) {
-// return AOT_SBR;
-// } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
-// return AOT_PS;
-// } else if (profile == OMX_AUDIO_AACObjectLD) {
-// return AOT_ER_AAC_LD;
-// } else if (profile == OMX_AUDIO_AACObjectELD) {
-// return AOT_ER_AAC_ELD;
-// } else {
-// ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
-// return AOT_AAC_LC;
-// }
-//}
-
-status_t C2SoftAacEnc::setAudioParams() {
- // We call this whenever sample rate, number of channels, bitrate or SBR mode change
- // in reponse to setParameter calls.
-
- ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
- mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio);
-
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
- ALOGE("Failed to set AAC encoder parameters");
- return UNKNOWN_ERROR;
- }
-
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
- ALOGE("Failed to set AAC encoder parameters");
- return UNKNOWN_ERROR;
- }
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
- ALOGE("Failed to set AAC encoder parameters");
- return UNKNOWN_ERROR;
- }
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
- getChannelMode(mNumChannels))) {
- ALOGE("Failed to set AAC encoder parameters");
- return UNKNOWN_ERROR;
- }
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
- ALOGE("Failed to set AAC encoder parameters");
- return UNKNOWN_ERROR;
- }
-
- if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
- ALOGE("Failed to set AAC encoder parameters");
- return UNKNOWN_ERROR;
- }
- }
-
- /* SBR ratio parameter configurations:
- 0: Default configuration wherein SBR ratio is configured depending on audio object type by
- the FDK.
- 1: Downsampled SBR (default for ELD)
- 2: Dualrate SBR (default for HE-AAC)
- */
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
- ALOGE("Failed to set AAC encoder parameters");
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-void C2SoftAacEnc::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
-
- if (mSignalledError) {
- return;
- }
- bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
-
- if (!mSentCodecSpecificData) {
- // The very first thing we want to output is the codec specific
- // data.
-
- if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
- ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
- // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- mSignalledError = true;
- return;
- }
-
- uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
- if (mBitRate != actualBitRate) {
- ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
- }
-
- AACENC_InfoStruct encInfo;
- if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
- ALOGE("Failed to get AAC encoder info");
- // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- mSignalledError = true;
- return;
- }
-
- std::unique_ptr<C2StreamCsdInfo::output> csd =
- C2StreamCsdInfo::output::AllocUnique(encInfo.confSize, 0u);
- // TODO: check NO_MEMORY
- memcpy(csd->m.value, encInfo.confBuf, encInfo.confSize);
- ALOGV("put csd");
-#if defined(LOG_NDEBUG) && !LOG_NDEBUG
- hexdump(csd->m.value, csd->flexCount());
-#endif
- work->worklets.front()->output.configUpdate.push_back(std::move(csd));
-
- mOutBufferSize = encInfo.maxOutBufBytes;
- mNumBytesPerInputFrame = encInfo.frameLength * mNumChannels * sizeof(int16_t);
- mInputTimeUs = work->input.ordinal.timestamp;
-
- mSentCodecSpecificData = true;
- }
-
- C2ReadView view = work->input.buffers[0]->data().linearBlocks().front().map().get();
- uint64_t timestamp = mInputTimeUs.peeku();
-
- size_t numFrames = (view.capacity() + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
- / mNumBytesPerInputFrame;
- ALOGV("capacity = %u; mInputSize = %zu; numFrames = %zu", view.capacity(), mInputSize, numFrames);
-
- std::shared_ptr<C2LinearBlock> block;
- std::unique_ptr<C2WriteView> wView;
- uint8_t *outPtr = nullptr;
- size_t outAvailable = 0u;
-
- if (numFrames) {
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- // TODO: error handling, proper usage, etc.
- c2_status_t err = pool->fetchLinearBlock(mOutBufferSize * numFrames, usage, &block);
- if (err != C2_OK) {
- ALOGE("err = %d", err);
- }
-
- wView.reset(new C2WriteView(block->map().get()));
- outPtr = wView->data();
- outAvailable = wView->size();
- }
-
- AACENC_InArgs inargs;
- AACENC_OutArgs outargs;
- memset(&inargs, 0, sizeof(inargs));
- memset(&outargs, 0, sizeof(outargs));
- inargs.numInSamples = view.capacity() / sizeof(int16_t);
-
- void* inBuffer[] = { (unsigned char *)view.data() };
- INT inBufferIds[] = { IN_AUDIO_DATA };
- INT inBufferSize[] = { (INT)view.capacity() };
- INT inBufferElSize[] = { sizeof(int16_t) };
-
- AACENC_BufDesc inBufDesc;
- inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*);
- inBufDesc.bufs = (void**)&inBuffer;
- inBufDesc.bufferIdentifiers = inBufferIds;
- inBufDesc.bufSizes = inBufferSize;
- inBufDesc.bufElSizes = inBufferElSize;
-
- void* outBuffer[] = { outPtr };
- INT outBufferIds[] = { OUT_BITSTREAM_DATA };
- INT outBufferSize[] = { 0 };
- INT outBufferElSize[] = { sizeof(UCHAR) };
-
- AACENC_BufDesc outBufDesc;
- outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*);
- outBufDesc.bufs = (void**)&outBuffer;
- outBufDesc.bufferIdentifiers = outBufferIds;
- outBufDesc.bufSizes = outBufferSize;
- outBufDesc.bufElSizes = outBufferElSize;
-
- // Encode the mInputFrame, which is treated as a modulo buffer
- AACENC_ERROR encoderErr = AACENC_OK;
- size_t nOutputBytes = 0;
-
- while (encoderErr == AACENC_OK && inargs.numInSamples > 0) {
- memset(&outargs, 0, sizeof(outargs));
-
- outBuffer[0] = outPtr;
- outBufferSize[0] = outAvailable - nOutputBytes;
-
- encoderErr = aacEncEncode(mAACEncoder,
- &inBufDesc,
- &outBufDesc,
- &inargs,
- &outargs);
-
- if (encoderErr == AACENC_OK) {
- if (outargs.numOutBytes > 0) {
- mInputSize = 0;
- int consumed = ((view.capacity() / sizeof(int16_t)) - inargs.numInSamples);
- mInputTimeUs = work->input.ordinal.timestamp
- + (consumed * 1000000ll / mNumChannels / mSampleRate);
- } else {
- mInputSize += outargs.numInSamples * sizeof(int16_t);
- mInputTimeUs += outargs.numInSamples * 1000000ll / mNumChannels / mSampleRate;
- }
- outPtr += outargs.numOutBytes;
- nOutputBytes += outargs.numOutBytes;
-
- if (outargs.numInSamples > 0) {
- inBuffer[0] = (int16_t *)inBuffer[0] + outargs.numInSamples;
- inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t);
- inargs.numInSamples -= outargs.numInSamples;
- }
- }
- ALOGV("nOutputBytes = %zu; inargs.numInSamples = %d", nOutputBytes, inargs.numInSamples);
- }
-
- if (eos && inBufferSize[0] > 0) {
- memset(&outargs, 0, sizeof(outargs));
-
- outBuffer[0] = outPtr;
- outBufferSize[0] = outAvailable - nOutputBytes;
-
- // Flush
- inargs.numInSamples = -1;
-
- (void)aacEncEncode(mAACEncoder,
- &inBufDesc,
- &outBufDesc,
- &inargs,
- &outargs);
-
- nOutputBytes += outargs.numOutBytes;
- }
-
- work->worklets.front()->output.flags =
- (C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0);
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets.front()->output.ordinal.timestamp = timestamp;
- work->workletsProcessed = 1u;
- if (nOutputBytes) {
- work->worklets.front()->output.buffers.push_back(
- createLinearBuffer(block, 0, nOutputBytes));
- }
-
-#if 0
- ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
- nOutputBytes, mInputTimeUs.peekll(), outHeader->nFlags);
-
- hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
-#endif
-}
-
-c2_status_t C2SoftAacEnc::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- switch (drainMode) {
- case DRAIN_COMPONENT_NO_EOS: // fall-through
- case NO_DRAIN:
- // no-op
- return C2_OK;
- case DRAIN_CHAIN:
- return C2_OMITTED;
- case DRAIN_COMPONENT_WITH_EOS:
- break;
- default:
- return C2_BAD_VALUE;
- }
-
- (void)pool;
- mSentCodecSpecificData = false;
- mInputSize = 0u;
-
- // TODO: we don't have any pending work at this time to drain.
- return C2_OK;
-}
-
-class C2SoftAacEncFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAacEnc(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftAacEncFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftAacEncFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
deleted file mode 100644
index c9f440f..0000000
--- a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_AAC_ENC_H_
-
-#define C2_SOFT_AAC_ENC_H_
-
-#include <SimpleC2Component.h>
-#include <media/stagefright/foundation/ABase.h>
-
-#include "aacenc_lib.h"
-
-namespace android {
-
-class C2SoftAacEnc : public SimpleC2Component {
-public:
- C2SoftAacEnc(const char *name, c2_node_id_t id);
- virtual ~C2SoftAacEnc();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- HANDLE_AACENCODER mAACEncoder;
-
- uint32_t mNumChannels;
- uint32_t mSampleRate;
- uint32_t mBitRate;
- int32_t mSBRMode;
- int32_t mSBRRatio;
- AUDIO_OBJECT_TYPE mAACProfile;
- UINT mNumBytesPerInputFrame;
- UINT mOutBufferSize;
-
- bool mSentCodecSpecificData;
- size_t mInputSize;
- c2_cntr64_t mInputTimeUs;
-
- bool mSignalledError;
-
- status_t initEncoder();
-
- status_t setAudioParams();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftAacEnc);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_AAC_ENC_H_
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.bp b/media/libstagefright/codecs/amrnb/dec/Android.bp
index f97af89..880f161 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/Android.bp
@@ -41,7 +41,7 @@
],
include_dirs: ["frameworks/av/media/libstagefright/include"],
- local_include_dirs: ["src"],
+ export_include_dirs: ["src"],
cflags: [
"-DOSCL_UNUSED_ARG(x)=(void)(x)",
@@ -138,100 +138,3 @@
// ],
//},
}
-
-//###############################################################################
-cc_library_shared {
- name: "libstagefright_soft_c2amrnbdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftAMR.cpp",],
-
- include_dirs: [
- "frameworks/av/media/libstagefright/codecs/amrwb/src",
- ],
-
- local_include_dirs: ["src"],
-
- cflags: [
- "-Wall",
- "-Werror",
- "-DAMRNB",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libstagefright_amrnbdec",
- "libstagefright_amrwbdec",
- ],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libstagefright_amrnb_common",
- ],
-}
-
-//###############################################################################
-cc_library_shared {
- name: "libstagefright_soft_c2amrwbdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftAMR.cpp",],
-
- include_dirs: [
- "frameworks/av/media/libstagefright/codecs/amrwb/src",
- ],
-
- local_include_dirs: ["src"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libstagefright_amrnbdec",
- "libstagefright_amrwbdec",
- ],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libstagefright_amrnb_common",
- ],
-}
\ No newline at end of file
diff --git a/media/libstagefright/codecs/amrnb/dec/C2SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/C2SoftAMR.cpp
deleted file mode 100644
index 1d4928a..0000000
--- a/media/libstagefright/codecs/amrnb/dec/C2SoftAMR.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftAMR"
-#include <utils/Log.h>
-
-#include "C2SoftAMR.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-#include "gsmamr_dec.h"
-#include "pvamrwbdecoder.h"
-
-namespace android {
-
-#ifdef AMRNB
- constexpr char kComponentName[] = "c2.google.amrnb.decoder";
-#else
- constexpr char kComponentName[] = "c2.google.amrwb.decoder";
-#endif
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(
-#ifdef AMRNB
- MEDIA_MIMETYPE_AUDIO_AMR_NB
-#else
- MEDIA_MIMETYPE_AUDIO_AMR_WB
-#endif
- )
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftAMR::C2SoftAMR(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mAmrHandle(nullptr),
- mDecoderBuf(nullptr),
- mDecoderCookie(nullptr) {
-}
-
-C2SoftAMR::~C2SoftAMR() {
- (void)onRelease();
-}
-
-c2_status_t C2SoftAMR::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_NO_MEMORY;
-}
-
-c2_status_t C2SoftAMR::onStop() {
- if (!mIsWide) {
- Speech_Decode_Frame_reset(mAmrHandle);
- } else {
- pvDecoder_AmrWb_Reset(mAmrHandle, 0 /* reset_all */);
- }
- mSignalledError = false;
- mSignalledOutputEos = false;
-
- return C2_OK;
-}
-
-void C2SoftAMR::onReset() {
- (void)onStop();
-}
-
-void C2SoftAMR::onRelease() {
- if (!mIsWide) {
- GSMDecodeFrameExit(&mAmrHandle);
- mAmrHandle = nullptr;
- } else {
- free(mDecoderBuf);
- mDecoderBuf = nullptr;
-
- mAmrHandle = nullptr;
- mDecoderCookie = nullptr;
- }
-}
-
-c2_status_t C2SoftAMR::onFlush_sm() {
- return onStop();
-}
-
-status_t C2SoftAMR::initDecoder() {
-#ifdef AMRNB
- mIsWide = false;
-#else
- mIsWide = true;
-#endif
- if (!mIsWide) {
- if (GSMInitDecode(&mAmrHandle, (int8_t *)"AMRNBDecoder"))
- return UNKNOWN_ERROR;
- } else {
- uint32_t memReq = pvDecoder_AmrWbMemRequirements();
- mDecoderBuf = malloc(memReq);
- if (mDecoderBuf) {
- pvDecoder_AmrWb_Init(&mAmrHandle, mDecoderBuf, &mDecoderCookie);
- }
- else {
- return NO_MEMORY;
- }
- }
- mSignalledError = false;
- mSignalledOutputEos = false;
-
- return OK;
-}
-
-static size_t getFrameSize(bool isWide, unsigned FM) {
- static const size_t kFrameSizeNB[16] = {
- 12, 13, 15, 17, 19, 20, 26, 31,
- 5, 6, 5, 5, // SID
- 0, 0, 0, // future use
- 0 // no data
- };
- static const size_t kFrameSizeWB[16] = {
- 17, 23, 32, 36, 40, 46, 50, 58, 60,
- 5, // SID
- 0, 0, 0, 0, // future use
- 0, // speech lost
- 0 // no data
- };
-
- if (FM > 15 || (isWide && FM > 9 && FM < 14) || (!isWide && FM > 11 && FM < 15)) {
- ALOGE("illegal AMR frame mode %d", FM);
- return 0;
- }
- // add 1 for header byte
- return (isWide ? kFrameSizeWB[FM] : kFrameSizeNB[FM]) + 1;
-}
-
-static status_t calculateNumFrames(const uint8 *input, size_t inSize,
- std::vector<size_t> *frameSizeList, bool isWide) {
- for (size_t k = 0; k < inSize;) {
- int16_t FM = ((input[0] >> 3) & 0x0f);
- size_t frameSize = getFrameSize(isWide, FM);
- if (frameSize == 0) return UNKNOWN_ERROR;
- if ((inSize - k) >= frameSize) {
- input += frameSize;
- k += frameSize;
- }
- else break;
- frameSizeList->push_back(frameSize);
- }
- return OK;
-}
-
-void C2SoftAMR::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer =
- work->input.buffers[0]->data().linearBlocks().front();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
-
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = rView.error();
- return;
- }
- if (inSize == 0) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
-
- std::vector<size_t> frameSizeList;
- if (OK != calculateNumFrames(rView.data() + inOffset, inSize, &frameSizeList,
- mIsWide)) {
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
- if (frameSizeList.empty()) {
- ALOGE("input size smaller than expected");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
-
- int16_t outSamples = mIsWide ? kNumSamplesPerFrameWB : kNumSamplesPerFrameNB;
- size_t calOutSize = outSamples * frameSizeList.size() * sizeof(int16_t);
- std::shared_ptr<C2LinearBlock> block;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(calOutSize, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = wView.error();
- return;
- }
-
- int16_t *output = reinterpret_cast<int16_t *>(wView.data());
- auto it = frameSizeList.begin();
- const uint8_t *inPtr = rView.data() + inOffset;
- size_t inPos = 0;
- while (inPos < inSize) {
- if (it == frameSizeList.end()) {
- ALOGD("unexpected trailing bytes, ignoring them");
- break;
- }
- uint8_t *input = const_cast<uint8_t *>(inPtr + inPos);
- int16_t FM = ((*input >> 3) & 0x0f);
- if (!mIsWide) {
- int32_t numBytesRead = AMRDecode(mAmrHandle,
- (Frame_Type_3GPP) FM,
- input + 1, output, MIME_IETF);
- if (static_cast<size_t>(numBytesRead + 1) != *it) {
- ALOGE("panic, parsed size does not match decoded size");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
- } else {
- if (FM >= 9) {
- // Produce silence instead of comfort noise and for
- // speech lost/no data.
- memset(output, 0, outSamples * sizeof(int16_t));
- } else {
- int16_t FT;
- RX_State_wb rx_state;
- int16_t numRecSamples;
-
- mime_unsorting(const_cast<uint8_t *>(&input[1]),
- mInputSampleBuffer, &FT, &FM, 1, &rx_state);
- pvDecoder_AmrWb(FM, mInputSampleBuffer, output, &numRecSamples,
- mDecoderBuf, FT, mDecoderCookie);
- if (numRecSamples != outSamples) {
- ALOGE("Sample output per frame incorrect");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
- /* Delete the 2 LSBs (14-bit output) */
- for (int i = 0; i < numRecSamples; ++i) {
- output[i] &= 0xfffC;
- }
- }
- }
- inPos += *it;
- output += outSamples;
- ++it;
- }
-
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block));
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-c2_status_t C2SoftAMR::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
- return C2_OK;
-}
-
-class C2SoftAMRDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAMR(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftAMRDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftAMRDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/amrnb/dec/C2SoftAMR.h b/media/libstagefright/codecs/amrnb/dec/C2SoftAMR.h
deleted file mode 100644
index 69fe213..0000000
--- a/media/libstagefright/codecs/amrnb/dec/C2SoftAMR.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_AMR_H_
-#define C2_SOFT_AMR_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-
-struct C2SoftAMR : public SimpleC2Component {
- C2SoftAMR(const char *name, c2_node_id_t id);
- virtual ~C2SoftAMR();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-private:
- enum {
- kSampleRateNB = 8000,
- kSampleRateWB = 16000,
- kNumSamplesPerFrameNB = 160,
- kNumSamplesPerFrameWB = 320,
- };
-
- void *mAmrHandle;
- void *mDecoderBuf;
- int16_t *mDecoderCookie;
-
- int16_t mInputSampleBuffer[477];
-
- bool mIsWide;
- bool mSignalledError;
- bool mSignalledOutputEos;
-
- status_t initDecoder();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftAMR);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_AMR_H_
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.bp b/media/libstagefright/codecs/amrnb/enc/Android.bp
index 4001d46..19fd4a8 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/Android.bp
@@ -63,7 +63,7 @@
],
include_dirs: ["frameworks/av/media/libstagefright/include"],
- local_include_dirs: ["src"],
+ export_include_dirs: ["src"],
cflags: [
"-DOSCL_UNUSED_ARG(x)=(void)(x)",
@@ -122,50 +122,6 @@
//###############################################################################
-cc_library_shared {
- name: "libstagefright_soft_c2amrnbenc",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftAmrNbEnc.cpp"],
-
- local_include_dirs: ["src"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libstagefright_amrnbenc",
- ],
-
- shared_libs: [
- "libutils",
- "liblog",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libstagefright_amrnb_common",
- ],
-}
-
-//###############################################################################
-
cc_test {
name: "libstagefright_amrnbenc_test",
gtest: false,
diff --git a/media/libstagefright/codecs/amrnb/enc/C2SoftAmrNbEnc.cpp b/media/libstagefright/codecs/amrnb/enc/C2SoftAmrNbEnc.cpp
deleted file mode 100644
index 406d1ca..0000000
--- a/media/libstagefright/codecs/amrnb/enc/C2SoftAmrNbEnc.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftAmrNbEnc"
-#include <utils/Log.h>
-
-#include "gsmamr_enc.h"
-
-#include "C2SoftAmrNbEnc.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.amrnb.encoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_AMR_NB)
- .build();
-}
-
-C2SoftAmrNbEnc::C2SoftAmrNbEnc(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mEncState(nullptr),
- mSidState(nullptr) {
-}
-
-C2SoftAmrNbEnc::~C2SoftAmrNbEnc() {
- onRelease();
-}
-
-c2_status_t C2SoftAmrNbEnc::onInit() {
- bool dtx_enable = false;
-
- if (AMREncodeInit(&mEncState, &mSidState, dtx_enable) != 0)
- return C2_CORRUPTED;
- mMode = MR795;
- mIsFirst = true;
- mSignalledError = false;
- mSignalledOutputEos = false;
- mAnchorTimeStamp = 0;
- mProcessedSamples = 0;
- mFilledLen = 0;
-
- return C2_OK;
-}
-
-void C2SoftAmrNbEnc::onRelease() {
- if (mEncState) {
- AMREncodeExit(&mEncState, &mSidState);
- mEncState = mSidState = nullptr;
- }
-}
-
-c2_status_t C2SoftAmrNbEnc::onStop() {
- if (AMREncodeReset(mEncState, mSidState) != 0)
- return C2_CORRUPTED;
- mIsFirst = true;
- mSignalledError = false;
- mSignalledOutputEos = false;
- mAnchorTimeStamp = 0;
- mProcessedSamples = 0;
- mFilledLen = 0;
-
- return C2_OK;
-}
-
-void C2SoftAmrNbEnc::onReset() {
- (void) onStop();
-}
-
-c2_status_t C2SoftAmrNbEnc::onFlush_sm() {
- return onStop();
-}
-
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-void C2SoftAmrNbEnc::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
- inSize, (int)work->input.ordinal.timestamp.peeku(),
- (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
-
- size_t outCapacity = kNumBytesPerInputFrame;
- outCapacity += mFilledLen + inSize;
- std::shared_ptr<C2LinearBlock> outputBlock;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &outputBlock);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = outputBlock->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / kSampleRate;
- const uint8_t *inPtr = rView.data() + inOffset;
- size_t inPos = 0;
- size_t outPos = 0;
- while (inPos < inSize) {
- int validSamples = mFilledLen / sizeof(int16_t);
- if ((inPos + (kNumBytesPerInputFrame - mFilledLen)) <= inSize) {
- memcpy(mInputFrame + validSamples, inPtr + inPos,
- (kNumBytesPerInputFrame - mFilledLen));
- inPos += (kNumBytesPerInputFrame - mFilledLen);
- } else {
- memcpy(mInputFrame + validSamples, inPtr + inPos, (inSize - inPos));
- mFilledLen += (inSize - inPos);
- inPos += (inSize - inPos);
- if (eos) {
- validSamples = mFilledLen / sizeof(int16_t);
- memset(mInputFrame + validSamples, 0, (kNumBytesPerInputFrame - mFilledLen));
- } else break;
- }
- Frame_Type_3GPP frameType;
- int numEncBytes = AMREncode(mEncState, mSidState, mMode, mInputFrame,
- wView.data() + outPos, &frameType,
- AMR_TX_WMF);
- if (numEncBytes < 0 || numEncBytes > ((int)outCapacity - (int)outPos)) {
- ALOGE("encodeFrame call failed, state [%d %zu %zu]", numEncBytes, outPos, outCapacity);
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- // Convert header byte from WMF to IETF format.
- if (numEncBytes > 0)
- wView.data()[outPos] = ((wView.data()[outPos] << 3) | 4) & 0x7c;
- outPos += numEncBytes;
- mProcessedSamples += kNumSamplesPerFrame;
- mFilledLen = 0;
- }
- ALOGV("causal sample size %d", mFilledLen);
- if (mIsFirst) {
- mIsFirst = false;
- mAnchorTimeStamp = work->input.ordinal.timestamp.peekull();
- }
- fillEmptyWork(work);
- if (outPos != 0) {
- work->worklets.front()->output.buffers.push_back(
- createLinearBuffer(std::move(outputBlock), 0, outPos));
- work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
- }
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- if (mFilledLen) ALOGV("Discarding trailing %d bytes", mFilledLen);
- }
-}
-
-c2_status_t C2SoftAmrNbEnc::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- onFlush_sm();
- return C2_OK;
-}
-
-class C2SoftAmrNbEncFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAmrNbEnc(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftAmrNbEncFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftAmrNbEncFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/amrnb/enc/C2SoftAmrNbEnc.h b/media/libstagefright/codecs/amrnb/enc/C2SoftAmrNbEnc.h
deleted file mode 100644
index 9ced921..0000000
--- a/media/libstagefright/codecs/amrnb/enc/C2SoftAmrNbEnc.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_AMRNB_ENC_H_
-#define C2_SOFT_AMRNB_ENC_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-
-namespace android {
-
-class C2SoftAmrNbEnc : public SimpleC2Component {
-public:
- C2SoftAmrNbEnc(const char *name, c2_node_id_t id);
- virtual ~C2SoftAmrNbEnc();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- static const int32_t kNumSamplesPerFrame = L_FRAME;
- static const int32_t kNumBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
- static const int32_t kSampleRate = 8000;
-
- void *mEncState;
- void *mSidState;
- Mode mMode;
- bool mIsFirst;
- bool mSignalledError;
- bool mSignalledOutputEos;
- uint64_t mAnchorTimeStamp;
- uint64_t mProcessedSamples;
- int32_t mFilledLen;
- int16_t mInputFrame[kNumSamplesPerFrame];
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftAmrNbEnc);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_AMRNB_ENC_H_
diff --git a/media/libstagefright/codecs/amrwb/Android.bp b/media/libstagefright/codecs/amrwb/Android.bp
index 14a73d6..9fefd81 100644
--- a/media/libstagefright/codecs/amrwb/Android.bp
+++ b/media/libstagefright/codecs/amrwb/Android.bp
@@ -45,8 +45,11 @@
],
include_dirs: ["frameworks/av/media/libstagefright/include"],
- local_include_dirs: ["src"],
- export_include_dirs: ["include"],
+
+ export_include_dirs: [
+ "src",
+ "include",
+ ],
cflags: [
"-DOSCL_UNUSED_ARG(x)=(void)(x)",
diff --git a/media/libstagefright/codecs/amrwbenc/Android.bp b/media/libstagefright/codecs/amrwbenc/Android.bp
index 88e9206..ebe08c6 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/Android.bp
@@ -185,46 +185,4 @@
//###############################################################################
-cc_library_shared {
- name: "libstagefright_soft_c2amrwbenc",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftAmrWbEnc.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libstagefright_amrwbenc",
- ],
-
- shared_libs: [
- "libutils",
- "liblog",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libstagefright_enc_common",
- ],
-}
-
-//###############################################################################
-
subdirs = ["SampleCode"]
diff --git a/media/libstagefright/codecs/amrwbenc/C2SoftAmrWbEnc.cpp b/media/libstagefright/codecs/amrwbenc/C2SoftAmrWbEnc.cpp
deleted file mode 100644
index 2a831e5..0000000
--- a/media/libstagefright/codecs/amrwbenc/C2SoftAmrWbEnc.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftAmrWbEnc"
-#include <utils/Log.h>
-
-#include "C2SoftAmrWbEnc.h"
-
-#include "cmnMemory.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.amrwb.encoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_AMR_WB)
- .build();
-}
-
-C2SoftAmrWbEnc::C2SoftAmrWbEnc(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mEncoderHandle(nullptr),
- mApiHandle(nullptr),
- mMemOperator(nullptr) {
-}
-
-C2SoftAmrWbEnc::~C2SoftAmrWbEnc() {
- onRelease();
-}
-
-c2_status_t C2SoftAmrWbEnc::onInit() {
- status_t err = initEncoder();
- mMode = VOAMRWB_MD2305;
- mIsFirst = true;
- mSignalledError = false;
- mSignalledOutputEos = false;
- mAnchorTimeStamp = 0;
- mProcessedSamples = 0;
- mFilledLen = 0;
-
- return err == OK ? C2_OK : C2_NO_MEMORY;
-}
-
-void C2SoftAmrWbEnc::onRelease() {
- if (mEncoderHandle) {
- CHECK_EQ((VO_U32)VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
- mEncoderHandle = nullptr;
- }
- if (mApiHandle) {
- delete mApiHandle;
- mApiHandle = nullptr;
- }
- if (mMemOperator) {
- delete mMemOperator;
- mMemOperator = nullptr;
- }
-}
-
-c2_status_t C2SoftAmrWbEnc::onStop() {
- for (int i = 0; i < kNumSamplesPerFrame; i++) {
- mInputFrame[i] = 0x0008; /* EHF_MASK */
- }
- uint8_t outBuffer[kNumBytesPerInputFrame];
- (void) encodeInput(outBuffer, kNumBytesPerInputFrame);
- mIsFirst = true;
- mSignalledError = false;
- mSignalledOutputEos = false;
- mAnchorTimeStamp = 0;
- mProcessedSamples = 0;
- mFilledLen = 0;
-
- return C2_OK;
-}
-
-void C2SoftAmrWbEnc::onReset() {
- (void) onStop();
-}
-
-c2_status_t C2SoftAmrWbEnc::onFlush_sm() {
- return onStop();
-}
-
-status_t C2SoftAmrWbEnc::initEncoder() {
- mApiHandle = new VO_AUDIO_CODECAPI;
- if (!mApiHandle) return NO_MEMORY;
-
- if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
- ALOGE("Failed to get api handle");
- return UNKNOWN_ERROR;
- }
-
- mMemOperator = new VO_MEM_OPERATOR;
- if (!mMemOperator) return NO_MEMORY;
-
- mMemOperator->Alloc = cmnMemAlloc;
- mMemOperator->Copy = cmnMemCopy;
- mMemOperator->Free = cmnMemFree;
- mMemOperator->Set = cmnMemSet;
- mMemOperator->Check = cmnMemCheck;
-
- VO_CODEC_INIT_USERDATA userData;
- memset(&userData, 0, sizeof(userData));
- userData.memflag = VO_IMF_USERMEMOPERATOR;
- userData.memData = (VO_PTR) mMemOperator;
-
- if (VO_ERR_NONE != mApiHandle->Init(
- &mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) {
- ALOGE("Failed to init AMRWB encoder");
- return UNKNOWN_ERROR;
- }
-
- VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267;
- if (VO_ERR_NONE != mApiHandle->SetParam(
- mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) {
- ALOGE("Failed to set AMRWB encoder frame type to %d", type);
- return UNKNOWN_ERROR;
- }
-
- if (VO_ERR_NONE !=
- mApiHandle->SetParam(
- mEncoderHandle, VO_PID_AMRWB_MODE, &mMode)) {
- ALOGE("Failed to set AMRWB encoder mode to %d", mMode);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-int C2SoftAmrWbEnc::encodeInput(uint8_t *buffer, uint32_t length) {
- VO_CODECBUFFER inputData;
- memset(&inputData, 0, sizeof(inputData));
- inputData.Buffer = (unsigned char *) mInputFrame;
- inputData.Length = kNumBytesPerInputFrame;
-
- CHECK_EQ((VO_U32)VO_ERR_NONE,
- mApiHandle->SetInputData(mEncoderHandle, &inputData));
-
- VO_AUDIO_OUTPUTINFO outputInfo;
- memset(&outputInfo, 0, sizeof(outputInfo));
- VO_CODECBUFFER outputData;
- memset(&outputData, 0, sizeof(outputData));
- outputData.Buffer = buffer;
- outputData.Length = length;
- VO_U32 ret = mApiHandle->GetOutputData(
- mEncoderHandle, &outputData, &outputInfo);
- if (ret != VO_ERR_NONE && ret != VO_ERR_INPUT_BUFFER_SMALL) {
- ALOGD("encountered error during encode call");
- return -1;
- }
- return outputData.Length;
-}
-
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-void C2SoftAmrWbEnc::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = rView.error();
- return;
- }
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
- inSize, (int)work->input.ordinal.timestamp.peeku(),
- (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
-
- size_t outCapacity = kNumBytesPerInputFrame;
- outCapacity += mFilledLen + inSize;
- std::shared_ptr<C2LinearBlock> outputBlock;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &outputBlock);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = outputBlock->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = wView.error();
- return;
- }
-
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / kSampleRate;
- const uint8_t *inPtr = rView.data() + inOffset;
- size_t inPos = 0;
- size_t outPos = 0;
- while (inPos < inSize) {
- int validSamples = mFilledLen / sizeof(int16_t);
- if ((inPos + (kNumBytesPerInputFrame - mFilledLen)) <= inSize) {
- memcpy(mInputFrame + validSamples, inPtr + inPos,
- (kNumBytesPerInputFrame - mFilledLen));
- inPos += (kNumBytesPerInputFrame - mFilledLen);
- } else {
- memcpy(mInputFrame + validSamples, inPtr + inPos, (inSize - inPos));
- mFilledLen += (inSize - inPos);
- inPos += (inSize - inPos);
- if (eos) {
- validSamples = mFilledLen / sizeof(int16_t);
- memset(mInputFrame + validSamples, 0, (kNumBytesPerInputFrame - mFilledLen));
- } else break;
- }
- int numEncBytes = encodeInput((wView.data() + outPos), outCapacity - outPos);
- if (numEncBytes < 0) {
- ALOGE("encodeFrame call failed, state [%d %zu %zu]", numEncBytes, outPos, outCapacity);
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- outPos += numEncBytes;
- mProcessedSamples += kNumSamplesPerFrame;
- mFilledLen = 0;
- }
- ALOGV("causal sample size %d", mFilledLen);
- if (mIsFirst) {
- mIsFirst = false;
- mAnchorTimeStamp = work->input.ordinal.timestamp.peekull();
- }
- fillEmptyWork(work);
- if (outPos != 0) {
- work->worklets.front()->output.buffers.push_back(
- createLinearBuffer(std::move(outputBlock), 0, outPos));
- work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
- }
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- if (mFilledLen) ALOGV("Discarding trailing %d bytes", mFilledLen);
- }
-}
-
-c2_status_t C2SoftAmrWbEnc::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- onFlush_sm();
- return C2_OK;
-}
-
-class C2SoftAmrWbEncFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAmrWbEnc(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftAmrWbEncFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftAmrWbEncFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/amrwbenc/C2SoftAmrWbEnc.h b/media/libstagefright/codecs/amrwbenc/C2SoftAmrWbEnc.h
deleted file mode 100644
index 29e68ac..0000000
--- a/media/libstagefright/codecs/amrwbenc/C2SoftAmrWbEnc.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_AMRWB_ENC_H_
-#define C2_SOFT_AMRWB_ENC_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-
-#include "voAMRWB.h"
-
-namespace android {
-
-class C2SoftAmrWbEnc : public SimpleC2Component {
-public:
- C2SoftAmrWbEnc(const char *name, c2_node_id_t id);
- virtual ~C2SoftAmrWbEnc();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- static const int32_t kNumSamplesPerFrame = 320;
- static const int32_t kNumBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
- static const int32_t kSampleRate = 16000;
-
- void *mEncoderHandle;
- VO_AUDIO_CODECAPI *mApiHandle;
- VO_MEM_OPERATOR *mMemOperator;
- VOAMRWBMODE mMode;
- bool mIsFirst;
- bool mSignalledError;
- bool mSignalledOutputEos;
- uint64_t mAnchorTimeStamp;
- uint64_t mProcessedSamples;
- int32_t mFilledLen;
- int16_t mInputFrame[kNumSamplesPerFrame];
-
- status_t initEncoder();
- int encodeInput(uint8_t *buffer, uint32_t length);
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftAmrWbEnc);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_AMRWB_ENC_H_
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index d789096..cf50a04 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -42,44 +42,3 @@
ldflags: ["-Wl,-Bsymbolic"],
compile_multilib: "32",
}
-
-cc_library_shared {
- name: "libstagefright_soft_c2avcdec",
-
- static_libs: [
- "libavcdec",
- ],
- srcs: ["C2SoftAvcDec.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- include_dirs: [
- "external/libavc/decoder",
- "external/libavc/common",
- ],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libmedia",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: false, // true,
- diag: {
- cfi: false, // true,
- },
- },
-
- ldflags: ["-Wl,-Bsymbolic"],
-}
diff --git a/media/libstagefright/codecs/avcdec/C2AvcConfig.h b/media/libstagefright/codecs/avcdec/C2AvcConfig.h
deleted file mode 100644
index a7e0d95..0000000
--- a/media/libstagefright/codecs/avcdec/C2AvcConfig.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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 C2AVCCONFIG_H_
-#define C2AVCCONFIG_H_
-
-#include <C2Config.h>
-
-namespace android {
-
-enum : uint32_t {
- kParamIndexAvcProfile = kParamIndexParamStart + 1,
- kParamIndexAvcLevel,
- kParamIndexBlockSize,
- kParamIndexAlignment,
- kParamIndexFramerate,
- kParamIndexBlocksPerSecond,
-};
-
-enum C2AvcProfileIdc : uint32_t {
- kAvcProfileUnknown = 0,
- kAvcProfileBaseline = 66,
- kAvcProfileMain = 77,
- kAvcProfileExtended = 88,
- kAvcProfileHigh = 100,
- kAvcProfileHigh10 = 110,
- kAvcProfileHigh422 = 122,
- kAvcProfileHigh444 = 144,
-};
-
-enum C2AvcLevelIdc : uint32_t {
- kAvcLevelUnknown = 0,
- kAvcLevel10 = 10,
- kAvcLevel1b = 9,
- kAvcLevel11 = 11,
- kAvcLevel12 = 12,
- kAvcLevel13 = 13,
- kAvcLevel20 = 20,
- kAvcLevel21 = 21,
- kAvcLevel22 = 22,
- kAvcLevel30 = 30,
- kAvcLevel31 = 31,
- kAvcLevel32 = 32,
- kAvcLevel40 = 40,
- kAvcLevel41 = 41,
- kAvcLevel42 = 42,
- kAvcLevel50 = 50,
- kAvcLevel51 = 51,
- kAvcLevel52 = 52,
-};
-
-// profile for AVC video decoder [IN]
-typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2AvcProfileIdc>, kParamIndexAvcProfile>
- C2AvcProfileInfo;
-
-// level for AVC video decoder [IN]
-typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2AvcLevelIdc>, kParamIndexAvcLevel>
- C2AvcLevelInfo;
-
-// block size [OUT]
-typedef C2StreamParam<C2Info, C2VideoSizeStruct, kParamIndexBlockSize> C2BlockSizeInfo;
-
-// alignment [OUT]
-typedef C2StreamParam<C2Info, C2VideoSizeStruct, kParamIndexAlignment> C2AlignmentInfo;
-
-// frame rate [OUT, hint]
-typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexFramerate> C2FrameRateInfo;
-
-// blocks-per-second [OUT, hint]
-typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexBlocksPerSecond> C2BlocksPerSecondInfo;
-
-} // namespace android
-
-#endif // C2AVCCONFIG_H_
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
deleted file mode 100644
index 1fc2c8c..0000000
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_NDEBUG 0
-#define LOG_TAG "C2SoftAvcDec"
-#include <utils/Log.h>
-
-#include <cmath>
-#include <thread>
-#include <cinttypes>
-
-#include "ih264_typedefs.h"
-#include "iv.h"
-#include "ivd.h"
-#include "ih264d.h"
-#include "C2SoftAvcDec.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <utils/misc.h>
-
-#include "ih264d_defs.h"
-
-namespace android {
-
-struct iv_obj_t : public ::iv_obj_t {};
-struct ivd_video_decode_ip_t : public ::ivd_video_decode_ip_t {};
-struct ivd_video_decode_op_t : public ::ivd_video_decode_op_t {};
-
-#define PRINT_TIME ALOGV
-
-constexpr char kComponentName[] = "c2.google.avc.decoder";
-// #define codingType OMX_VIDEO_CodingAVC
-#define CODEC_MIME_TYPE MEDIA_MIMETYPE_VIDEO_AVC
-
-/** Function and structure definitions to keep code similar for each codec */
-#define ivdec_api_function ih264d_api_function
-#define ivdext_create_ip_t ih264d_create_ip_t
-#define ivdext_create_op_t ih264d_create_op_t
-#define ivdext_delete_ip_t ih264d_delete_ip_t
-#define ivdext_delete_op_t ih264d_delete_op_t
-#define ivdext_ctl_set_num_cores_ip_t ih264d_ctl_set_num_cores_ip_t
-#define ivdext_ctl_set_num_cores_op_t ih264d_ctl_set_num_cores_op_t
-
-#define IVDEXT_CMD_CTL_SET_NUM_CORES \
- (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
-namespace {
-
-std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .inputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
- .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
- .build();
-}
-
-void CopyPlane(
- uint8_t *dst, const C2PlaneInfo &plane,
- const uint8_t *src, uint32_t width, uint32_t height) {
- for (uint32_t row = 0; row < height; ++row) {
- for (uint32_t col = 0; col < width; ++col) {
- *dst = *src;
- dst += plane.colInc;
- ++src;
- }
- dst -= plane.colInc * width;
- dst += plane.rowInc;
- }
-}
-
-void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM)) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-} // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-
-C2SoftAvcDec::C2SoftAvcDec(
- const char *name,
- c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mCodecCtx(NULL),
- mOutBuffer(NULL),
- mIvColorFormat(IV_YUV_420P),
- mChangingResolution(false),
- mSignalledError(false),
- mWidth(320),
- mHeight(240),
- mInputOffset(0) {
- ALOGV("in %s", __func__);
- GETTIME(&mTimeStart, NULL);
-
- // If input dump is enabled, then open create an empty file
- GENERATE_FILE_NAMES();
- CREATE_DUMP_FILE(mInFile);
-}
-
-C2SoftAvcDec::~C2SoftAvcDec() {
- ALOGV("in %s", __func__);
- CHECK_EQ(deInitDecoder(), (status_t)OK);
-}
-
-c2_status_t C2SoftAvcDec::onInit() {
- // TODO: initialize using intf
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcDec::onStop() {
- ALOGV("onStop");
- mSignalledError = false;
- resetDecoder();
- resetPlugin();
-
- return C2_OK;
-}
-
-void C2SoftAvcDec::onReset() {
- ALOGV("onReset");
- (void)onStop();
-}
-
-void C2SoftAvcDec::onRelease() {
- (void)deInitDecoder();
-}
-
-c2_status_t C2SoftAvcDec::onFlush_sm() {
- setFlushMode();
-
- while (true) {
- ivd_video_decode_ip_t s_dec_ip;
- ivd_video_decode_op_t s_dec_op;
- IV_API_CALL_STATUS_T status;
- // size_t sizeY, sizeUV;
-
- setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, 0, 0u);
-
- status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
- if (0 == s_dec_op.u4_output_present) {
- resetPlugin();
- break;
- }
- }
-
- if (mOutBuffer) {
- free(mOutBuffer);
- mOutBuffer = NULL;
- }
- return C2_OK;
-}
-
-static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
- (void) ctxt;
- return memalign(alignment, size);
-}
-
-static void ivd_aligned_free(void *ctxt, void *buf) {
- (void) ctxt;
- free(buf);
- return;
-}
-
-static size_t GetCPUCoreCount() {
- long cpuCoreCount = 1;
-#if defined(_SC_NPROCESSORS_ONLN)
- cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
-#else
- // _SC_NPROC_ONLN must be defined...
- cpuCoreCount = sysconf(_SC_NPROC_ONLN);
-#endif
- CHECK(cpuCoreCount >= 1);
- ALOGV("Number of CPU cores: %ld", cpuCoreCount);
- return (size_t)cpuCoreCount;
-}
-
-void C2SoftAvcDec::logVersion() {
- ivd_ctl_getversioninfo_ip_t s_ctl_ip;
- ivd_ctl_getversioninfo_op_t s_ctl_op;
- UWORD8 au1_buf[512];
- IV_API_CALL_STATUS_T status;
-
- s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION;
- s_ctl_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t);
- s_ctl_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t);
- s_ctl_ip.pv_version_buffer = au1_buf;
- s_ctl_ip.u4_version_buffer_size = sizeof(au1_buf);
-
- status =
- ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Error in getting version number: 0x%x",
- s_ctl_op.u4_error_code);
- } else {
- ALOGV("Ittiam decoder version number: %s",
- (char *)s_ctl_ip.pv_version_buffer);
- }
- return;
-}
-
-status_t C2SoftAvcDec::setParams(size_t stride) {
- ivd_ctl_set_config_ip_t s_ctl_ip;
- ivd_ctl_set_config_op_t s_ctl_op;
- IV_API_CALL_STATUS_T status;
- s_ctl_ip.u4_disp_wd = (UWORD32)stride;
- s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;
-
- s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
- s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME;
- s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
- s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
- s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
-
- ALOGV("Set the run-time (dynamic) parameters stride = %zu", stride);
- status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Error in setting the run-time parameters: 0x%x",
- s_ctl_op.u4_error_code);
-
- return UNKNOWN_ERROR;
- }
-
- if (mOutBuffer != NULL) {
- free(mOutBuffer);
- }
- uint32_t bufferSize = mWidth * mHeight * 3 / 2;
- mOutBuffer = (uint8_t *)memalign(128, bufferSize);
- if (NULL == mOutBuffer) {
- ALOGE("Could not allocate output buffer of size %u", bufferSize);
- return C2_NO_MEMORY;
- }
- return OK;
-}
-
-status_t C2SoftAvcDec::resetPlugin() {
- mInputOffset = 0;
-
- /* Initialize both start and end times */
- gettimeofday(&mTimeStart, NULL);
- gettimeofday(&mTimeEnd, NULL);
-
- return OK;
-}
-
-status_t C2SoftAvcDec::resetDecoder() {
- ivd_ctl_reset_ip_t s_ctl_ip;
- ivd_ctl_reset_op_t s_ctl_op;
- IV_API_CALL_STATUS_T status;
-
- s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
- s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
- s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t);
-
- status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op);
- if (IV_SUCCESS != status) {
- ALOGE("Error in reset: 0x%x", s_ctl_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
- mSignalledError = false;
-
- /* Set number of cores/threads to be used by the codec */
- setNumCores();
-
- mStride = 0;
- return OK;
-}
-
-status_t C2SoftAvcDec::setNumCores() {
- ivdext_ctl_set_num_cores_ip_t s_set_cores_ip;
- ivdext_ctl_set_num_cores_op_t s_set_cores_op;
- IV_API_CALL_STATUS_T status;
- s_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES;
- s_set_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_NUM_CORES);
- s_set_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
- s_set_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t);
- status = ivdec_api_function(
- mCodecCtx, (void *)&s_set_cores_ip, (void *)&s_set_cores_op);
- if (IV_SUCCESS != status) {
- ALOGE("Error in setting number of cores: 0x%x",
- s_set_cores_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
- return OK;
-}
-
-status_t C2SoftAvcDec::setFlushMode() {
- ALOGV("setFlushMode");
- IV_API_CALL_STATUS_T status;
- ivd_ctl_flush_ip_t s_video_flush_ip;
- ivd_ctl_flush_op_t s_video_flush_op;
-
- s_video_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_video_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH;
- s_video_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
- s_video_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t);
-
- /* Set the decoder in Flush mode, subsequent decode() calls will flush */
- status = ivdec_api_function(
- mCodecCtx, (void *)&s_video_flush_ip, (void *)&s_video_flush_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Error in setting the decoder in flush mode: (%d) 0x%x", status,
- s_video_flush_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftAvcDec::initDecoder() {
- IV_API_CALL_STATUS_T status;
-
- mNumCores = GetCPUCoreCount();
- mCodecCtx = NULL;
-
- mStride = mWidth;
-
- /* Initialize the decoder */
- {
- ivdext_create_ip_t s_create_ip;
- ivdext_create_op_t s_create_op;
-
- void *dec_fxns = (void *)ivdec_api_function;
-
- s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
- s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
- s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
- s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t);
- s_create_ip.s_ivd_create_ip_t.e_output_format = (IV_COLOR_FORMAT_T)mIvColorFormat;
- s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
- s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
- s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
-
- status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op);
-
- mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
- mCodecCtx->pv_fxns = dec_fxns;
- mCodecCtx->u4_size = sizeof(iv_obj_t);
-
- if (status != IV_SUCCESS) {
- ALOGE("Error in create: 0x%x",
- s_create_op.s_ivd_create_op_t.u4_error_code);
- deInitDecoder();
- return UNKNOWN_ERROR;
- }
- }
-
- /* Reset the plugin state */
- resetPlugin();
-
- /* Set the run time (dynamic) parameters */
- setParams(mStride);
-
- /* Set number of cores/threads to be used by the codec */
- setNumCores();
-
- /* Get codec version */
- logVersion();
-
- mFlushNeeded = false;
- return OK;
-}
-
-status_t C2SoftAvcDec::deInitDecoder() {
- IV_API_CALL_STATUS_T status;
-
- if (mCodecCtx) {
- ivdext_delete_ip_t s_delete_ip;
- ivdext_delete_op_t s_delete_op;
-
- s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
- s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
-
- s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t);
-
- status = ivdec_api_function(mCodecCtx, (void *)&s_delete_ip, (void *)&s_delete_op);
- if (status != IV_SUCCESS) {
- ALOGE("Error in delete: 0x%x",
- s_delete_op.s_ivd_delete_op_t.u4_error_code);
- return UNKNOWN_ERROR;
- }
- mCodecCtx = NULL;
- }
-
- mChangingResolution = false;
-
- return OK;
-}
-
-bool C2SoftAvcDec::getVUIParams() {
- IV_API_CALL_STATUS_T status;
- ih264d_ctl_get_vui_params_ip_t s_ctl_get_vui_params_ip;
- ih264d_ctl_get_vui_params_op_t s_ctl_get_vui_params_op;
-
- s_ctl_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_ctl_get_vui_params_ip.e_sub_cmd =
- (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_GET_VUI_PARAMS;
-
- s_ctl_get_vui_params_ip.u4_size =
- sizeof(ih264d_ctl_get_vui_params_ip_t);
-
- s_ctl_get_vui_params_op.u4_size = sizeof(ih264d_ctl_get_vui_params_op_t);
-
- status = ivdec_api_function(
- (iv_obj_t *)mCodecCtx, (void *)&s_ctl_get_vui_params_ip,
- (void *)&s_ctl_get_vui_params_op);
-
- if (status != IV_SUCCESS) {
- ALOGW("Error in getting VUI params: 0x%x",
- s_ctl_get_vui_params_op.u4_error_code);
- return false;
- }
-
- int32_t primaries = s_ctl_get_vui_params_op.u1_colour_primaries;
- int32_t transfer = s_ctl_get_vui_params_op.u1_tfr_chars;
- int32_t coeffs = s_ctl_get_vui_params_op.u1_matrix_coeffs;
- bool fullRange = s_ctl_get_vui_params_op.u1_video_full_range_flag;
-
- ColorAspects colorAspects;
- ColorUtils::convertIsoColorAspectsToCodecAspects(
- primaries, transfer, coeffs, fullRange, colorAspects);
-
- // Update color aspects if necessary.
- if (colorAspectsDiffer(colorAspects, mBitstreamColorAspects)) {
- mBitstreamColorAspects = colorAspects;
- status_t err = handleColorAspectsChange();
- CHECK(err == OK);
- }
- return true;
-}
-
-bool C2SoftAvcDec::setDecodeArgs(
- ivd_video_decode_ip_t *ps_dec_ip,
- ivd_video_decode_op_t *ps_dec_op,
- C2ReadView *inBuffer,
- C2GraphicView *outBuffer,
- uint32_t workIndex,
- size_t inOffset) {
- size_t width = mWidth;
- size_t height = mHeight;
- size_t sizeY = width * height;
- size_t sizeUV;
-
- ps_dec_ip->u4_size = sizeof(ivd_video_decode_ip_t);
- ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
- ps_dec_op->u4_output_present = 0;
-
- ps_dec_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
-
- /* When in flush and after EOS with zero byte input,
- * inBuffer is set to zero. Hence check for non-null */
- if (inBuffer) {
- ps_dec_ip->u4_ts = workIndex;
- ps_dec_ip->pv_stream_buffer = const_cast<uint8_t *>(inBuffer->data()) + inOffset;
- ps_dec_ip->u4_num_Bytes = inBuffer->capacity() - inOffset;
- } else {
- ps_dec_ip->u4_ts = 0;
- ps_dec_ip->pv_stream_buffer = NULL;
- ps_dec_ip->u4_num_Bytes = 0;
- }
-
- sizeUV = sizeY / 4;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
- ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
-
- if (outBuffer) {
- if (outBuffer->width() < width ||
- outBuffer->height() < height) {
- ALOGE("Output buffer too small: provided (%dx%d) required (%zux%zu)",
- outBuffer->width(), outBuffer->height(), width, height);
- return false;
- }
- ALOGV("width = %u, stride[0] = %u, stride[1] = %u, stride[2] = %u",
- outBuffer->width(),
- outBuffer->layout().planes[0].rowInc,
- outBuffer->layout().planes[1].rowInc,
- outBuffer->layout().planes[2].rowInc);
- const C2PlanarLayout &layout = outBuffer->layout();
- ps_dec_ip->s_out_buffer.pu1_bufs[0] = outBuffer->data()[0];
- if (layout.planes[0].rowInc != (int32_t)mWidth || layout.planes[1].colInc != 1) {
- ps_dec_ip->s_out_buffer.pu1_bufs[0] = mOutBuffer;
- }
- ps_dec_ip->s_out_buffer.pu1_bufs[1] = outBuffer->data()[1];
- if (layout.planes[1].rowInc != (int32_t)mWidth / 2 || layout.planes[1].colInc != 1) {
- ps_dec_ip->s_out_buffer.pu1_bufs[1] = mOutBuffer + sizeY;
- }
- ps_dec_ip->s_out_buffer.pu1_bufs[2] = outBuffer->data()[2];
- if (layout.planes[2].rowInc != (int32_t)mWidth / 2 || layout.planes[2].colInc != 1) {
- ps_dec_ip->s_out_buffer.pu1_bufs[2] = mOutBuffer + sizeY + sizeUV;
- }
- } else {
- // mOutBuffer always has the right size.
- ps_dec_ip->s_out_buffer.pu1_bufs[0] = mOutBuffer;
- ps_dec_ip->s_out_buffer.pu1_bufs[1] = mOutBuffer + sizeY;
- ps_dec_ip->s_out_buffer.pu1_bufs[2] = mOutBuffer + sizeY + sizeUV;
- }
-
- ps_dec_ip->s_out_buffer.u4_num_bufs = 3;
- return true;
-}
-
-c2_status_t C2SoftAvcDec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
- if (NULL == mCodecCtx) {
- if (OK != initDecoder()) {
- ALOGE("Failed to initialize decoder");
- // TODO: notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
- mSignalledError = true;
- return C2_CORRUPTED;
- }
- }
- if (mWidth != mStride) {
- /* Set the run-time (dynamic) parameters */
- mStride = mWidth;
- setParams(mStride);
- }
-
- if (!mAllocatedBlock) {
- // TODO: error handling
- // TODO: format & usage
- uint32_t format = HAL_PIXEL_FORMAT_YV12;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- ALOGV("using allocator %u", pool->getAllocatorId());
-
- (void)pool->fetchGraphicBlock(
- mWidth, mHeight, format, usage, &mAllocatedBlock);
- ALOGV("provided (%dx%d) required (%dx%d)",
- mAllocatedBlock->width(), mAllocatedBlock->height(), mWidth, mHeight);
- }
- return C2_OK;
-}
-
-void C2SoftAvcDec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) {
- std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(mAllocatedBlock);
- mAllocatedBlock.reset();
- auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("EOS");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
- if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
- fillWork(work);
- } else {
- finish(index, fillWork);
- }
-}
-
-void C2SoftAvcDec::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- bool eos = false;
-
- work->result = C2_OK;
- work->workletsProcessed = 0u;
-
- const C2ConstLinearBlock buffer =
- work->input.buffers[0]->data().linearBlocks().front();
- if (buffer.size() == 0) {
- ALOGV("empty input: %llu", work->input.ordinal.frameIndex.peekull());
- // TODO: result?
- fillEmptyWork(work);
- if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM)) {
- eos = true;
- }
- return;
- } else if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- ALOGV("input EOS: %llu", work->input.ordinal.frameIndex.peekull());
- eos = true;
- }
-
- C2ReadView input = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (input.error() != C2_OK) {
- work->result = input.error();
- fillEmptyWork(work);
- ALOGD("map error: %d", input.error());
- return;
- }
- ALOGV("buffer.size() = %u, input.capacity() = %u", buffer.size(), input.capacity());
- uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
- size_t inOffset = 0u;
-
- while (inOffset < input.capacity()) {
- if (mSignalledError) {
- break;
- }
- (void)ensureDecoderState(pool);
- ivd_video_decode_ip_t s_dec_ip;
- ivd_video_decode_op_t s_dec_op;
- WORD32 timeDelay, timeTaken;
- //size_t sizeY, sizeUV;
-
- {
- C2GraphicView output = mAllocatedBlock->map().get();
- if (output.error() != C2_OK) {
- ALOGE("mapped err = %d", output.error());
- work->result = output.error();
- fillEmptyWork(work);
- return;
- }
- if (!setDecodeArgs(&s_dec_ip, &s_dec_op, &input, &output, workIndex, inOffset)) {
- ALOGE("Decoder arg setup failed");
- // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
- mSignalledError = true;
- break;
- }
- ALOGV("Decoder arg setup succeeded");
- // If input dump is enabled, then write to file
- DUMP_TO_FILE(mInFile, s_dec_ip.pv_stream_buffer, s_dec_ip.u4_num_Bytes, mInputOffset);
-
- GETTIME(&mTimeStart, NULL);
- /* Compute time elapsed between end of previous decode()
- * to start of current decode() */
- TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
-
- IV_API_CALL_STATUS_T status;
- status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
- ALOGV("status = %d, error_code = %d", status, (s_dec_op.u4_error_code & 0xFF));
- if (s_dec_op.u4_output_present) {
- const C2PlanarLayout &layout = output.layout();
- if (layout.planes[0].rowInc != (int32_t)mWidth || layout.planes[1].colInc != 1) {
- CopyPlane(output.data()[0], layout.planes[0], mOutBuffer, mWidth, mHeight);
- }
- if (layout.planes[1].rowInc != (int32_t)mWidth / 2 || layout.planes[1].colInc != 1) {
- CopyPlane(
- output.data()[1], layout.planes[1],
- mOutBuffer + (mWidth * mHeight), mWidth / 2, mHeight / 2);
- }
- if (layout.planes[2].rowInc != (int32_t)mWidth / 2 || layout.planes[2].colInc != 1) {
- CopyPlane(
- output.data()[2], layout.planes[2],
- mOutBuffer + (mWidth * mHeight * 5 / 4), mWidth / 2, mHeight / 2);
- }
- }
- }
-
- bool unsupportedResolution =
- (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
-
- /* Check for unsupported dimensions */
- if (unsupportedResolution) {
- ALOGE("Unsupported resolution : %dx%d", mWidth, mHeight);
- // TODO: notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
- mSignalledError = true;
- break;
- }
-
- bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & 0xFF));
- if (allocationFailed) {
- ALOGE("Allocation failure in decoder");
- // TODO: notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
- mSignalledError = true;
- break;
- }
-
- bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
-
- getVUIParams();
-
- GETTIME(&mTimeEnd, NULL);
- /* Compute time taken for decode() */
- TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
-
- PRINT_TIME("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
- s_dec_op.u4_num_bytes_consumed);
- ALOGV("bytes total=%u", input.capacity());
- if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
- mFlushNeeded = true;
- }
-
- if (1 != s_dec_op.u4_frame_decoded_flag) {
- /* If the input did not contain picture data, return work without
- * buffer */
- ALOGV("no picture data: %u", workIndex);
- fillEmptyWork(work);
- }
-
- if (resChanged) {
- ALOGV("res changed");
- if (mFlushNeeded) {
- drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
- }
- resetDecoder();
- resetPlugin();
- mStride = mWidth;
- setParams(mStride);
- continue;
- }
-
- if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) {
- uint32_t width = s_dec_op.u4_pic_wd;
- uint32_t height = s_dec_op.u4_pic_ht;
- ALOGV("width = %u height = %u", width, height);
- if (width != mWidth || height != mHeight) {
- mAllocatedBlock.reset();
- mWidth = width;
- mHeight = height;
- }
- // TODO: continue?
- }
-
- if (mUpdateColorAspects) {
- //notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
- // kDescribeColorAspectsIndex, NULL);
- ALOGV("update color aspect");
- mUpdateColorAspects = false;
- }
-
- if (s_dec_op.u4_output_present) {
- ALOGV("output_present: %d", s_dec_op.u4_ts);
- finishWork(s_dec_op.u4_ts, work);
- }
-
- inOffset += s_dec_op.u4_num_bytes_consumed;
- }
- if (inOffset >= input.capacity()) {
- /* If input EOS is seen, drain the decoder.
- * There can be a case where EOS is sent along with last picture data
- * In that case, only after decoding that input data, decoder has to be
- * put in flush. This case is handled here */
- if (eos) {
- drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
- }
- }
-}
-
-c2_status_t C2SoftAvcDec::drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work) {
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
- setFlushMode();
-
- while (true) {
- (void)ensureDecoderState(pool);
- C2GraphicView output = mAllocatedBlock->map().get();
- if (output.error() != OK) {
- ALOGE("mapped err = %d", output.error());
- }
-
- ivd_video_decode_ip_t s_dec_ip;
- ivd_video_decode_op_t s_dec_op;
-
- setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, &output, 0, 0u);
-
- (void)ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
-
- if (s_dec_op.u4_output_present) {
- ALOGV("output_present: %d", s_dec_op.u4_ts);
- finishWork(s_dec_op.u4_ts, work);
- } else {
- break;
- }
- }
-
- if (drainMode == DRAIN_COMPONENT_WITH_EOS
- && work && work->workletsProcessed == 0u) {
- fillEmptyWork(work);
- }
-
- return C2_OK;
-}
-
-bool C2SoftAvcDec::colorAspectsDiffer(
- const ColorAspects &a, const ColorAspects &b) {
- if (a.mRange != b.mRange
- || a.mPrimaries != b.mPrimaries
- || a.mTransfer != b.mTransfer
- || a.mMatrixCoeffs != b.mMatrixCoeffs) {
- return true;
- }
- return false;
-}
-
-c2_status_t C2SoftAvcDec::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- return drainInternal(drainMode, pool, nullptr);
-}
-
-void C2SoftAvcDec::updateFinalColorAspects(
- const ColorAspects &otherAspects, const ColorAspects &preferredAspects) {
- Mutex::Autolock autoLock(mColorAspectsLock);
- ColorAspects newAspects;
- newAspects.mRange = preferredAspects.mRange != ColorAspects::RangeUnspecified ?
- preferredAspects.mRange : otherAspects.mRange;
- newAspects.mPrimaries = preferredAspects.mPrimaries != ColorAspects::PrimariesUnspecified ?
- preferredAspects.mPrimaries : otherAspects.mPrimaries;
- newAspects.mTransfer = preferredAspects.mTransfer != ColorAspects::TransferUnspecified ?
- preferredAspects.mTransfer : otherAspects.mTransfer;
- newAspects.mMatrixCoeffs = preferredAspects.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
- preferredAspects.mMatrixCoeffs : otherAspects.mMatrixCoeffs;
-
- // Check to see if need update mFinalColorAspects.
- if (colorAspectsDiffer(mFinalColorAspects, newAspects)) {
- mFinalColorAspects = newAspects;
- mUpdateColorAspects = true;
- }
-}
-
-status_t C2SoftAvcDec::handleColorAspectsChange() {
-// int perference = getColorAspectPreference();
-// ALOGD("Color Aspects preference: %d ", perference);
-//
-// if (perference == kPreferBitstream) {
-// updateFinalColorAspects(mDefaultColorAspects, mBitstreamColorAspects);
-// } else if (perference == kPreferContainer) {
-// updateFinalColorAspects(mBitstreamColorAspects, mDefaultColorAspects);
-// } else {
-// return OMX_ErrorUnsupportedSetting;
-// }
- updateFinalColorAspects(mDefaultColorAspects, mBitstreamColorAspects);
- return C2_OK;
-}
-
-class C2SoftAvcDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAvcDec(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftAvcDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftAvcDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
deleted file mode 100644
index d324a0f..0000000
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef C2_SOFT_H264_DEC_H_
-
-#define C2_SOFT_H264_DEC_H_
-
-#include <condition_variable>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <set>
-#include <unordered_map>
-
-#include <util/C2ParamUtils.h>
-
-#include <C2Component.h>
-#include <C2Param.h>
-#include <SimpleC2Component.h>
-
-#include "C2AvcConfig.h"
-
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/foundation/ColorUtils.h>
-
-#include <sys/time.h>
-
-namespace android {
-
-struct iv_obj_t;
-struct ivd_video_decode_ip_t;
-struct ivd_video_decode_op_t;
-
-/** Number of entries in the time-stamp array */
-#define MAX_PENDING_WORKS 64
-
-/** Maximum number of cores supported by the codec */
-#define CODEC_MAX_NUM_CORES 4
-
-#define CODEC_MAX_WIDTH 1920
-
-#define CODEC_MAX_HEIGHT 1088
-
-/** Input buffer size */
-#define INPUT_BUF_SIZE (1024 * 1024)
-
-#define MIN(a, b) ((a) < (b)) ? (a) : (b)
-
-/** Get time */
-#define GETTIME(a, b) gettimeofday(a, b);
-
-/** Compute difference between start and end */
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
-#if 0
-class C2SoftAvcDecIntf : public C2ComponentInterface {
-public:
- struct SupportedValuesWithFields {
- C2FieldSupportedValues supported;
- std::set<C2ParamField> restrictingFields;
-
- SupportedValuesWithFields(const C2FieldSupportedValues &supported) : supported(supported) {}
- };
-
- C2SoftAvcDecIntf(const char *name, c2_node_id_t id);
- virtual ~C2SoftAvcDecIntf() override;
-
- // From C2ComponentInterface
- virtual C2String getName() const override;
- virtual c2_node_id_t getId() const override;
- virtual c2_status_t query_vb(
- const std::vector<C2Param*> &stackParams,
- const std::vector<C2Param::Index> &heapParamIndices,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
- virtual c2_status_t config_vb(
- const std::vector<C2Param*> ¶ms,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
- virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) override;
- virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) override;
- // TODO: move this into some common store class
- std::shared_ptr<C2ParamReflector> getParamReflector() const;
- virtual c2_status_t querySupportedParams_nb(
- std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override;
- virtual c2_status_t querySupportedValues_vb(
- std::vector<C2FieldSupportedValuesQuery> &fields, c2_blocking_t mayBlock) const override;
-
-private:
- class ParamReflector;
-
- const C2String mName;
- const c2_node_id_t mId;
-
- C2ComponentDomainInfo mDomainInfo;
- // TODO: config desc
- std::unique_ptr<C2PortMimeConfig::input> mInputPortMime;
- C2PortStreamCountConfig::input mInputStreamCount;
- std::unique_ptr<C2PortMimeConfig::output> mOutputPortMime;
- C2PortStreamCountConfig::output mOutputStreamCount;
- // TODO: C2StreamMimeConfig mInputStreamMime;
- // TODO: C2StreamMimeConfig mOutputStreamMime;
- C2StreamFormatConfig::input mInputStreamFormat;
- std::unique_ptr<C2PortBlockPoolsTuning::output> mOutputBlockPools;
- C2StreamFormatConfig::output mOutputStreamFormat;
- C2VideoSizeStreamInfo::output mVideoSize;
- C2MaxVideoSizeHintPortSetting::input mMaxVideoSizeHint;
- C2AvcProfileInfo::input mProfile;
- C2AvcLevelInfo::input mLevel;
- C2BlockSizeInfo::output mBlockSize;
- C2AlignmentInfo::output mAlignment;
- C2FrameRateInfo::output mFrameRate;
- C2BlocksPerSecondInfo::output mBlocksPerSecond;
-
- std::shared_ptr<C2ParamReflector> mParamReflector;
-
- std::unordered_map<uint32_t, C2Param *> mParams;
- // C2ParamField is LessThanComparable
- std::map<C2ParamField, SupportedValuesWithFields> mSupportedValues;
- std::unordered_map<
- uint32_t, std::function<std::unique_ptr<C2SettingResult>(C2Param *)>> mFieldVerifiers;
- std::vector<std::shared_ptr<C2ParamDescriptor>> mParamDescs;
-
- void updateSupportedValues();
- friend class C2SoftAvcDec;
-};
-#endif
-
-class C2SoftAvcDec : public SimpleC2Component {
-public:
- C2SoftAvcDec(const char *name, c2_node_id_t id);
- virtual ~C2SoftAvcDec();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- Mutex mColorAspectsLock;
- // color aspects passed from the framework.
- ColorAspects mDefaultColorAspects;
- // color aspects parsed from the bitstream.
- ColorAspects mBitstreamColorAspects;
- // final color aspects after combining the above two aspects.
- ColorAspects mFinalColorAspects;
- bool mUpdateColorAspects;
-
- bool colorAspectsDiffer(const ColorAspects &a, const ColorAspects &b);
-
- // This functions takes two color aspects and updates the mFinalColorAspects
- // based on |preferredAspects|.
- void updateFinalColorAspects(
- const ColorAspects &otherAspects, const ColorAspects &preferredAspects);
-
- // This function will update the mFinalColorAspects based on codec preference.
- status_t handleColorAspectsChange();
-
- std::shared_ptr<C2GraphicBlock> mAllocatedBlock;
-
- iv_obj_t *mCodecCtx; // Codec context
-
- size_t mNumCores; // Number of cores to be uesd by the codec
-
- struct timeval mTimeStart; // Time at the start of decode()
- struct timeval mTimeEnd; // Time at the end of decode()
-
- // Internal buffer to be used to flush out the buffers from decoder
- uint8_t *mOutBuffer;
-
-#ifdef FILE_DUMP_ENABLE
- char mInFile[200];
-#endif /* FILE_DUMP_ENABLE */
-
- int mIvColorFormat; // Ittiam Color format
-
- bool mIsInFlush; // codec is flush mode
- bool mReceivedEOS; // EOS is receieved on input port
-
- // The input stream has changed to a different resolution, which is still supported by the
- // codec. So the codec is switching to decode the new resolution.
- bool mChangingResolution;
- bool mFlushNeeded;
- bool mSignalledError;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mStride;
- size_t mInputOffset;
-
- status_t initDecoder();
- status_t deInitDecoder();
- status_t setFlushMode();
- status_t setParams(size_t stride);
- void logVersion();
- status_t setNumCores();
- status_t resetDecoder();
- status_t resetPlugin();
-
- c2_status_t ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool);
- void finishWork(uint64_t index, const std::unique_ptr<C2Work> &work);
- c2_status_t drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work);
-
- bool setDecodeArgs(
- ivd_video_decode_ip_t *ps_dec_ip,
- ivd_video_decode_op_t *ps_dec_op,
- C2ReadView *inBuffer,
- C2GraphicView *outBuffer,
- uint32_t timeStampIx,
- size_t inOffset);
-
- bool getVUIParams();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftAvcDec);
-};
-
-#ifdef FILE_DUMP_ENABLE
-
-#define INPUT_DUMP_PATH "/sdcard/media/avcd_input"
-#define INPUT_DUMP_EXT "h264"
-
-#define GENERATE_FILE_NAMES() { \
- GETTIME(&mTimeStart, NULL); \
- strcpy(mInFile, ""); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
- INPUT_DUMP_EXT); \
-}
-
-#define CREATE_DUMP_FILE(m_filename) { \
- FILE *fp = fopen(m_filename, "wb"); \
- if (fp != NULL) { \
- fclose(fp); \
- } else { \
- ALOGD("Could not open file %s", m_filename); \
- } \
-}
-#define DUMP_TO_FILE(m_filename, m_buf, m_size, m_offset)\
-{ \
- FILE *fp = fopen(m_filename, "ab"); \
- if (fp != NULL && m_buf != NULL && m_offset == 0) { \
- int i; \
- i = fwrite(m_buf, 1, m_size, fp); \
- ALOGD("fwrite ret %d to write %d", i, m_size); \
- if (i != (int) m_size) { \
- ALOGD("Error in fwrite, returned %d", i); \
- perror("Error in write to file"); \
- } \
- } else if (fp == NULL) { \
- ALOGD("Could not write to file %s", m_filename);\
- } \
- if (fp) { \
- fclose(fp); \
- } \
-}
-#else /* FILE_DUMP_ENABLE */
-#define INPUT_DUMP_PATH
-#define INPUT_DUMP_EXT
-#define OUTPUT_DUMP_PATH
-#define OUTPUT_DUMP_EXT
-#define GENERATE_FILE_NAMES()
-#define CREATE_DUMP_FILE(m_filename)
-#define DUMP_TO_FILE(m_filename, m_buf, m_size, m_offset)
-#endif /* FILE_DUMP_ENABLE */
-
-} // namespace android
-
-#endif // C2_SOFT_H264_DEC_H_
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index 67a2fdc..cefe77c 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -1,48 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2avcenc",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- static_libs: [ "libavcenc" ],
- srcs: ["C2SoftAvcEnc.cpp"],
-
- include_dirs: [
- "external/libavc/encoder",
- "external/libavc/common",
- "frameworks/av/media/libstagefright/include",
- "frameworks/native/include/media/hardware",
- ],
-
- shared_libs: [
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libutils",
- "liblog",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-variable",
- ],
- ldflags: ["-Wl,-Bsymbolic"],
-}
-
-cc_library_shared {
name: "libstagefright_soft_avcenc",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
deleted file mode 100644
index d75e4c1..0000000
--- a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
+++ /dev/null
@@ -1,1253 +0,0 @@
-/*
- * Copyright 2018 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 "C2SoftAvcEnc"
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include "ih264_typedefs.h"
-#include "ih264e.h"
-#include "ih264e_error.h"
-#include "iv2.h"
-#include "ive2.h"
-#include "C2SoftAvcEnc.h"
-
-namespace android {
-
-#define ive_api_function ih264e_api_function
-
-constexpr char kComponentName[] = "c2.google.avc.encoder";
-
-namespace {
-
-// From external/libavc/encoder/ih264e_bitstream.h
-constexpr uint32_t MIN_STREAM_SIZE = 0x800;
-
-static size_t GetCPUCoreCount() {
- long cpuCoreCount = 1;
-#if defined(_SC_NPROCESSORS_ONLN)
- cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
-#else
- // _SC_NPROC_ONLN must be defined...
- cpuCoreCount = sysconf(_SC_NPROC_ONLN);
-#endif
- CHECK(cpuCoreCount >= 1);
- ALOGV("Number of CPU cores: %ld", cpuCoreCount);
- return (size_t)cpuCoreCount;
-}
-
-std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatVideo)
- .outputFormat(C2FormatCompressed)
- .inputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
- .outputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
- .build();
-}
-
-void ConvertRGBToPlanarYUV(
- uint8_t *dstY, size_t dstStride, size_t dstVStride,
- const C2GraphicView &src) {
- CHECK((src.width() & 1) == 0);
- CHECK((src.height() & 1) == 0);
-
- uint8_t *dstU = dstY + dstStride * dstVStride;
- uint8_t *dstV = dstU + (dstStride >> 1) * (dstVStride >> 1);
-
- const C2PlanarLayout &layout = src.layout();
- const uint8_t *pRed = src.data()[C2PlanarLayout::PLANE_R];
- const uint8_t *pGreen = src.data()[C2PlanarLayout::PLANE_G];
- const uint8_t *pBlue = src.data()[C2PlanarLayout::PLANE_B];
-
- for (size_t y = 0; y < src.height(); ++y) {
- for (size_t x = 0; x < src.width(); ++x) {
- unsigned red = *pRed;
- unsigned green = *pGreen;
- unsigned blue = *pBlue;
-
- // using ITU-R BT.601 conversion matrix
- unsigned luma =
- ((red * 66 + green * 129 + blue * 25) >> 8) + 16;
-
- dstY[x] = luma;
-
- if ((x & 1) == 0 && (y & 1) == 0) {
- unsigned U =
- ((-red * 38 - green * 74 + blue * 112) >> 8) + 128;
-
- unsigned V =
- ((red * 112 - green * 94 - blue * 18) >> 8) + 128;
-
- dstU[x >> 1] = U;
- dstV[x >> 1] = V;
- }
- pRed += layout.planes[C2PlanarLayout::PLANE_R].colInc;
- pGreen += layout.planes[C2PlanarLayout::PLANE_G].colInc;
- pBlue += layout.planes[C2PlanarLayout::PLANE_B].colInc;
- }
-
- if ((y & 1) == 0) {
- dstU += dstStride >> 1;
- dstV += dstStride >> 1;
- }
-
- pRed -= layout.planes[C2PlanarLayout::PLANE_R].colInc * src.width();
- pGreen -= layout.planes[C2PlanarLayout::PLANE_G].colInc * src.width();
- pBlue -= layout.planes[C2PlanarLayout::PLANE_B].colInc * src.width();
- pRed += layout.planes[C2PlanarLayout::PLANE_R].rowInc;
- pGreen += layout.planes[C2PlanarLayout::PLANE_G].rowInc;
- pBlue += layout.planes[C2PlanarLayout::PLANE_B].rowInc;
-
- dstY += dstStride;
- }
-}
-
-} // namespace
-
-C2SoftAvcEnc::C2SoftAvcEnc(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mUpdateFlag(0),
- mIvVideoColorFormat(IV_YUV_420P),
- mAVCEncProfile(IV_PROFILE_BASE),
- mAVCEncLevel(41),
- mStarted(false),
- mSawInputEOS(false),
- mSawOutputEOS(false),
- mSignalledError(false),
- mCodecCtx(NULL),
- mWidth(1080),
- mHeight(1920),
- mFramerate(60),
- mBitrate(20000),
- // TODO: output buffer size
- mOutBufferSize(524288) {
-
- // If dump is enabled, then open create an empty file
- GENERATE_FILE_NAMES();
- CREATE_DUMP_FILE(mInFile);
- CREATE_DUMP_FILE(mOutFile);
-
- initEncParams();
-}
-
-C2SoftAvcEnc::~C2SoftAvcEnc() {
- releaseEncoder();
-}
-
-c2_status_t C2SoftAvcEnc::onInit() {
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::onStop() {
- return C2_OK;
-}
-
-void C2SoftAvcEnc::onReset() {
- // TODO: use IVE_CMD_CTL_RESET?
- releaseEncoder();
- initEncParams();
-}
-
-void C2SoftAvcEnc::onRelease() {
- releaseEncoder();
-}
-
-c2_status_t C2SoftAvcEnc::onFlush_sm() {
- // TODO: use IVE_CMD_CTL_FLUSH?
- return C2_OK;
-}
-
-void C2SoftAvcEnc::initEncParams() {
- mCodecCtx = NULL;
- mMemRecords = NULL;
- mNumMemRecords = DEFAULT_MEM_REC_CNT;
- mHeaderGenerated = 0;
- mNumCores = GetCPUCoreCount();
- mArch = DEFAULT_ARCH;
- mSliceMode = DEFAULT_SLICE_MODE;
- mSliceParam = DEFAULT_SLICE_PARAM;
- mHalfPelEnable = DEFAULT_HPEL;
- mIInterval = DEFAULT_I_INTERVAL;
- mIDRInterval = DEFAULT_IDR_INTERVAL;
- mDisableDeblkLevel = DEFAULT_DISABLE_DEBLK_LEVEL;
- mEnableFastSad = DEFAULT_ENABLE_FAST_SAD;
- mEnableAltRef = DEFAULT_ENABLE_ALT_REF;
- mEncSpeed = DEFAULT_ENC_SPEED;
- mIntra4x4 = DEFAULT_INTRA4x4;
- mConstrainedIntraFlag = DEFAULT_CONSTRAINED_INTRA;
- mAIRMode = DEFAULT_AIR;
- mAIRRefreshPeriod = DEFAULT_AIR_REFRESH_PERIOD;
- mPSNREnable = DEFAULT_PSNR_ENABLE;
- mReconEnable = DEFAULT_RECON_ENABLE;
- mEntropyMode = DEFAULT_ENTROPY_MODE;
- mBframes = DEFAULT_B_FRAMES;
-
- gettimeofday(&mTimeStart, NULL);
- gettimeofday(&mTimeEnd, NULL);
-}
-
-c2_status_t C2SoftAvcEnc::setDimensions() {
- ive_ctl_set_dimensions_ip_t s_dimensions_ip;
- ive_ctl_set_dimensions_op_t s_dimensions_op;
- IV_STATUS_T status;
-
- s_dimensions_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_dimensions_ip.e_sub_cmd = IVE_CMD_CTL_SET_DIMENSIONS;
- s_dimensions_ip.u4_ht = mHeight;
- s_dimensions_ip.u4_wd = mWidth;
-
- s_dimensions_ip.u4_timestamp_high = -1;
- s_dimensions_ip.u4_timestamp_low = -1;
-
- s_dimensions_ip.u4_size = sizeof(ive_ctl_set_dimensions_ip_t);
- s_dimensions_op.u4_size = sizeof(ive_ctl_set_dimensions_op_t);
-
- status = ive_api_function(mCodecCtx, &s_dimensions_ip, &s_dimensions_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set frame dimensions = 0x%x\n",
- s_dimensions_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setNumCores() {
- IV_STATUS_T status;
- ive_ctl_set_num_cores_ip_t s_num_cores_ip;
- ive_ctl_set_num_cores_op_t s_num_cores_op;
- s_num_cores_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_num_cores_ip.e_sub_cmd = IVE_CMD_CTL_SET_NUM_CORES;
- s_num_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_CORES);
- s_num_cores_ip.u4_timestamp_high = -1;
- s_num_cores_ip.u4_timestamp_low = -1;
- s_num_cores_ip.u4_size = sizeof(ive_ctl_set_num_cores_ip_t);
-
- s_num_cores_op.u4_size = sizeof(ive_ctl_set_num_cores_op_t);
-
- status = ive_api_function(
- mCodecCtx, (void *) &s_num_cores_ip, (void *) &s_num_cores_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set processor params = 0x%x\n",
- s_num_cores_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setFrameRate() {
- ive_ctl_set_frame_rate_ip_t s_frame_rate_ip;
- ive_ctl_set_frame_rate_op_t s_frame_rate_op;
- IV_STATUS_T status;
-
- s_frame_rate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_frame_rate_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
-
- s_frame_rate_ip.u4_src_frame_rate = mFramerate;
- s_frame_rate_ip.u4_tgt_frame_rate = mFramerate;
-
- s_frame_rate_ip.u4_timestamp_high = -1;
- s_frame_rate_ip.u4_timestamp_low = -1;
-
- s_frame_rate_ip.u4_size = sizeof(ive_ctl_set_frame_rate_ip_t);
- s_frame_rate_op.u4_size = sizeof(ive_ctl_set_frame_rate_op_t);
-
- status = ive_api_function(mCodecCtx, &s_frame_rate_ip, &s_frame_rate_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set frame rate = 0x%x\n",
- s_frame_rate_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setIpeParams() {
- ive_ctl_set_ipe_params_ip_t s_ipe_params_ip;
- ive_ctl_set_ipe_params_op_t s_ipe_params_op;
- IV_STATUS_T status;
-
- s_ipe_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_ipe_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_IPE_PARAMS;
-
- s_ipe_params_ip.u4_enable_intra_4x4 = mIntra4x4;
- s_ipe_params_ip.u4_enc_speed_preset = mEncSpeed;
- s_ipe_params_ip.u4_constrained_intra_pred = mConstrainedIntraFlag;
-
- s_ipe_params_ip.u4_timestamp_high = -1;
- s_ipe_params_ip.u4_timestamp_low = -1;
-
- s_ipe_params_ip.u4_size = sizeof(ive_ctl_set_ipe_params_ip_t);
- s_ipe_params_op.u4_size = sizeof(ive_ctl_set_ipe_params_op_t);
-
- status = ive_api_function(mCodecCtx, &s_ipe_params_ip, &s_ipe_params_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set ipe params = 0x%x\n",
- s_ipe_params_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setBitRate() {
- ive_ctl_set_bitrate_ip_t s_bitrate_ip;
- ive_ctl_set_bitrate_op_t s_bitrate_op;
- IV_STATUS_T status;
-
- s_bitrate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_bitrate_ip.e_sub_cmd = IVE_CMD_CTL_SET_BITRATE;
-
- s_bitrate_ip.u4_target_bitrate = mBitrate;
-
- s_bitrate_ip.u4_timestamp_high = -1;
- s_bitrate_ip.u4_timestamp_low = -1;
-
- s_bitrate_ip.u4_size = sizeof(ive_ctl_set_bitrate_ip_t);
- s_bitrate_op.u4_size = sizeof(ive_ctl_set_bitrate_op_t);
-
- status = ive_api_function(mCodecCtx, &s_bitrate_ip, &s_bitrate_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set bit rate = 0x%x\n", s_bitrate_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type) {
- ive_ctl_set_frame_type_ip_t s_frame_type_ip;
- ive_ctl_set_frame_type_op_t s_frame_type_op;
- IV_STATUS_T status;
- s_frame_type_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_frame_type_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
-
- s_frame_type_ip.e_frame_type = e_frame_type;
-
- s_frame_type_ip.u4_timestamp_high = -1;
- s_frame_type_ip.u4_timestamp_low = -1;
-
- s_frame_type_ip.u4_size = sizeof(ive_ctl_set_frame_type_ip_t);
- s_frame_type_op.u4_size = sizeof(ive_ctl_set_frame_type_op_t);
-
- status = ive_api_function(mCodecCtx, &s_frame_type_ip, &s_frame_type_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set frame type = 0x%x\n",
- s_frame_type_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setQp() {
- ive_ctl_set_qp_ip_t s_qp_ip;
- ive_ctl_set_qp_op_t s_qp_op;
- IV_STATUS_T status;
-
- s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
-
- s_qp_ip.u4_i_qp = DEFAULT_I_QP;
- s_qp_ip.u4_i_qp_max = DEFAULT_QP_MAX;
- s_qp_ip.u4_i_qp_min = DEFAULT_QP_MIN;
-
- s_qp_ip.u4_p_qp = DEFAULT_P_QP;
- s_qp_ip.u4_p_qp_max = DEFAULT_QP_MAX;
- s_qp_ip.u4_p_qp_min = DEFAULT_QP_MIN;
-
- s_qp_ip.u4_b_qp = DEFAULT_P_QP;
- s_qp_ip.u4_b_qp_max = DEFAULT_QP_MAX;
- s_qp_ip.u4_b_qp_min = DEFAULT_QP_MIN;
-
- s_qp_ip.u4_timestamp_high = -1;
- s_qp_ip.u4_timestamp_low = -1;
-
- s_qp_ip.u4_size = sizeof(ive_ctl_set_qp_ip_t);
- s_qp_op.u4_size = sizeof(ive_ctl_set_qp_op_t);
-
- status = ive_api_function(mCodecCtx, &s_qp_ip, &s_qp_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set qp 0x%x\n", s_qp_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setEncMode(IVE_ENC_MODE_T e_enc_mode) {
- IV_STATUS_T status;
- ive_ctl_set_enc_mode_ip_t s_enc_mode_ip;
- ive_ctl_set_enc_mode_op_t s_enc_mode_op;
-
- s_enc_mode_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_enc_mode_ip.e_sub_cmd = IVE_CMD_CTL_SET_ENC_MODE;
-
- s_enc_mode_ip.e_enc_mode = e_enc_mode;
-
- s_enc_mode_ip.u4_timestamp_high = -1;
- s_enc_mode_ip.u4_timestamp_low = -1;
-
- s_enc_mode_ip.u4_size = sizeof(ive_ctl_set_enc_mode_ip_t);
- s_enc_mode_op.u4_size = sizeof(ive_ctl_set_enc_mode_op_t);
-
- status = ive_api_function(mCodecCtx, &s_enc_mode_ip, &s_enc_mode_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set in header encode mode = 0x%x\n",
- s_enc_mode_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setVbvParams() {
- ive_ctl_set_vbv_params_ip_t s_vbv_ip;
- ive_ctl_set_vbv_params_op_t s_vbv_op;
- IV_STATUS_T status;
-
- s_vbv_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_vbv_ip.e_sub_cmd = IVE_CMD_CTL_SET_VBV_PARAMS;
-
- s_vbv_ip.u4_vbv_buf_size = 0;
- s_vbv_ip.u4_vbv_buffer_delay = 1000;
-
- s_vbv_ip.u4_timestamp_high = -1;
- s_vbv_ip.u4_timestamp_low = -1;
-
- s_vbv_ip.u4_size = sizeof(ive_ctl_set_vbv_params_ip_t);
- s_vbv_op.u4_size = sizeof(ive_ctl_set_vbv_params_op_t);
-
- status = ive_api_function(mCodecCtx, &s_vbv_ip, &s_vbv_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set VBV params = 0x%x\n", s_vbv_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setAirParams() {
- ive_ctl_set_air_params_ip_t s_air_ip;
- ive_ctl_set_air_params_op_t s_air_op;
- IV_STATUS_T status;
-
- s_air_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_air_ip.e_sub_cmd = IVE_CMD_CTL_SET_AIR_PARAMS;
-
- s_air_ip.e_air_mode = mAIRMode;
- s_air_ip.u4_air_refresh_period = mAIRRefreshPeriod;
-
- s_air_ip.u4_timestamp_high = -1;
- s_air_ip.u4_timestamp_low = -1;
-
- s_air_ip.u4_size = sizeof(ive_ctl_set_air_params_ip_t);
- s_air_op.u4_size = sizeof(ive_ctl_set_air_params_op_t);
-
- status = ive_api_function(mCodecCtx, &s_air_ip, &s_air_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set air params = 0x%x\n", s_air_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setMeParams() {
- IV_STATUS_T status;
- ive_ctl_set_me_params_ip_t s_me_params_ip;
- ive_ctl_set_me_params_op_t s_me_params_op;
-
- s_me_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_me_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_ME_PARAMS;
-
- s_me_params_ip.u4_enable_fast_sad = mEnableFastSad;
- s_me_params_ip.u4_enable_alt_ref = mEnableAltRef;
-
- s_me_params_ip.u4_enable_hpel = mHalfPelEnable;
- s_me_params_ip.u4_enable_qpel = DEFAULT_QPEL;
- s_me_params_ip.u4_me_speed_preset = DEFAULT_ME_SPEED;
- s_me_params_ip.u4_srch_rng_x = DEFAULT_SRCH_RNG_X;
- s_me_params_ip.u4_srch_rng_y = DEFAULT_SRCH_RNG_Y;
-
- s_me_params_ip.u4_timestamp_high = -1;
- s_me_params_ip.u4_timestamp_low = -1;
-
- s_me_params_ip.u4_size = sizeof(ive_ctl_set_me_params_ip_t);
- s_me_params_op.u4_size = sizeof(ive_ctl_set_me_params_op_t);
-
- status = ive_api_function(mCodecCtx, &s_me_params_ip, &s_me_params_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set me params = 0x%x\n", s_me_params_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setGopParams() {
- IV_STATUS_T status;
- ive_ctl_set_gop_params_ip_t s_gop_params_ip;
- ive_ctl_set_gop_params_op_t s_gop_params_op;
-
- s_gop_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_gop_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_GOP_PARAMS;
-
- s_gop_params_ip.u4_i_frm_interval = mIInterval;
- s_gop_params_ip.u4_idr_frm_interval = mIDRInterval;
-
- s_gop_params_ip.u4_timestamp_high = -1;
- s_gop_params_ip.u4_timestamp_low = -1;
-
- s_gop_params_ip.u4_size = sizeof(ive_ctl_set_gop_params_ip_t);
- s_gop_params_op.u4_size = sizeof(ive_ctl_set_gop_params_op_t);
-
- status = ive_api_function(mCodecCtx, &s_gop_params_ip, &s_gop_params_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set GOP params = 0x%x\n",
- s_gop_params_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setProfileParams() {
- IV_STATUS_T status;
- ive_ctl_set_profile_params_ip_t s_profile_params_ip;
- ive_ctl_set_profile_params_op_t s_profile_params_op;
-
- s_profile_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_profile_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
-
- s_profile_params_ip.e_profile = DEFAULT_EPROFILE;
- s_profile_params_ip.u4_entropy_coding_mode = mEntropyMode;
- s_profile_params_ip.u4_timestamp_high = -1;
- s_profile_params_ip.u4_timestamp_low = -1;
-
- s_profile_params_ip.u4_size = sizeof(ive_ctl_set_profile_params_ip_t);
- s_profile_params_op.u4_size = sizeof(ive_ctl_set_profile_params_op_t);
-
- status = ive_api_function(mCodecCtx, &s_profile_params_ip, &s_profile_params_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to set profile params = 0x%x\n",
- s_profile_params_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setDeblockParams() {
- IV_STATUS_T status;
- ive_ctl_set_deblock_params_ip_t s_deblock_params_ip;
- ive_ctl_set_deblock_params_op_t s_deblock_params_op;
-
- s_deblock_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_deblock_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_DEBLOCK_PARAMS;
-
- s_deblock_params_ip.u4_disable_deblock_level = mDisableDeblkLevel;
-
- s_deblock_params_ip.u4_timestamp_high = -1;
- s_deblock_params_ip.u4_timestamp_low = -1;
-
- s_deblock_params_ip.u4_size = sizeof(ive_ctl_set_deblock_params_ip_t);
- s_deblock_params_op.u4_size = sizeof(ive_ctl_set_deblock_params_op_t);
-
- status = ive_api_function(mCodecCtx, &s_deblock_params_ip, &s_deblock_params_op);
- if (status != IV_SUCCESS) {
- ALOGE("Unable to enable/disable deblock params = 0x%x\n",
- s_deblock_params_op.u4_error_code);
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-void C2SoftAvcEnc::logVersion() {
- ive_ctl_getversioninfo_ip_t s_ctl_ip;
- ive_ctl_getversioninfo_op_t s_ctl_op;
- UWORD8 au1_buf[512];
- IV_STATUS_T status;
-
- s_ctl_ip.e_cmd = IVE_CMD_VIDEO_CTL;
- s_ctl_ip.e_sub_cmd = IVE_CMD_CTL_GETVERSION;
- s_ctl_ip.u4_size = sizeof(ive_ctl_getversioninfo_ip_t);
- s_ctl_op.u4_size = sizeof(ive_ctl_getversioninfo_op_t);
- s_ctl_ip.pu1_version = au1_buf;
- s_ctl_ip.u4_version_bufsize = sizeof(au1_buf);
-
- status = ive_api_function(mCodecCtx, (void *) &s_ctl_ip, (void *) &s_ctl_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Error in getting version: 0x%x", s_ctl_op.u4_error_code);
- } else {
- ALOGV("Ittiam encoder version: %s", (char *)s_ctl_ip.pu1_version);
- }
- return;
-}
-
-c2_status_t C2SoftAvcEnc::initEncoder() {
- IV_STATUS_T status;
- WORD32 level;
- uint32_t displaySizeY;
-
- CHECK(!mStarted);
-
- c2_status_t errType = C2_OK;
-
- displaySizeY = mWidth * mHeight;
- if (displaySizeY > (1920 * 1088)) {
- level = 50;
- } else if (displaySizeY > (1280 * 720)) {
- level = 40;
- } else if (displaySizeY > (720 * 576)) {
- level = 31;
- } else if (displaySizeY > (624 * 320)) {
- level = 30;
- } else if (displaySizeY > (352 * 288)) {
- level = 21;
- } else if (displaySizeY > (176 * 144)) {
- level = 20;
- } else {
- level = 10;
- }
- mAVCEncLevel = MAX(level, mAVCEncLevel);
-
- mStride = mWidth;
-
- // TODO
- mIvVideoColorFormat = IV_YUV_420P;
-
- ALOGD("Params width %d height %d level %d colorFormat %d", mWidth,
- mHeight, mAVCEncLevel, mIvVideoColorFormat);
-
- /* Getting Number of MemRecords */
- {
- iv_num_mem_rec_ip_t s_num_mem_rec_ip;
- iv_num_mem_rec_op_t s_num_mem_rec_op;
-
- s_num_mem_rec_ip.u4_size = sizeof(iv_num_mem_rec_ip_t);
- s_num_mem_rec_op.u4_size = sizeof(iv_num_mem_rec_op_t);
-
- s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
-
- status = ive_api_function(0, &s_num_mem_rec_ip, &s_num_mem_rec_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Get number of memory records failed = 0x%x\n",
- s_num_mem_rec_op.u4_error_code);
- return C2_CORRUPTED;
- }
-
- mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
- }
-
- /* Allocate array to hold memory records */
- if (mNumMemRecords > SIZE_MAX / sizeof(iv_mem_rec_t)) {
- ALOGE("requested memory size is too big.");
- return C2_CORRUPTED;
- }
- mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
- if (NULL == mMemRecords) {
- ALOGE("Unable to allocate memory for hold memory records: Size %zu",
- mNumMemRecords * sizeof(iv_mem_rec_t));
- mSignalledError = true;
- return C2_CORRUPTED;
- }
-
- {
- iv_mem_rec_t *ps_mem_rec;
- ps_mem_rec = mMemRecords;
- for (size_t i = 0; i < mNumMemRecords; i++) {
- ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
- ps_mem_rec->pv_base = NULL;
- ps_mem_rec->u4_mem_size = 0;
- ps_mem_rec->u4_mem_alignment = 0;
- ps_mem_rec->e_mem_type = IV_NA_MEM_TYPE;
-
- ps_mem_rec++;
- }
- }
-
- /* Getting MemRecords Attributes */
- {
- iv_fill_mem_rec_ip_t s_fill_mem_rec_ip;
- iv_fill_mem_rec_op_t s_fill_mem_rec_op;
-
- s_fill_mem_rec_ip.u4_size = sizeof(iv_fill_mem_rec_ip_t);
- s_fill_mem_rec_op.u4_size = sizeof(iv_fill_mem_rec_op_t);
-
- s_fill_mem_rec_ip.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
- s_fill_mem_rec_ip.ps_mem_rec = mMemRecords;
- s_fill_mem_rec_ip.u4_num_mem_rec = mNumMemRecords;
- s_fill_mem_rec_ip.u4_max_wd = mWidth;
- s_fill_mem_rec_ip.u4_max_ht = mHeight;
- s_fill_mem_rec_ip.u4_max_level = mAVCEncLevel;
- s_fill_mem_rec_ip.e_color_format = DEFAULT_INP_COLOR_FORMAT;
- s_fill_mem_rec_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
- s_fill_mem_rec_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
- s_fill_mem_rec_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
- s_fill_mem_rec_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
-
- status = ive_api_function(0, &s_fill_mem_rec_ip, &s_fill_mem_rec_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Fill memory records failed = 0x%x\n",
- s_fill_mem_rec_op.u4_error_code);
- return C2_CORRUPTED;
- }
- }
-
- /* Allocating Memory for Mem Records */
- {
- WORD32 total_size;
- iv_mem_rec_t *ps_mem_rec;
- total_size = 0;
- ps_mem_rec = mMemRecords;
-
- for (size_t i = 0; i < mNumMemRecords; i++) {
- ps_mem_rec->pv_base = ive_aligned_malloc(
- ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
- if (ps_mem_rec->pv_base == NULL) {
- ALOGE("Allocation failure for mem record id %zu size %u\n", i,
- ps_mem_rec->u4_mem_size);
- return C2_CORRUPTED;
-
- }
- total_size += ps_mem_rec->u4_mem_size;
-
- ps_mem_rec++;
- }
- }
-
- /* Codec Instance Creation */
- {
- ive_init_ip_t s_init_ip;
- ive_init_op_t s_init_op;
-
- mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
- mCodecCtx->u4_size = sizeof(iv_obj_t);
- mCodecCtx->pv_fxns = (void *)ive_api_function;
-
- s_init_ip.u4_size = sizeof(ive_init_ip_t);
- s_init_op.u4_size = sizeof(ive_init_op_t);
-
- s_init_ip.e_cmd = IV_CMD_INIT;
- s_init_ip.u4_num_mem_rec = mNumMemRecords;
- s_init_ip.ps_mem_rec = mMemRecords;
- s_init_ip.u4_max_wd = mWidth;
- s_init_ip.u4_max_ht = mHeight;
- s_init_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
- s_init_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
- s_init_ip.u4_max_level = mAVCEncLevel;
- s_init_ip.e_inp_color_fmt = mIvVideoColorFormat;
-
- if (mReconEnable || mPSNREnable) {
- s_init_ip.u4_enable_recon = 1;
- } else {
- s_init_ip.u4_enable_recon = 0;
- }
- s_init_ip.e_recon_color_fmt = DEFAULT_RECON_COLOR_FORMAT;
- s_init_ip.e_rc_mode = DEFAULT_RC_MODE;
- s_init_ip.u4_max_framerate = DEFAULT_MAX_FRAMERATE;
- s_init_ip.u4_max_bitrate = DEFAULT_MAX_BITRATE;
- s_init_ip.u4_num_bframes = mBframes;
- s_init_ip.e_content_type = IV_PROGRESSIVE;
- s_init_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
- s_init_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
- s_init_ip.e_slice_mode = mSliceMode;
- s_init_ip.u4_slice_param = mSliceParam;
- s_init_ip.e_arch = mArch;
- s_init_ip.e_soc = DEFAULT_SOC;
-
- status = ive_api_function(mCodecCtx, &s_init_ip, &s_init_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Init encoder failed = 0x%x\n", s_init_op.u4_error_code);
- return C2_CORRUPTED;
- }
- }
-
- /* Get Codec Version */
- logVersion();
-
- /* set processor details */
- setNumCores();
-
- /* Video control Set Frame dimensions */
- setDimensions();
-
- /* Video control Set Frame rates */
- setFrameRate();
-
- /* Video control Set IPE Params */
- setIpeParams();
-
- /* Video control Set Bitrate */
- setBitRate();
-
- /* Video control Set QP */
- setQp();
-
- /* Video control Set AIR params */
- setAirParams();
-
- /* Video control Set VBV params */
- setVbvParams();
-
- /* Video control Set Motion estimation params */
- setMeParams();
-
- /* Video control Set GOP params */
- setGopParams();
-
- /* Video control Set Deblock params */
- setDeblockParams();
-
- /* Video control Set Profile params */
- setProfileParams();
-
- /* Video control Set in Encode header mode */
- setEncMode(IVE_ENC_MODE_HEADER);
-
- ALOGV("init_codec successfull");
-
- mSpsPpsHeaderReceived = false;
- mStarted = true;
-
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::releaseEncoder() {
- IV_STATUS_T status = IV_SUCCESS;
- iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
- iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
- iv_mem_rec_t *ps_mem_rec;
-
- if (!mStarted) {
- return C2_OK;
- }
-
- s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
- s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
- s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
- s_retrieve_mem_ip.ps_mem_rec = mMemRecords;
-
- status = ive_api_function(mCodecCtx, &s_retrieve_mem_ip, &s_retrieve_mem_op);
-
- if (status != IV_SUCCESS) {
- ALOGE("Unable to retrieve memory records = 0x%x\n",
- s_retrieve_mem_op.u4_error_code);
- return C2_CORRUPTED;
- }
-
- /* Free memory records */
- ps_mem_rec = mMemRecords;
- for (size_t i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
- ive_aligned_free(ps_mem_rec->pv_base);
- ps_mem_rec++;
- }
-
- free(mMemRecords);
-
- // clear other pointers into the space being free()d
- mCodecCtx = NULL;
-
- mStarted = false;
-
- return C2_OK;
-}
-
-c2_status_t C2SoftAvcEnc::setEncodeArgs(
- ive_video_encode_ip_t *ps_encode_ip,
- ive_video_encode_op_t *ps_encode_op,
- const C2GraphicView *const input,
- uint8_t *base,
- uint32_t capacity,
- uint64_t timestamp) {
- iv_raw_buf_t *ps_inp_raw_buf;
-
- ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
- ps_encode_ip->s_out_buf.pv_buf = base;
- ps_encode_ip->s_out_buf.u4_bytes = 0;
- ps_encode_ip->s_out_buf.u4_bufsize = capacity;
- ps_encode_ip->u4_size = sizeof(ive_video_encode_ip_t);
- ps_encode_op->u4_size = sizeof(ive_video_encode_op_t);
-
- ps_encode_ip->e_cmd = IVE_CMD_VIDEO_ENCODE;
- ps_encode_ip->pv_bufs = NULL;
- ps_encode_ip->pv_mb_info = NULL;
- ps_encode_ip->pv_pic_info = NULL;
- ps_encode_ip->u4_mb_info_type = 0;
- ps_encode_ip->u4_pic_info_type = 0;
- ps_encode_ip->u4_is_last = 0;
- ps_encode_ip->u4_timestamp_high = timestamp >> 32;
- ps_encode_ip->u4_timestamp_low = timestamp & 0xFFFFFFFF;
- ps_encode_op->s_out_buf.pv_buf = NULL;
-
- /* Initialize color formats */
- memset(ps_inp_raw_buf, 0, sizeof(iv_raw_buf_t));
- ps_inp_raw_buf->u4_size = sizeof(iv_raw_buf_t);
- ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
- if (input == nullptr) {
- if (mSawInputEOS){
- ps_encode_ip->u4_is_last = 1;
- }
- return C2_OK;
- }
-
- ALOGV("width = %d, height = %d", input->width(), input->height());
- if (mWidth != input->width() || mHeight != input->height()) {
- return C2_BAD_VALUE;
- }
- const C2PlanarLayout &layout = input->layout();
- uint8_t *yPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_Y]);
- uint8_t *uPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_U]);
- uint8_t *vPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_V]);
- int32_t yStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
- int32_t uStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
- int32_t vStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
-
- switch (layout.type) {
- case C2PlanarLayout::TYPE_RGB:
- // fall-through
- case C2PlanarLayout::TYPE_RGBA: {
- size_t yPlaneSize = input->width() * input->height();
- std::unique_ptr<uint8_t[]> freeBuffer;
- if (mFreeConversionBuffers.empty()) {
- freeBuffer.reset(new uint8_t[yPlaneSize * 3 / 2]);
- } else {
- freeBuffer.swap(mFreeConversionBuffers.front());
- mFreeConversionBuffers.pop_front();
- }
- yPlane = freeBuffer.get();
- mConversionBuffersInUse.push_back(std::move(freeBuffer));
- uPlane = yPlane + yPlaneSize;
- vPlane = uPlane + yPlaneSize / 4;
- yStride = input->width();
- uStride = vStride = input->width() / 2;
- ConvertRGBToPlanarYUV(yPlane, yStride, input->height(), *input);
- break;
- }
- case C2PlanarLayout::TYPE_YUV:
- // fall-through
- case C2PlanarLayout::TYPE_YUVA:
- // Do nothing
- break;
- default:
- ALOGE("Unrecognized plane type: %d", layout.type);
- return C2_BAD_VALUE;
- }
-
- switch (mIvVideoColorFormat) {
- case IV_YUV_420P:
- {
- // input buffer is supposed to be const but Ittiam API wants bare pointer.
- ps_inp_raw_buf->apv_bufs[0] = yPlane;
- ps_inp_raw_buf->apv_bufs[1] = uPlane;
- ps_inp_raw_buf->apv_bufs[2] = vPlane;
-
- ps_inp_raw_buf->au4_wd[0] = input->width();
- ps_inp_raw_buf->au4_wd[1] = input->width() / 2;
- ps_inp_raw_buf->au4_wd[2] = input->width() / 2;
-
- ps_inp_raw_buf->au4_ht[0] = input->height();
- ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
- ps_inp_raw_buf->au4_ht[2] = input->height() / 2;
-
- ps_inp_raw_buf->au4_strd[0] = yStride;
- ps_inp_raw_buf->au4_strd[1] = uStride;
- ps_inp_raw_buf->au4_strd[2] = vStride;
- break;
- }
-
- case IV_YUV_422ILE:
- {
- // TODO
- // ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
- // ps_inp_raw_buf->au4_wd[0] = mWidth * 2;
- // ps_inp_raw_buf->au4_ht[0] = mHeight;
- // ps_inp_raw_buf->au4_strd[0] = mStride * 2;
- break;
- }
-
- case IV_YUV_420SP_UV:
- case IV_YUV_420SP_VU:
- default:
- {
- ps_inp_raw_buf->apv_bufs[0] = yPlane;
- ps_inp_raw_buf->apv_bufs[1] = uPlane;
-
- ps_inp_raw_buf->au4_wd[0] = input->width();
- ps_inp_raw_buf->au4_wd[1] = input->width();
-
- ps_inp_raw_buf->au4_ht[0] = input->height();
- ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
-
- ps_inp_raw_buf->au4_strd[0] = yStride;
- ps_inp_raw_buf->au4_strd[1] = uStride;
- break;
- }
- }
- return C2_OK;
-}
-
-void C2SoftAvcEnc::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
-
- IV_STATUS_T status;
- WORD32 timeDelay, timeTaken;
- uint64_t timestamp = work->input.ordinal.timestamp.peekull();
-
- // Initialize encoder if not already initialized
- if (mCodecCtx == NULL) {
- if (C2_OK != initEncoder()) {
- ALOGE("Failed to initialize encoder");
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
- return;
- }
- }
- if (mSignalledError) {
- return;
- }
-
- // while (!mSawOutputEOS && !outQueue.empty()) {
- c2_status_t error;
- ive_video_encode_ip_t s_encode_ip;
- ive_video_encode_op_t s_encode_op;
-
- if (!mSpsPpsHeaderReceived) {
- constexpr uint32_t kHeaderLength = MIN_STREAM_SIZE;
- uint8_t header[kHeaderLength];
- error = setEncodeArgs(
- &s_encode_ip, &s_encode_op, NULL, header, kHeaderLength, timestamp);
- if (error != C2_OK) {
- mSignalledError = true;
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
- return;
- }
- status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
-
- if (IV_SUCCESS != status) {
- ALOGE("Encode header failed = 0x%x\n",
- s_encode_op.u4_error_code);
- return;
- } else {
- ALOGV("Bytes Generated in header %d\n",
- s_encode_op.s_out_buf.u4_bytes);
- }
-
- mSpsPpsHeaderReceived = true;
-
- std::unique_ptr<C2StreamCsdInfo::output> csd =
- C2StreamCsdInfo::output::AllocUnique(s_encode_op.s_out_buf.u4_bytes, 0u);
- memcpy(csd->m.value, header, s_encode_op.s_out_buf.u4_bytes);
- work->worklets.front()->output.configUpdate.push_back(std::move(csd));
-
- DUMP_TO_FILE(
- mOutFile, csd->m.value, csd->flexCount());
- }
-
- if (mUpdateFlag) {
- if (mUpdateFlag & kUpdateBitrate) {
- setBitRate();
- }
- if (mUpdateFlag & kRequestKeyFrame) {
- setFrameType(IV_IDR_FRAME);
- }
- if (mUpdateFlag & kUpdateAIRMode) {
- setAirParams();
- // notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
- // OMX_IndexConfigAndroidIntraRefresh, NULL);
- }
- mUpdateFlag = 0;
- }
-
- if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- mSawInputEOS = true;
- }
-
- /* In normal mode, store inputBufferInfo and this will be returned
- when encoder consumes this input */
- // if (!mInputDataIsMeta && (inputBufferInfo != NULL)) {
- // for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
- // if (NULL == mInputBufferInfo[i]) {
- // mInputBufferInfo[i] = inputBufferInfo;
- // break;
- // }
- // }
- // }
- const C2GraphicView view =
- work->input.buffers[0]->data().graphicBlocks().front().map().get();
- if (view.error() != C2_OK) {
- ALOGE("graphic view map err = %d", view.error());
- return;
- }
-
- std::shared_ptr<C2LinearBlock> block;
-
- do {
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- // TODO: error handling, proper usage, etc.
- c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetch linear block err = %d", err);
- work->workletsProcessed = 1u;
- work->result = err;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error() != C2_OK) {
- ALOGE("write view map err = %d", wView.error());
- work->workletsProcessed = 1u;
- work->result = wView.error();
- return;
- }
-
- error = setEncodeArgs(
- &s_encode_ip, &s_encode_op, &view, wView.base(), wView.capacity(), timestamp);
- if (error != C2_OK) {
- mSignalledError = true;
- ALOGE("setEncodeArgs failed : %d", error);
- work->workletsProcessed = 1u;
- work->result = error;
- return;
- }
-
- // DUMP_TO_FILE(
- // mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
- // (mHeight * mStride * 3 / 2));
-
- GETTIME(&mTimeStart, NULL);
- /* Compute time elapsed between end of previous decode()
- * to start of current decode() */
- TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
- status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
-
- if (IV_SUCCESS != status) {
- if ((s_encode_op.u4_error_code & 0xFF) == IH264E_BITSTREAM_BUFFER_OVERFLOW) {
- // TODO: use IVE_CMD_CTL_GETBUFINFO for proper max input size?
- mOutBufferSize *= 2;
- continue;
- }
- ALOGE("Encode Frame failed = 0x%x\n",
- s_encode_op.u4_error_code);
- mSignalledError = true;
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
- return;
- }
- } while (IV_SUCCESS != status);
-
- // Hold input buffer reference
- mBuffers[s_encode_ip.s_inp_buf.apv_bufs[0]] = work->input.buffers[0];
-
- GETTIME(&mTimeEnd, NULL);
- /* Compute time taken for decode() */
- TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
-
- ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
- s_encode_op.s_out_buf.u4_bytes);
-
- void *freed = s_encode_op.s_inp_buf.apv_bufs[0];
- /* If encoder frees up an input buffer, mark it as free */
- if (freed != NULL) {
- if (mBuffers.count(freed) == 0u) {
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
- return;
- }
- // Release input buffer reference
- mBuffers.erase(freed);
-
- auto it = std::find_if(
- mConversionBuffersInUse.begin(), mConversionBuffersInUse.end(),
- [freed](const auto &elem) { return elem.get() == freed; });
- if (it != mConversionBuffersInUse.end()) {
- mFreeConversionBuffers.push_back(std::move(*it));
- mConversionBuffersInUse.erase(it);
- }
- }
-
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets.front()->output.ordinal.timestamp =
- ((uint64_t)s_encode_op.u4_timestamp_high << 32) | s_encode_op.u4_timestamp_low;
- work->worklets.front()->output.buffers.clear();
- std::shared_ptr<C2Buffer> buffer =
- createLinearBuffer(block, 0, s_encode_op.s_out_buf.u4_bytes);
- work->worklets.front()->output.buffers.push_back(buffer);
- work->workletsProcessed = 1u;
-
- if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) {
- buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
- 0u /* stream id */, C2PictureTypeKeyFrame));
- }
-
- if (s_encode_op.u4_is_last) {
- // outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
- mSawOutputEOS = true;
- } else {
- // outputBufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS;
- }
-}
-
-c2_status_t C2SoftAvcEnc::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- // TODO: use IVE_CMD_CTL_FLUSH?
- (void)drainMode;
- (void)pool;
- return C2_OK;
-}
-
-
-class C2SoftAvcEncFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAvcEnc(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftAvcEncFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftAvcEncFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.h b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.h
deleted file mode 100644
index a113436..0000000
--- a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright 2018 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 C2_SOFT_AVC_ENC_H__
-#define C2_SOFT_AVC_ENC_H__
-
-#include <map>
-
-#include <media/stagefright/foundation/ABase.h>
-#include <utils/Vector.h>
-
-#include <SimpleC2Component.h>
-
-namespace android {
-
-#define CODEC_MAX_CORES 4
-#define LEN_STATUS_BUFFER (10 * 1024)
-#define MAX_VBV_BUFF_SIZE (120 * 16384)
-#define MAX_NUM_IO_BUFS 3
-
-#define DEFAULT_MAX_REF_FRM 2
-#define DEFAULT_MAX_REORDER_FRM 0
-#define DEFAULT_QP_MIN 10
-#define DEFAULT_QP_MAX 40
-#define DEFAULT_MAX_BITRATE 20000000
-#define DEFAULT_MAX_SRCH_RANGE_X 256
-#define DEFAULT_MAX_SRCH_RANGE_Y 256
-#define DEFAULT_MAX_FRAMERATE 120000
-#define DEFAULT_NUM_CORES 1
-#define DEFAULT_NUM_CORES_PRE_ENC 0
-#define DEFAULT_FPS 30
-#define DEFAULT_ENC_SPEED IVE_NORMAL
-
-#define DEFAULT_MEM_REC_CNT 0
-#define DEFAULT_RECON_ENABLE 0
-#define DEFAULT_CHKSUM_ENABLE 0
-#define DEFAULT_START_FRM 0
-#define DEFAULT_NUM_FRMS 0xFFFFFFFF
-#define DEFAULT_INP_COLOR_FORMAT IV_YUV_420SP_VU
-#define DEFAULT_RECON_COLOR_FORMAT IV_YUV_420P
-#define DEFAULT_LOOPBACK 0
-#define DEFAULT_SRC_FRAME_RATE 30
-#define DEFAULT_TGT_FRAME_RATE 30
-#define DEFAULT_MAX_WD 1920
-#define DEFAULT_MAX_HT 1920
-#define DEFAULT_MAX_LEVEL 41
-#define DEFAULT_STRIDE 0
-#define DEFAULT_WD 1280
-#define DEFAULT_HT 720
-#define DEFAULT_PSNR_ENABLE 0
-#define DEFAULT_ME_SPEED 100
-#define DEFAULT_ENABLE_FAST_SAD 0
-#define DEFAULT_ENABLE_ALT_REF 0
-#define DEFAULT_RC_MODE IVE_RC_STORAGE
-#define DEFAULT_BITRATE 6000000
-#define DEFAULT_I_QP 22
-#define DEFAULT_I_QP_MAX DEFAULT_QP_MAX
-#define DEFAULT_I_QP_MIN DEFAULT_QP_MIN
-#define DEFAULT_P_QP 28
-#define DEFAULT_P_QP_MAX DEFAULT_QP_MAX
-#define DEFAULT_P_QP_MIN DEFAULT_QP_MIN
-#define DEFAULT_B_QP 22
-#define DEFAULT_B_QP_MAX DEFAULT_QP_MAX
-#define DEFAULT_B_QP_MIN DEFAULT_QP_MIN
-#define DEFAULT_AIR IVE_AIR_MODE_NONE
-#define DEFAULT_AIR_REFRESH_PERIOD 30
-#define DEFAULT_SRCH_RNG_X 64
-#define DEFAULT_SRCH_RNG_Y 48
-#define DEFAULT_I_INTERVAL 30
-#define DEFAULT_IDR_INTERVAL 1000
-#define DEFAULT_B_FRAMES 0
-#define DEFAULT_DISABLE_DEBLK_LEVEL 0
-#define DEFAULT_HPEL 1
-#define DEFAULT_QPEL 1
-#define DEFAULT_I4 1
-#define DEFAULT_EPROFILE IV_PROFILE_BASE
-#define DEFAULT_ENTROPY_MODE 0
-#define DEFAULT_SLICE_MODE IVE_SLICE_MODE_NONE
-#define DEFAULT_SLICE_PARAM 256
-#define DEFAULT_ARCH ARCH_ARM_A9Q
-#define DEFAULT_SOC SOC_GENERIC
-#define DEFAULT_INTRA4x4 0
-#define STRLENGTH 500
-#define DEFAULT_CONSTRAINED_INTRA 0
-
-#define MIN(a, b) ((a) < (b))? (a) : (b)
-#define MAX(a, b) ((a) > (b))? (a) : (b)
-#define ALIGN16(x) ((((x) + 15) >> 4) << 4)
-#define ALIGN128(x) ((((x) + 127) >> 7) << 7)
-#define ALIGN4096(x) ((((x) + 4095) >> 12) << 12)
-
-/** Used to remove warnings about unused parameters */
-#define UNUSED(x) ((void)(x))
-
-/** Get time */
-#define GETTIME(a, b) gettimeofday(a, b);
-
-/** Compute difference between start and end */
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
-#define ive_aligned_malloc(alignment, size) memalign(alignment, size)
-#define ive_aligned_free(buf) free(buf)
-
-struct C2SoftAvcEnc : public SimpleC2Component {
- C2SoftAvcEnc(const char *name, c2_node_id_t id);
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-protected:
- virtual ~C2SoftAvcEnc();
-
-private:
- enum {
- kUpdateBitrate = 1 << 0,
- kRequestKeyFrame = 1 << 1,
- kUpdateAIRMode = 1 << 2,
- };
-
- // OMX input buffer's timestamp and flags
- typedef struct {
- int64_t mTimeUs;
- int32_t mFlags;
- } InputBufferInfo;
-
- int32_t mStride;
-
- struct timeval mTimeStart; // Time at the start of decode()
- struct timeval mTimeEnd; // Time at the end of decode()
-
- int mUpdateFlag;
-
-#ifdef FILE_DUMP_ENABLE
- char mInFile[200];
- char mOutFile[200];
-#endif /* FILE_DUMP_ENABLE */
-
- IV_COLOR_FORMAT_T mIvVideoColorFormat;
-
- IV_PROFILE_T mAVCEncProfile;
- WORD32 mAVCEncLevel;
- bool mStarted;
- bool mSpsPpsHeaderReceived;
-
- bool mSawInputEOS;
- bool mSawOutputEOS;
- bool mSignalledError;
- bool mIntra4x4;
- bool mEnableFastSad;
- bool mEnableAltRef;
- bool mReconEnable;
- bool mPSNREnable;
- bool mEntropyMode;
- bool mConstrainedIntraFlag;
- IVE_SPEED_CONFIG mEncSpeed;
-
- iv_obj_t *mCodecCtx; // Codec context
- iv_mem_rec_t *mMemRecords; // Memory records requested by the codec
- size_t mNumMemRecords; // Number of memory records requested by codec
- size_t mNumCores; // Number of cores used by the codec
-
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mFramerate;
- uint32_t mBitrate;
- uint32_t mOutBufferSize;
- UWORD32 mHeaderGenerated;
- UWORD32 mBframes;
- IV_ARCH_T mArch;
- IVE_SLICE_MODE_T mSliceMode;
- UWORD32 mSliceParam;
- bool mHalfPelEnable;
- UWORD32 mIInterval;
- UWORD32 mIDRInterval;
- UWORD32 mDisableDeblkLevel;
- IVE_AIR_MODE_T mAIRMode;
- UWORD32 mAIRRefreshPeriod;
- std::map<const void *, std::shared_ptr<C2Buffer>> mBuffers;
- std::list<std::unique_ptr<uint8_t[]>> mFreeConversionBuffers;
- std::list<std::unique_ptr<uint8_t[]>> mConversionBuffersInUse;
-
- void initEncParams();
- c2_status_t initEncoder();
- c2_status_t releaseEncoder();
-
- c2_status_t setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type);
- c2_status_t setQp();
- c2_status_t setEncMode(IVE_ENC_MODE_T e_enc_mode);
- c2_status_t setDimensions();
- c2_status_t setNumCores();
- c2_status_t setFrameRate();
- c2_status_t setIpeParams();
- c2_status_t setBitRate();
- c2_status_t setAirParams();
- c2_status_t setMeParams();
- c2_status_t setGopParams();
- c2_status_t setProfileParams();
- c2_status_t setDeblockParams();
- c2_status_t setVbvParams();
- void logVersion();
- c2_status_t setEncodeArgs(
- ive_video_encode_ip_t *ps_encode_ip,
- ive_video_encode_op_t *ps_encode_op,
- const C2GraphicView *const input,
- uint8_t *base,
- uint32_t capacity,
- uint64_t timestamp);
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftAvcEnc);
-};
-
-#ifdef FILE_DUMP_ENABLE
-
-#define INPUT_DUMP_PATH "/sdcard/media/avce_input"
-#define INPUT_DUMP_EXT "yuv"
-#define OUTPUT_DUMP_PATH "/sdcard/media/avce_output"
-#define OUTPUT_DUMP_EXT "h264"
-
-#define GENERATE_FILE_NAMES() { \
- GETTIME(&mTimeStart, NULL); \
- strcpy(mInFile, ""); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
- INPUT_DUMP_EXT); \
- strcpy(mOutFile, ""); \
- sprintf(mOutFile, "%s_%ld.%ld.%s", OUTPUT_DUMP_PATH,\
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
- OUTPUT_DUMP_EXT); \
-}
-
-#define CREATE_DUMP_FILE(m_filename) { \
- FILE *fp = fopen(m_filename, "wb"); \
- if (fp != NULL) { \
- ALOGD("Opened file %s", m_filename); \
- fclose(fp); \
- } else { \
- ALOGD("Could not open file %s", m_filename); \
- } \
-}
-#define DUMP_TO_FILE(m_filename, m_buf, m_size) \
-{ \
- FILE *fp = fopen(m_filename, "ab"); \
- if (fp != NULL && m_buf != NULL) { \
- int i; \
- i = fwrite(m_buf, 1, m_size, fp); \
- ALOGD("fwrite ret %d to write %d", i, m_size); \
- if (i != (int)m_size) { \
- ALOGD("Error in fwrite, returned %d", i); \
- perror("Error in write to file"); \
- } \
- fclose(fp); \
- } else { \
- ALOGD("Could not write to file %s", m_filename);\
- if (fp != NULL) \
- fclose(fp); \
- } \
-}
-#else /* FILE_DUMP_ENABLE */
-#define INPUT_DUMP_PATH
-#define INPUT_DUMP_EXT
-#define OUTPUT_DUMP_PATH
-#define OUTPUT_DUMP_EXT
-#define GENERATE_FILE_NAMES()
-#define CREATE_DUMP_FILE(m_filename)
-#define DUMP_TO_FILE(m_filename, m_buf, m_size)
-#endif /* FILE_DUMP_ENABLE */
-
-} // namespace android
-
-#endif // C2_SOFT_AVC_ENC_H__
diff --git a/media/libstagefright/codecs/cmds/Android.bp b/media/libstagefright/codecs/cmds/Android.bp
deleted file mode 100644
index 6dba0a3..0000000
--- a/media/libstagefright/codecs/cmds/Android.bp
+++ /dev/null
@@ -1,41 +0,0 @@
-cc_binary {
- name: "codec2",
-
- srcs: [
- "codec2.cpp",
- ],
-
- include_dirs: [
- ],
-
- shared_libs: [
- "libbinder",
- "libcutils",
- "libgui",
- "liblog",
- "libmediaextractor",
- "libstagefright",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libui",
- "libutils",
- ],
-
- cflags: [
- "-Werror",
- "-Wall",
- "-std=c++14",
- ],
-
-// sanitize: {
-// cfi: true,
-// misc_undefined: [
-// "unsigned-integer-overflow",
-// "signed-integer-overflow",
-// ],
-// diag: {
-// cfi: true,
-// },
-// },
-}
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
deleted file mode 100644
index 295a5b0..0000000
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * 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.
- */
-
-#include <inttypes.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <thread>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "codec2"
-#include <media/stagefright/foundation/ADebug.h>
-
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <media/DataSource.h>
-#include <media/ICrypto.h>
-#include <media/IMediaHTTPService.h>
-#include <media/MediaExtractor.h>
-#include <media/MediaSource.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaExtractorFactory.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-#include <gui/GLConsumer.h>
-#include <gui/IProducerListener.h>
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-
-#include <util/C2ParamUtils.h>
-#include <C2AllocatorGralloc.h>
-#include <C2Buffer.h>
-#include <C2BufferPriv.h>
-#include <C2Component.h>
-#include <C2PlatformSupport.h>
-#include <C2Work.h>
-
-using namespace android;
-using namespace std::chrono_literals;
-
-namespace {
-
-class LinearBuffer : public C2Buffer {
-public:
- explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block)
- : C2Buffer({ block->share(block->offset(), block->size(), ::C2Fence()) }) {}
-};
-
-class Listener;
-
-class SimplePlayer {
-public:
- SimplePlayer();
- ~SimplePlayer();
-
- void onWorkDone(std::weak_ptr<C2Component> component,
- std::list<std::unique_ptr<C2Work>> workItems);
- void onTripped(std::weak_ptr<C2Component> component,
- std::vector<std::shared_ptr<C2SettingResult>> settingResult);
- void onError(std::weak_ptr<C2Component> component, uint32_t errorCode);
-
- void play(const sp<IMediaSource> &source);
-
-private:
- typedef std::unique_lock<std::mutex> ULock;
-
- std::shared_ptr<Listener> mListener;
- std::shared_ptr<C2Component> mComponent;
-
- sp<IProducerListener> mProducerListener;
-
- std::atomic_int mLinearPoolId;
-
- std::shared_ptr<C2Allocator> mAllocIon;
- std::shared_ptr<C2BlockPool> mLinearPool;
-
- std::mutex mQueueLock;
- std::condition_variable mQueueCondition;
- std::list<std::unique_ptr<C2Work>> mWorkQueue;
-
- std::mutex mProcessedLock;
- std::condition_variable mProcessedCondition;
- std::list<std::unique_ptr<C2Work>> mProcessedWork;
-
- sp<Surface> mSurface;
- sp<SurfaceComposerClient> mComposerClient;
- sp<SurfaceControl> mControl;
-};
-
-class Listener : public C2Component::Listener {
-public:
- explicit Listener(SimplePlayer *thiz) : mThis(thiz) {}
- virtual ~Listener() = default;
-
- virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
- std::list<std::unique_ptr<C2Work>> workItems) override {
- mThis->onWorkDone(component, std::move(workItems));
- }
-
- virtual void onTripped_nb(std::weak_ptr<C2Component> component,
- std::vector<std::shared_ptr<C2SettingResult>> settingResult) override {
- mThis->onTripped(component, settingResult);
- }
-
- virtual void onError_nb(std::weak_ptr<C2Component> component,
- uint32_t errorCode) override {
- mThis->onError(component, errorCode);
- }
-
-private:
- SimplePlayer * const mThis;
-};
-
-
-SimplePlayer::SimplePlayer()
- : mListener(new Listener(this)),
- mProducerListener(new DummyProducerListener),
- mLinearPoolId(C2BlockPool::PLATFORM_START),
- mComposerClient(new SurfaceComposerClient) {
- CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
-
- std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
- CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
- mLinearPool = std::make_shared<C2PooledBlockPool>(mAllocIon, mLinearPoolId++);
-
- mControl = mComposerClient->createSurface(
- String8("A Surface"),
- 1280,
- 800,
- HAL_PIXEL_FORMAT_YV12);
- //PIXEL_FORMAT_RGB_565);
-
- CHECK(mControl != NULL);
- CHECK(mControl->isValid());
-
- SurfaceComposerClient::Transaction{}
- .setLayer(mControl, INT_MAX)
- .show(mControl)
- .apply();
-
- mSurface = mControl->getSurface();
- CHECK(mSurface != NULL);
- mSurface->connect(NATIVE_WINDOW_API_CPU, mProducerListener);
-}
-
-SimplePlayer::~SimplePlayer() {
- mComposerClient->dispose();
-}
-
-void SimplePlayer::onWorkDone(
- std::weak_ptr<C2Component> component, std::list<std::unique_ptr<C2Work>> workItems) {
- ALOGV("SimplePlayer::onWorkDone");
- (void) component;
- ULock l(mProcessedLock);
- for (auto & item : workItems) {
- mProcessedWork.push_back(std::move(item));
- }
- mProcessedCondition.notify_all();
-}
-
-void SimplePlayer::onTripped(
- std::weak_ptr<C2Component> component,
- std::vector<std::shared_ptr<C2SettingResult>> settingResult) {
- (void) component;
- (void) settingResult;
- // TODO
-}
-
-void SimplePlayer::onError(std::weak_ptr<C2Component> component, uint32_t errorCode) {
- (void) component;
- (void) errorCode;
- // TODO
-}
-
-void SimplePlayer::play(const sp<IMediaSource> &source) {
- ALOGV("SimplePlayer::play");
- sp<AMessage> format;
- (void) convertMetaDataToMessage(source->getFormat(), &format);
-
- sp<ABuffer> csd0, csd1;
- format->findBuffer("csd-0", &csd0);
- format->findBuffer("csd-1", &csd1);
-
- status_t err = source->start();
-
- if (err != OK) {
- fprintf(stderr, "source returned error %d (0x%08x)\n", err, err);
- return;
- }
-
- std::shared_ptr<C2ComponentStore> store = GetCodec2PlatformComponentStore();
- std::shared_ptr<C2Component> component;
- (void)store->createComponent("c2.google.avc.decoder", &component);
-
- (void)component->setListener_vb(mListener, C2_DONT_BLOCK);
- std::unique_ptr<C2PortBlockPoolsTuning::output> pools =
- C2PortBlockPoolsTuning::output::AllocUnique({ (uint64_t)C2BlockPool::BASIC_GRAPHIC });
- std::vector<std::unique_ptr<C2SettingResult>> result;
- (void)component->intf()->config_vb({pools.get()}, C2_DONT_BLOCK, &result);
- component->start();
-
- for (int i = 0; i < 8; ++i) {
- mWorkQueue.emplace_back(new C2Work);
- }
-
- std::atomic_bool running(true);
- std::thread surfaceThread([this, &running]() {
- const sp<IGraphicBufferProducer> &igbp = mSurface->getIGraphicBufferProducer();
- while (running) {
- std::unique_ptr<C2Work> work;
- {
- ULock l(mProcessedLock);
- if (mProcessedWork.empty()) {
- mProcessedCondition.wait_for(l, 100ms);
- if (mProcessedWork.empty()) {
- continue;
- }
- }
- work.swap(mProcessedWork.front());
- mProcessedWork.pop_front();
- }
- int slot;
- sp<Fence> fence;
- ALOGV("Render: Frame #%lld", work->worklets.front()->output.ordinal.frameIndex.peekll());
- const std::shared_ptr<C2Buffer> &output = work->worklets.front()->output.buffers[0];
- if (output) {
- const C2ConstGraphicBlock block = output->data().graphicBlocks().front();
- native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(block.handle());
- sp<GraphicBuffer> buffer(new GraphicBuffer(
- grallocHandle,
- GraphicBuffer::CLONE_HANDLE,
- block.width(),
- block.height(),
- HAL_PIXEL_FORMAT_YV12,
- 1,
- (uint64_t)GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
- block.width()));
- native_handle_delete(grallocHandle);
-
- status_t err = igbp->attachBuffer(&slot, buffer);
-
- IGraphicBufferProducer::QueueBufferInput qbi(
- (work->worklets.front()->output.ordinal.timestamp * 1000ll).peekll(),
- false,
- HAL_DATASPACE_UNKNOWN,
- Rect(block.width(), block.height()),
- NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
- 0,
- Fence::NO_FENCE,
- 0);
- IGraphicBufferProducer::QueueBufferOutput qbo;
- err = igbp->queueBuffer(slot, qbi, &qbo);
- }
-
- work->input.buffers.clear();
- work->worklets.clear();
-
- ULock l(mQueueLock);
- mWorkQueue.push_back(std::move(work));
- mQueueCondition.notify_all();
- }
- ALOGV("render loop finished");
- });
-
- long numFrames = 0;
- mLinearPool.reset(new C2PooledBlockPool(mAllocIon, mLinearPoolId++));
-
- for (;;) {
- size_t size = 0u;
- void *data = nullptr;
- int64_t timestamp = 0u;
- MediaBufferBase *buffer = nullptr;
- sp<ABuffer> csd;
- if (csd0 != nullptr) {
- csd = csd0;
- csd0 = nullptr;
- } else if (csd1 != nullptr) {
- csd = csd1;
- csd1 = nullptr;
- } else {
- status_t err = source->read(&buffer);
- if (err != OK) {
- CHECK(buffer == NULL);
-
- if (err == INFO_FORMAT_CHANGED) {
- continue;
- }
-
- break;
- }
- MetaDataBase &meta = buffer->meta_data();
- CHECK(meta.findInt64(kKeyTime, ×tamp));
-
- size = buffer->size();
- data = buffer->data();
- }
-
- if (csd != nullptr) {
- size = csd->size();
- data = csd->data();
- }
-
- // Prepare C2Work
-
- std::unique_ptr<C2Work> work;
- while (!work) {
- ULock l(mQueueLock);
- if (!mWorkQueue.empty()) {
- work.swap(mWorkQueue.front());
- mWorkQueue.pop_front();
- } else {
- mQueueCondition.wait_for(l, 100ms);
- }
- }
- work->input.flags = (C2FrameData::flags_t)0;
- work->input.ordinal.timestamp = timestamp;
- work->input.ordinal.frameIndex = numFrames;
-
- std::shared_ptr<C2LinearBlock> block;
- mLinearPool->fetchLinearBlock(
- size,
- { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
- &block);
- C2WriteView view = block->map().get();
- if (view.error() != C2_OK) {
- fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
- break;
- }
- memcpy(view.base(), data, size);
-
- work->input.buffers.clear();
- work->input.buffers.emplace_back(new LinearBuffer(block));
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
-
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
-
- ALOGV("Frame #%ld size = %zu", numFrames, size);
- // DO THE DECODING
- component->queue_nb(&items);
-
- if (buffer) {
- buffer->release();
- buffer = NULL;
- }
-
- ++numFrames;
- }
- ALOGV("main loop finished");
- source->stop();
- running.store(false);
- surfaceThread.join();
-
- component->release();
- printf("\n");
-}
-
-} // namespace
-
-static void usage(const char *me) {
- fprintf(stderr, "usage: %s [options] [input_filename]\n", me);
- fprintf(stderr, " -h(elp)\n");
-}
-
-int main(int argc, char **argv) {
- android::ProcessState::self()->startThreadPool();
-
- int res;
- while ((res = getopt(argc, argv, "h")) >= 0) {
- switch (res) {
- case 'h':
- default:
- {
- usage(argv[0]);
- exit(1);
- break;
- }
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc < 1) {
- fprintf(stderr, "No input file specified\n");
- return 1;
- }
-
- status_t err = OK;
- SimplePlayer player;
-
- for (int k = 0; k < argc && err == OK; ++k) {
- const char *filename = argv[k];
-
- sp<DataSource> dataSource =
- DataSourceFactory::CreateFromURI(NULL /* httpService */, filename);
-
- if (strncasecmp(filename, "sine:", 5) && dataSource == NULL) {
- fprintf(stderr, "Unable to create data source.\n");
- return 1;
- }
-
- Vector<sp<IMediaSource> > mediaSources;
- sp<IMediaSource> mediaSource;
-
- sp<IMediaExtractor> extractor = MediaExtractorFactory::Create(dataSource);
-
- if (extractor == NULL) {
- fprintf(stderr, "could not create extractor.\n");
- return -1;
- }
-
- sp<MetaData> meta = extractor->getMetaData();
-
- if (meta != NULL) {
- const char *mime;
- if (!meta->findCString(kKeyMIMEType, &mime)) {
- fprintf(stderr, "extractor did not provide MIME type.\n");
- return -1;
- }
- }
-
- size_t numTracks = extractor->countTracks();
-
- size_t i;
- for (i = 0; i < numTracks; ++i) {
- meta = extractor->getTrackMetaData(
- i, MediaExtractor::kIncludeExtensiveMetaData);
-
- if (meta == NULL) {
- break;
- }
- const char *mime;
- meta->findCString(kKeyMIMEType, &mime);
-
- // TODO: allowing AVC only for the time being
- if (!strncasecmp(mime, "video/avc", 9)) {
- break;
- }
-
- meta = NULL;
- }
-
- if (meta == NULL) {
- fprintf(stderr, "No AVC track found.\n");
- return -1;
- }
-
- mediaSource = extractor->getTrack(i);
- if (mediaSource == nullptr) {
- fprintf(stderr, "skip NULL track %zu, total tracks %zu.\n", i, numTracks);
- return -1;
- }
-
- player.play(mediaSource);
- }
-
- return 0;
-}
diff --git a/media/libstagefright/codecs/flac/dec/Android.bp b/media/libstagefright/codecs/flac/dec/Android.bp
index 68fdd15..9af086b 100644
--- a/media/libstagefright/codecs/flac/dec/Android.bp
+++ b/media/libstagefright/codecs/flac/dec/Android.bp
@@ -1,48 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2flacdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: [
- "C2SoftFlacDecoder.cpp",
- ],
-
- include_dirs: [
- "external/flac/include",
- "frameworks/av/media/libstagefright/flac/dec",
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_flacdec",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-}
-
-
-cc_library_shared {
name: "libstagefright_soft_flacdec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/flac/dec/C2SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/C2SoftFlacDecoder.cpp
deleted file mode 100644
index 87138af..0000000
--- a/media/libstagefright/codecs/flac/dec/C2SoftFlacDecoder.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftFlacDecoder"
-#include <utils/Log.h>
-
-#include "C2SoftFlacDecoder.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.flac.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_FLAC)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftFlacDecoder::C2SoftFlacDecoder(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mFLACDecoder(nullptr) {
-}
-
-C2SoftFlacDecoder::~C2SoftFlacDecoder() {
- delete mFLACDecoder;
-}
-
-c2_status_t C2SoftFlacDecoder::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_NO_MEMORY;
-}
-
-c2_status_t C2SoftFlacDecoder::onStop() {
- if (mFLACDecoder) mFLACDecoder->flush();
- memset(&mStreamInfo, 0, sizeof(mStreamInfo));
- mHasStreamInfo = false;
- mSignalledError = false;
- mSignalledOutputEos = false;
- mInputBufferCount = 0;
- return C2_OK;
-}
-
-void C2SoftFlacDecoder::onReset() {
- (void)onStop();
-}
-
-void C2SoftFlacDecoder::onRelease() {
-}
-
-c2_status_t C2SoftFlacDecoder::onFlush_sm() {
- return onStop();
-}
-
-status_t C2SoftFlacDecoder::initDecoder() {
- if (mFLACDecoder) {
- delete mFLACDecoder;
- }
- mFLACDecoder = FLACDecoder::Create();
- if (!mFLACDecoder) {
- ALOGE("initDecoder: failed to create FLACDecoder");
- mSignalledError = true;
- return NO_MEMORY;
- }
-
- memset(&mStreamInfo, 0, sizeof(mStreamInfo));
- mHasStreamInfo = false;
- mSignalledError = false;
- mSignalledOutputEos = false;
- mInputBufferCount = 0;
-
- return OK;
-}
-
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-// (TODO) add multiframe support, in plugin and FLACDecoder.cpp
-void C2SoftFlacDecoder::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
- bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
- bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
-
- if (inSize == 0) {
- fillEmptyWork(work);
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
-
- if (mInputBufferCount == 0 && !codecConfig) {
- ALOGV("First frame has to include configuration, forcing config");
- codecConfig = true;
- }
-
- uint8_t *input = const_cast<uint8_t *>(rView.data() + inOffset);
- if (codecConfig) {
- status_t decoderErr = mFLACDecoder->parseMetadata(input, inSize);
- if (decoderErr != OK && decoderErr != WOULD_BLOCK) {
- ALOGE("process: FLACDecoder parseMetaData returns error %d", decoderErr);
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
-
- mInputBufferCount++;
- fillEmptyWork(work);
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
-
- if (decoderErr == WOULD_BLOCK) {
- ALOGV("process: parseMetadata is Blocking, Continue %d", decoderErr);
- } else {
- mStreamInfo = mFLACDecoder->getStreamInfo();
- if (mStreamInfo.max_blocksize && mStreamInfo.channels)
- mHasStreamInfo = true;
- ALOGD("process: decoder configuration : %d Hz, %d channels, %d samples,"
- " %d block size", mStreamInfo.sample_rate, mStreamInfo.channels,
- (int)mStreamInfo.total_samples, mStreamInfo.max_blocksize);
- }
- return;
- }
-
- size_t outSize;
- if (mHasStreamInfo)
- outSize = mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(short);
- else
- outSize = kMaxBlockSize * FLACDecoder::kMaxChannels * sizeof(short);
-
- std::shared_ptr<C2LinearBlock> block;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(outSize, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- short *output = reinterpret_cast<short *>(wView.data());
- status_t decoderErr = mFLACDecoder->decodeOneFrame(
- input, inSize, output, &outSize);
- if (decoderErr != OK) {
- ALOGE("process: FLACDecoder decodeOneFrame returns error %d", decoderErr);
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
-
- mInputBufferCount++;
- ALOGV("out buffer attr. size %zu", outSize);
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, 0, outSize));
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-c2_status_t C2SoftFlacDecoder::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- if (mFLACDecoder) mFLACDecoder->flush();
-
- return C2_OK;
-}
-
-class C2SoftFlacDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftFlacDecoder(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftFlacDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftFlacDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/flac/dec/C2SoftFlacDecoder.h b/media/libstagefright/codecs/flac/dec/C2SoftFlacDecoder.h
deleted file mode 100644
index 43d913b..0000000
--- a/media/libstagefright/codecs/flac/dec/C2SoftFlacDecoder.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_FLAC_DECODER_H_
-#define C2_SOFT_FLAC_DECODER_H_
-
-#include <SimpleC2Component.h>
-
-#include "FLACDecoder.h"
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-
-struct C2SoftFlacDecoder : public SimpleC2Component {
- C2SoftFlacDecoder(const char *name, c2_node_id_t id);
- virtual ~C2SoftFlacDecoder();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- enum {
- kMaxBlockSize = 4096
- };
-
- FLACDecoder *mFLACDecoder;
- FLAC__StreamMetadata_StreamInfo mStreamInfo;
- bool mSignalledError;
- bool mSignalledOutputEos;
- bool mHasStreamInfo;
- size_t mInputBufferCount;
-
- status_t initDecoder();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftFlacDecoder);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_FLAC_DECODER_H_
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index bb705dd..46b974d 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -1,43 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2flacenc",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftFlacEnc.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libFLAC",
- ],
-
- shared_libs: [
- "liblog",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libutils",
- ],
-}
-
-cc_library_shared {
srcs: ["SoftFlacEncoder.cpp"],
diff --git a/media/libstagefright/codecs/flac/enc/C2SoftFlacEnc.cpp b/media/libstagefright/codecs/flac/enc/C2SoftFlacEnc.cpp
deleted file mode 100644
index f94ed49..0000000
--- a/media/libstagefright/codecs/flac/enc/C2SoftFlacEnc.cpp
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftFlacEnc"
-#include <utils/Log.h>
-
-#include "C2SoftFlacEnc.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.flac.encoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_FLAC)
- .build();
-}
-
-C2SoftFlacEnc::C2SoftFlacEnc(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mFlacStreamEncoder(nullptr),
- mInputBufferPcm32(nullptr) {
-}
-
-C2SoftFlacEnc::~C2SoftFlacEnc() {
- onRelease();
-}
-
-c2_status_t C2SoftFlacEnc::onInit() {
- mFlacStreamEncoder = FLAC__stream_encoder_new();
- if (!mFlacStreamEncoder) return C2_CORRUPTED;
-
- mInputBufferPcm32 = (FLAC__int32*) malloc(
- kInBlockSize * kMaxNumChannels * sizeof(FLAC__int32));
- if (!mInputBufferPcm32) return C2_NO_MEMORY;
-
- mSignalledError = false;
- mSignalledOutputEos = false;
- mNumChannels = 1;
- mSampleRate = 44100;
- mCompressionLevel = FLAC_COMPRESSION_LEVEL_DEFAULT;
- mIsFirstFrame = true;
- mAnchorTimeStamp = 0ull;
- mProcessedSamples = 0u;
- mEncoderWriteData = false;
- mEncoderReturnedNbBytes = 0;
-#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
- mHeaderOffset = 0;
- mWroteHeader = false;
-#endif
-
- status_t err = configureEncoder();
- return err == OK ? C2_OK : C2_CORRUPTED;
-}
-
-void C2SoftFlacEnc::onRelease() {
- if (mFlacStreamEncoder) {
- FLAC__stream_encoder_delete(mFlacStreamEncoder);
- mFlacStreamEncoder = nullptr;
- }
-
- if (mInputBufferPcm32) {
- free(mInputBufferPcm32);
- mInputBufferPcm32 = nullptr;
- }
-}
-
-void C2SoftFlacEnc::onReset() {
- mNumChannels = 1;
- mSampleRate = 44100;
- mCompressionLevel = FLAC_COMPRESSION_LEVEL_DEFAULT;
- (void) onStop();
-}
-
-c2_status_t C2SoftFlacEnc::onStop() {
- mSignalledError = false;
- mSignalledOutputEos = false;
- mIsFirstFrame = true;
- mAnchorTimeStamp = 0ull;
- mProcessedSamples = 0u;
- mEncoderWriteData = false;
- mEncoderReturnedNbBytes = 0;
-#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
- mHeaderOffset = 0;
- mWroteHeader = false;
-#endif
-
- c2_status_t status = drain(DRAIN_COMPONENT_NO_EOS, nullptr);
- if (C2_OK != status) return status;
-
- status_t err = configureEncoder();
- if (err != OK) mSignalledError = true;
- return C2_OK;
-}
-
-c2_status_t C2SoftFlacEnc::onFlush_sm() {
- return onStop();
-}
-
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-void C2SoftFlacEnc::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
- inSize, (int)work->input.ordinal.timestamp.peeku(),
- (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
- if (mIsFirstFrame && inSize) {
- mAnchorTimeStamp = work->input.ordinal.timestamp.peekull();
- mIsFirstFrame = false;
- }
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / mSampleRate;
-
- size_t outCapacity = inSize;
- outCapacity += mBlockSize * mNumChannels * sizeof(int16_t);
-#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
- outCapacity += FLAC_HEADER_SIZE;
-#endif
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &mOutputBlock);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = mOutputBlock->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- mEncoderWriteData = true;
- mEncoderReturnedNbBytes = 0;
- size_t inPos = 0;
- const uint8_t *inPtr = rView.data() + inOffset;
- while (inPos < inSize) {
- size_t processSize = MIN(kInBlockSize * mNumChannels * sizeof(int16_t), (inSize - inPos));
- const unsigned nbInputFrames = processSize / (mNumChannels * sizeof(int16_t));
- const unsigned nbInputSamples = processSize / sizeof(int16_t);
- const int16_t *pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
- ALOGV("about to encode %zu bytes", processSize);
-
- for (unsigned i = 0; i < nbInputSamples; i++) {
- mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
- }
-
- FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
- mFlacStreamEncoder, mInputBufferPcm32, nbInputFrames);
- if (!ok) {
- ALOGE("error encountered during encoding");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- mOutputBlock.reset();
- return;
- }
- inPos += processSize;
- }
- if (eos && !drain(DRAIN_COMPONENT_WITH_EOS, pool)) {
- ALOGE("error encountered during encoding");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- mOutputBlock.reset();
- return;
- }
- fillEmptyWork(work);
- if (mEncoderReturnedNbBytes != 0) {
- std::shared_ptr<C2Buffer> buffer = createLinearBuffer(std::move(mOutputBlock), 0, mEncoderReturnedNbBytes);
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
- } else {
- ALOGV("encoder process_interleaved returned without data to write");
- }
- mOutputBlock = nullptr;
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- mEncoderWriteData = false;
- mEncoderReturnedNbBytes = 0;
-}
-
-FLAC__StreamEncoderWriteStatus C2SoftFlacEnc::onEncodedFlacAvailable(
- const FLAC__byte buffer[], size_t bytes, unsigned samples,
- unsigned current_frame) {
- (void) current_frame;
- ALOGV("%s (bytes=%zu, samples=%u, curr_frame=%u)", __func__, bytes, samples,
- current_frame);
-
-#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
- if (samples == 0) {
- ALOGI("saving %zu bytes of header", bytes);
- memcpy(mHeader + mHeaderOffset, buffer, bytes);
- mHeaderOffset += bytes;// will contain header size when finished receiving header
- return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
- }
-#endif
-
- if ((samples == 0) || !mEncoderWriteData) {
- // called by the encoder because there's header data to save, but it's not the role
- // of this component (unless WRITE_FLAC_HEADER_IN_FIRST_BUFFER is defined)
- ALOGV("ignoring %zu bytes of header data (samples=%d)", bytes, samples);
- return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
- }
-
- // write encoded data
- C2WriteView wView = mOutputBlock->map().get();
- uint8_t* outData = wView.data();
-#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
- if (!mWroteHeader) {
- ALOGI("writing %d bytes of header on output", mHeaderOffset);
- memcpy(outData + mEncoderReturnedNbBytes, mHeader, mHeaderOffset);
- mEncoderReturnedNbBytes += mHeaderOffset;
- mWroteHeader = true;
- }
-#endif
- ALOGV("writing %zu bytes of encoded data on output", bytes);
- // increment mProcessedSamples to maintain audio synchronization during
- // play back
- mProcessedSamples += samples;
- if (bytes + mEncoderReturnedNbBytes > mOutputBlock->capacity()) {
- ALOGE("not enough space left to write encoded data, dropping %zu bytes", bytes);
- // a fatal error would stop the encoding
- return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
- }
- memcpy(outData + mEncoderReturnedNbBytes, buffer, bytes);
- mEncoderReturnedNbBytes += bytes;
- return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-
-status_t C2SoftFlacEnc::configureEncoder() {
- ALOGV("%s numChannel=%d, sampleRate=%d", __func__, mNumChannels, mSampleRate);
-
- if (mSignalledError || !mFlacStreamEncoder) {
- ALOGE("can't configure encoder: no encoder or invalid state");
- return UNKNOWN_ERROR;
- }
-
- FLAC__bool ok = true;
- ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
- ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
- ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
- ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, mCompressionLevel);
- ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
- if (!ok) {
- ALOGE("unknown error when configuring encoder");
- return UNKNOWN_ERROR;
- }
-
- ok &= FLAC__STREAM_ENCODER_INIT_STATUS_OK ==
- FLAC__stream_encoder_init_stream(mFlacStreamEncoder,
- flacEncoderWriteCallback /*write_callback*/,
- nullptr /*seek_callback*/,
- nullptr /*tell_callback*/,
- nullptr /*metadata_callback*/,
- (void *) this /*client_data*/);
-
- if (!ok) {
- ALOGE("unknown error when configuring encoder");
- return UNKNOWN_ERROR;
- }
-
- mBlockSize = FLAC__stream_encoder_get_blocksize(mFlacStreamEncoder);
-
- ALOGV("encoder successfully configured");
- return OK;
-}
-
-FLAC__StreamEncoderWriteStatus C2SoftFlacEnc::flacEncoderWriteCallback(
- const FLAC__StreamEncoder *,
- const FLAC__byte buffer[],
- size_t bytes,
- unsigned samples,
- unsigned current_frame,
- void *client_data) {
- return ((C2SoftFlacEnc*) client_data)->onEncodedFlacAvailable(
- buffer, bytes, samples, current_frame);
-}
-
-c2_status_t C2SoftFlacEnc::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- switch (drainMode) {
- case NO_DRAIN:
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- case DRAIN_CHAIN:
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- case DRAIN_COMPONENT_WITH_EOS:
- // TODO: This flag is not being sent back to the client
- // because there are no items in PendingWork queue as all the
- // inputs are being sent back with emptywork or valid encoded data
- // mSignalledOutputEos = true;
- case DRAIN_COMPONENT_NO_EOS:
- break;
- default:
- return C2_BAD_VALUE;
- }
- FLAC__bool ok = FLAC__stream_encoder_finish(mFlacStreamEncoder);
- if (!ok) return C2_CORRUPTED;
- mIsFirstFrame = true;
- mAnchorTimeStamp = 0ull;
- mProcessedSamples = 0u;
-
- return C2_OK;
-}
-
-class C2SoftFlacEncFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftFlacEnc(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftFlacEncFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftFlacEncFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/flac/enc/C2SoftFlacEnc.h b/media/libstagefright/codecs/flac/enc/C2SoftFlacEnc.h
deleted file mode 100644
index cc8cb86..0000000
--- a/media/libstagefright/codecs/flac/enc/C2SoftFlacEnc.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_FLAC_ENC_H_
-#define C2_SOFT_FLAC_ENC_H_
-
-#include <SimpleC2Component.h>
-
-#include "FLAC/stream_encoder.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-
-// use this symbol to have the first output buffer start with FLAC frame header so a dump of
-// all the output buffers can be opened as a .flac file
-//#define WRITE_FLAC_HEADER_IN_FIRST_BUFFER
-
-#define FLAC_COMPRESSION_LEVEL_MIN 0
-#define FLAC_COMPRESSION_LEVEL_DEFAULT 5
-#define FLAC_COMPRESSION_LEVEL_MAX 8
-
-#define FLAC_HEADER_SIZE 128
-
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
-namespace android {
-
-class C2SoftFlacEnc : public SimpleC2Component {
-public:
- C2SoftFlacEnc(const char *name, c2_node_id_t id);
- virtual ~C2SoftFlacEnc();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- status_t configureEncoder();
- static FLAC__StreamEncoderWriteStatus flacEncoderWriteCallback(
- const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[],
- size_t bytes, unsigned samples, unsigned current_frame,
- void *client_data);
- FLAC__StreamEncoderWriteStatus onEncodedFlacAvailable(
- const FLAC__byte buffer[], size_t bytes, unsigned samples,
- unsigned current_frame);
-
- const unsigned int kInBlockSize = 1152;
- const unsigned int kMaxNumChannels = 2;
- FLAC__StreamEncoder* mFlacStreamEncoder;
- FLAC__int32* mInputBufferPcm32;
- std::shared_ptr<C2LinearBlock> mOutputBlock;
- bool mSignalledError;
- bool mSignalledOutputEos;
- uint32_t mNumChannels;
- uint32_t mSampleRate;
- uint32_t mCompressionLevel;
- uint32_t mBlockSize;
- bool mIsFirstFrame;
- uint64_t mAnchorTimeStamp;
- uint64_t mProcessedSamples;
- // should the data received by the callback be written to the output port
- bool mEncoderWriteData;
- size_t mEncoderReturnedNbBytes;
-#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
- unsigned mHeaderOffset;
- bool mWroteHeader;
- char mHeader[FLAC_HEADER_SIZE];
-#endif
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftFlacEnc);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_FLAC_ENC_H_
diff --git a/media/libstagefright/codecs/g711/dec/Android.bp b/media/libstagefright/codecs/g711/dec/Android.bp
index 58a0a4d..3d97d8c 100644
--- a/media/libstagefright/codecs/g711/dec/Android.bp
+++ b/media/libstagefright/codecs/g711/dec/Android.bp
@@ -1,79 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2g711alawdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: [
- "C2SoftG711.cpp",
- ],
-
- cflags: [
- "-Werror",
- "-Wall",
- "-DALAW",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-}
-
-cc_library_shared {
- name: "libstagefright_soft_c2g711mlawdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: [
- "C2SoftG711.cpp",
- ],
-
- cflags: [
- "-Werror",
- "-Wall",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-}
-
-cc_library_shared {
name: "libstagefright_soft_g711dec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
deleted file mode 100644
index 1049420..0000000
--- a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftG711"
-#include <utils/Log.h>
-
-#include "C2SoftG711.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-#ifdef ALAW
-constexpr char kComponentName[] = "c2.google.g711.alaw.decoder";
-#else
-constexpr char kComponentName[] = "c2.google.g711.mlaw.decoder";
-#endif
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(
-#ifdef ALAW
- MEDIA_MIMETYPE_AUDIO_G711_ALAW
-#else
- MEDIA_MIMETYPE_AUDIO_G711_MLAW
-#endif
- )
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-
-C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)) {
-}
-
-C2SoftG711::~C2SoftG711() {
- onRelease();
-}
-
-c2_status_t C2SoftG711::onInit() {
- mSignalledOutputEos = false;
- return C2_OK;
-}
-
-c2_status_t C2SoftG711::onStop() {
- mSignalledOutputEos = false;
- return C2_OK;
-}
-
-void C2SoftG711::onReset() {
- (void)onStop();
-}
-
-void C2SoftG711::onRelease() {
-}
-
-c2_status_t C2SoftG711::onFlush_sm() {
- return onStop();
-}
-
-void C2SoftG711::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer =
- work->input.buffers[0]->data().linearBlocks().front();
- C2ReadView rView = inBuffer.map().get();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- int outSize = inSize * sizeof(int16_t);
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
- bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
-
- if (inSize == 0) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
-
- uint8_t *inputptr = const_cast<uint8_t *>(rView.data() + inOffset);
-
- std::shared_ptr<C2LinearBlock> block;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(outSize, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return;
- }
- int16_t *outputptr = reinterpret_cast<int16_t *>(wView.data());
-
-#ifdef ALAW
- DecodeALaw(outputptr, inputptr, inSize);
-#else
- DecodeMLaw(outputptr, inputptr, inSize);
-#endif
-
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block));
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-c2_status_t C2SoftG711::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- return C2_OK;
-}
-
-#ifdef ALAW
-void C2SoftG711::DecodeALaw(
- int16_t *out, const uint8_t *in, size_t inSize) {
- while (inSize > 0) {
- inSize--;
- int32_t x = *in++;
-
- int32_t ix = x ^ 0x55;
- ix &= 0x7f;
-
- int32_t iexp = ix >> 4;
- int32_t mant = ix & 0x0f;
-
- if (iexp > 0) {
- mant += 16;
- }
-
- mant = (mant << 4) + 8;
-
- if (iexp > 1) {
- mant = mant << (iexp - 1);
- }
-
- *out++ = (x > 127) ? mant : -mant;
- }
-}
-#else
-void C2SoftG711::DecodeMLaw(
- int16_t *out, const uint8_t *in, size_t inSize) {
- while (inSize > 0) {
- inSize--;
- int32_t x = *in++;
-
- int32_t mantissa = ~x;
- int32_t exponent = (mantissa >> 4) & 7;
- int32_t segment = exponent + 1;
- mantissa &= 0x0f;
-
- int32_t step = 4 << segment;
-
- int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
-
- *out++ = (x < 0x80) ? -abs : abs;
- }
-}
-#endif
-
-class C2SoftG711DecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftG711(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftG711DecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftG711DecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/g711/dec/C2SoftG711.h b/media/libstagefright/codecs/g711/dec/C2SoftG711.h
deleted file mode 100644
index eed38c9..0000000
--- a/media/libstagefright/codecs/g711/dec/C2SoftG711.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_G711_H_
-#define C2_SOFT_G711_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-
-struct C2SoftG711 : public SimpleC2Component {
- C2SoftG711(const char *name, c2_node_id_t id);
- virtual ~C2SoftG711();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-private:
- bool mSignalledOutputEos;
-
-#ifdef ALAW
- void DecodeALaw(int16_t *out, const uint8_t *in, size_t inSize);
-#else
- void DecodeMLaw(int16_t *out, const uint8_t *in, size_t inSize);
-#endif
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftG711);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_G711_H_
diff --git a/media/libstagefright/codecs/gsm/dec/Android.bp b/media/libstagefright/codecs/gsm/dec/Android.bp
index c057d8a..1c3208b 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.bp
+++ b/media/libstagefright/codecs/gsm/dec/Android.bp
@@ -1,45 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2gsmdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: [
- "C2SoftGSM.cpp"
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- static_libs: [
- "libgsm"
- ],
-}
-
-cc_library_shared {
name: "libstagefright_soft_gsmdec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/gsm/dec/C2SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/C2SoftGSM.cpp
deleted file mode 100644
index d021768..0000000
--- a/media/libstagefright/codecs/gsm/dec/C2SoftGSM.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftGSM"
-#include <utils/Log.h>
-
-#include "C2SoftGSM.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.gsm.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_MSGSM)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftGSM::C2SoftGSM(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mGsm(nullptr) {
-}
-
-C2SoftGSM::~C2SoftGSM() {
- onRelease();
-}
-
-c2_status_t C2SoftGSM::onInit() {
- if (!mGsm) mGsm = gsm_create();
- if (!mGsm) return C2_NO_MEMORY;
- int msopt = 1;
- (void)gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
- mSignalledError = false;
- mSignalledEos = false;
- return C2_OK;
-}
-
-c2_status_t C2SoftGSM::onStop() {
- if (mGsm) {
- gsm_destroy(mGsm);
- mGsm = nullptr;
- }
- if (!mGsm) mGsm = gsm_create();
- if (!mGsm) return C2_NO_MEMORY;
- int msopt = 1;
- (void)gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
- mSignalledError = false;
- mSignalledEos = false;
- return C2_OK;
-}
-
-void C2SoftGSM::onReset() {
- (void)onStop();
-}
-
-void C2SoftGSM::onRelease() {
- if (mGsm) {
- gsm_destroy(mGsm);
- mGsm = nullptr;
- }
-}
-
-c2_status_t C2SoftGSM::onFlush_sm() {
- return onStop();
-}
-
-static size_t decodeGSM(gsm handle, int16_t *out, size_t outCapacity,
- uint8_t *in, size_t inSize) {
- size_t outSize = 0;
-
- if (inSize % MSGSM_IN_FRM_SZ == 0
- && (inSize / MSGSM_IN_FRM_SZ * MSGSM_OUT_FRM_SZ * sizeof(*out)
- <= outCapacity)) {
- while (inSize > 0) {
- gsm_decode(handle, in, out);
- in += FRGSM_IN_FRM_SZ;
- inSize -= FRGSM_IN_FRM_SZ;
- out += FRGSM_OUT_FRM_SZ;
- outSize += FRGSM_OUT_FRM_SZ;
-
- gsm_decode(handle, in, out);
- in += FRGSM_IN_FRM_SZ_MINUS_1;
- inSize -= FRGSM_IN_FRM_SZ_MINUS_1;
- out += FRGSM_OUT_FRM_SZ;
- outSize += FRGSM_OUT_FRM_SZ;
- }
- }
-
- return outSize * sizeof(int16_t);
-}
-
-void C2SoftGSM::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = rView.error();
- return;
- }
-
- if (inSize == 0) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
-
- size_t outCapacity = (inSize / MSGSM_IN_FRM_SZ ) * MSGSM_OUT_FRM_SZ * sizeof(int16_t);
- std::shared_ptr<C2LinearBlock> block;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = wView.error();
- return;
- }
-
- int16_t *output = reinterpret_cast<int16_t *>(wView.data());
- uint8_t *input = const_cast<uint8_t *>(rView.data() + inOffset);
- size_t outSize = decodeGSM(mGsm, output, outCapacity, input, inSize);
- if (!outSize) {
- ALOGE("encountered improper insize or outsize");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- ALOGV("out buffer attr. size %zu", outSize);
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, 0, outSize));
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-c2_status_t C2SoftGSM::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- return C2_OK;
-}
-
-class C2SoftGSMDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftGSM(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftGSMDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftGSMDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/gsm/dec/C2SoftGSM.h b/media/libstagefright/codecs/gsm/dec/C2SoftGSM.h
deleted file mode 100644
index 597711c..0000000
--- a/media/libstagefright/codecs/gsm/dec/C2SoftGSM.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_GSM_H_
-#define C2_SOFT_GSM_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-extern "C" {
- #include "gsm.h"
-}
-
-namespace android {
-
-#define FRGSM_IN_FRM_SZ 33
-#define FRGSM_IN_FRM_SZ_MINUS_1 32
-#define FRGSM_OUT_FRM_SZ 160
-#define MSGSM_IN_FRM_SZ (FRGSM_IN_FRM_SZ + FRGSM_IN_FRM_SZ_MINUS_1)
-#define MSGSM_OUT_FRM_SZ (FRGSM_OUT_FRM_SZ * 2)
-
-struct C2SoftGSM : public SimpleC2Component {
- C2SoftGSM(const char *name, c2_node_id_t id);
- virtual ~C2SoftGSM();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
- private:
- gsm mGsm;
- bool mSignalledError;
- bool mSignalledEos;
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftGSM);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_GSM_H_
diff --git a/media/libstagefright/codecs/hevcdec/Android.bp b/media/libstagefright/codecs/hevcdec/Android.bp
index 385807a..45920e6 100644
--- a/media/libstagefright/codecs/hevcdec/Android.bp
+++ b/media/libstagefright/codecs/hevcdec/Android.bp
@@ -46,48 +46,3 @@
ldflags: ["-Wl,-Bsymbolic"],
compile_multilib: "32",
}
-
-cc_library_shared {
- name: "libstagefright_soft_c2hevcdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftHevcDec.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- include_dirs: [
- "external/libhevc/decoder",
- "external/libhevc/common",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: false, // true,
- diag: {
- cfi: false, // true,
- },
- },
-
- static_libs: ["libhevcdec"],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libmedia",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- ldflags: ["-Wl,-Bsymbolic"],
-
-}
diff --git a/media/libstagefright/codecs/hevcdec/C2SoftHevcDec.cpp b/media/libstagefright/codecs/hevcdec/C2SoftHevcDec.cpp
deleted file mode 100644
index 6d208bd..0000000
--- a/media/libstagefright/codecs/hevcdec/C2SoftHevcDec.cpp
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftHevcDec"
-#include <utils/Log.h>
-
-#include "ihevc_typedefs.h"
-#include "iv.h"
-#include "ivd.h"
-#include "ihevcd_cxa.h"
-#include "C2SoftHevcDec.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.hevc.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .inputMediaType(MEDIA_MIMETYPE_VIDEO_HEVC)
- .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
- .build();
-}
-
-static size_t getCpuCoreCount() {
- long cpuCoreCount = 1;
-#if defined(_SC_NPROCESSORS_ONLN)
- cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
-#else
- // _SC_NPROC_ONLN must be defined...
- cpuCoreCount = sysconf(_SC_NPROC_ONLN);
-#endif
- CHECK(cpuCoreCount >= 1);
- ALOGV("Number of CPU cores: %ld", cpuCoreCount);
- return (size_t)cpuCoreCount;
-}
-
-static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
- (void) ctxt;
- return memalign(alignment, size);
-}
-
-static void ivd_aligned_free(void *ctxt, void *mem) {
- (void) ctxt;
- free(mem);
-}
-
-C2SoftHevcDec::C2SoftHevcDec(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mDecHandle(nullptr),
- mOutBufferFlush(nullptr),
- mIvColorformat(IV_YUV_420P),
- mWidth(320),
- mHeight(240) {
-}
-
-C2SoftHevcDec::~C2SoftHevcDec() {
- onRelease();
-}
-
-c2_status_t C2SoftHevcDec::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_CORRUPTED;
-}
-
-c2_status_t C2SoftHevcDec::onStop() {
- if (OK != resetDecoder()) return C2_CORRUPTED;
- resetPlugin();
- return C2_OK;
-}
-
-void C2SoftHevcDec::onReset() {
- (void) onStop();
-}
-
-void C2SoftHevcDec::onRelease() {
- (void) deleteDecoder();
- if (mOutBufferFlush) {
- ivd_aligned_free(nullptr, mOutBufferFlush);
- mOutBufferFlush = nullptr;
- }
- if (mOutBlock) {
- mOutBlock.reset();
- }
-}
-
-c2_status_t C2SoftHevcDec::onFlush_sm() {
- if (OK != setFlushMode()) return C2_CORRUPTED;
-
- uint32_t displayStride = mStride;
- uint32_t displayHeight = mHeight;
- uint32_t bufferSize = displayStride * displayHeight * 3 / 2;
- mOutBufferFlush = (uint8_t *)ivd_aligned_malloc(nullptr, 128, bufferSize);
- if (!mOutBufferFlush) {
- ALOGE("could not allocate tmp output buffer (for flush) of size %u ", bufferSize);
- return C2_NO_MEMORY;
- }
-
- while (true) {
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
-
- setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, nullptr, 0, 0, 0);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (0 == s_decode_op.u4_output_present) {
- resetPlugin();
- break;
- }
- }
-
- ivd_aligned_free(nullptr, mOutBufferFlush);
- mOutBufferFlush = nullptr;
-
- return C2_OK;
-}
-
-status_t C2SoftHevcDec::createDecoder() {
- ivdext_create_ip_t s_create_ip;
- ivdext_create_op_t s_create_op;
-
- s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
- s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
- s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
- s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorformat;
- s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
- s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
- s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = nullptr;
- s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_create_ip,
- &s_create_op);
- if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__,
- s_create_op.s_ivd_create_op_t.u4_error_code);
- return UNKNOWN_ERROR;
- }
- mDecHandle = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
- mDecHandle->pv_fxns = (void *)ivdec_api_function;
- mDecHandle->u4_size = sizeof(iv_obj_t);
-
- return OK;
-}
-
-status_t C2SoftHevcDec::setNumCores() {
- ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip;
- ivdext_ctl_set_num_cores_op_t s_set_num_cores_op;
-
- s_set_num_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
- s_set_num_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_num_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES;
- s_set_num_cores_ip.u4_num_cores = mNumCores;
- s_set_num_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_num_cores_ip,
- &s_set_num_cores_op);
- if (IV_SUCCESS != status) {
- ALOGD("error in %s: 0x%x", __func__, s_set_num_cores_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftHevcDec::setParams(size_t stride) {
- ivd_ctl_set_config_ip_t s_set_dyn_params_ip;
- ivd_ctl_set_config_op_t s_set_dyn_params_op;
-
- s_set_dyn_params_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
- s_set_dyn_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_dyn_params_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
- s_set_dyn_params_ip.u4_disp_wd = (UWORD32) stride;
- s_set_dyn_params_ip.e_frm_skip_mode = IVD_SKIP_NONE;
- s_set_dyn_params_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
- s_set_dyn_params_ip.e_vid_dec_mode = IVD_DECODE_FRAME;
- s_set_dyn_params_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_dyn_params_ip,
- &s_set_dyn_params_op);
- if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__, s_set_dyn_params_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftHevcDec::getVersion() {
- ivd_ctl_getversioninfo_ip_t s_get_versioninfo_ip;
- ivd_ctl_getversioninfo_op_t s_get_versioninfo_op;
- UWORD8 au1_buf[512];
-
- s_get_versioninfo_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t);
- s_get_versioninfo_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_get_versioninfo_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION;
- s_get_versioninfo_ip.pv_version_buffer = au1_buf;
- s_get_versioninfo_ip.u4_version_buffer_size = sizeof(au1_buf);
- s_get_versioninfo_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_get_versioninfo_ip,
- &s_get_versioninfo_op);
- if (status != IV_SUCCESS) {
- ALOGD("error in %s: 0x%x", __func__,
- s_get_versioninfo_op.u4_error_code);
- } else {
- ALOGV("ittiam decoder version number: %s",
- (char *) s_get_versioninfo_ip.pv_version_buffer);
- }
-
- return OK;
-}
-
-status_t C2SoftHevcDec::initDecoder() {
- if (OK != createDecoder()) return UNKNOWN_ERROR;
- mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN64(mWidth);
- mSignalledError = false;
- mPreference = kPreferBitstream;
- memset(&mDefaultColorAspects, 0, sizeof(ColorAspects));
- memset(&mBitstreamColorAspects, 0, sizeof(ColorAspects));
- memset(&mFinalColorAspects, 0, sizeof(ColorAspects));
- mUpdateColorAspects = false;
- resetPlugin();
- (void) setNumCores();
- if (OK != setParams(mStride)) return UNKNOWN_ERROR;
- (void) getVersion();
-
- return OK;
-}
-
-bool C2SoftHevcDec::setDecodeArgs(ivd_video_decode_ip_t *ps_decode_ip,
- ivd_video_decode_op_t *ps_decode_op,
- C2ReadView *inBuffer,
- C2GraphicView *outBuffer,
- size_t inOffset,
- size_t inSize,
- uint32_t tsMarker) {
- uint32_t displayStride = mStride;
- uint32_t displayHeight = mHeight;
- size_t lumaSize = displayStride * displayHeight;
- size_t chromaSize = lumaSize >> 2;
-
- ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
- ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
- if (inBuffer) {
- ps_decode_ip->u4_ts = tsMarker;
- ps_decode_ip->pv_stream_buffer = const_cast<uint8_t *>(inBuffer->data() + inOffset);
- ps_decode_ip->u4_num_Bytes = inSize;
- } else {
- ps_decode_ip->u4_ts = 0;
- ps_decode_ip->pv_stream_buffer = nullptr;
- ps_decode_ip->u4_num_Bytes = 0;
- }
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[0] = lumaSize;
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
- if (outBuffer) {
- if (outBuffer->width() < displayStride || outBuffer->height() < displayHeight) {
- ALOGE("Output buffer too small: provided (%dx%d) required (%ux%u)",
- outBuffer->width(), outBuffer->height(), displayStride, displayHeight);
- return false;
- }
- ps_decode_ip->s_out_buffer.pu1_bufs[0] = outBuffer->data()[C2PlanarLayout::PLANE_Y];
- ps_decode_ip->s_out_buffer.pu1_bufs[1] = outBuffer->data()[C2PlanarLayout::PLANE_U];
- ps_decode_ip->s_out_buffer.pu1_bufs[2] = outBuffer->data()[C2PlanarLayout::PLANE_V];
- } else {
- ps_decode_ip->s_out_buffer.pu1_bufs[0] = mOutBufferFlush;
- ps_decode_ip->s_out_buffer.pu1_bufs[1] = mOutBufferFlush + lumaSize;
- ps_decode_ip->s_out_buffer.pu1_bufs[2] = mOutBufferFlush + lumaSize + chromaSize;
- }
- ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
- ps_decode_op->u4_size = sizeof(ivd_video_decode_op_t);
- ps_decode_op->u4_output_present = 0;
-
- return true;
-}
-
-bool C2SoftHevcDec::colorAspectsDiffer(
- const ColorAspects &a, const ColorAspects &b) {
- if (a.mRange != b.mRange
- || a.mPrimaries != b.mPrimaries
- || a.mTransfer != b.mTransfer
- || a.mMatrixCoeffs != b.mMatrixCoeffs) {
- return true;
- }
- return false;
-}
-
-void C2SoftHevcDec::updateFinalColorAspects(
- const ColorAspects &otherAspects, const ColorAspects &preferredAspects) {
- Mutex::Autolock autoLock(mColorAspectsLock);
- ColorAspects newAspects;
- newAspects.mRange = preferredAspects.mRange != ColorAspects::RangeUnspecified ?
- preferredAspects.mRange : otherAspects.mRange;
- newAspects.mPrimaries = preferredAspects.mPrimaries != ColorAspects::PrimariesUnspecified ?
- preferredAspects.mPrimaries : otherAspects.mPrimaries;
- newAspects.mTransfer = preferredAspects.mTransfer != ColorAspects::TransferUnspecified ?
- preferredAspects.mTransfer : otherAspects.mTransfer;
- newAspects.mMatrixCoeffs = preferredAspects.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
- preferredAspects.mMatrixCoeffs : otherAspects.mMatrixCoeffs;
-
- // Check to see if need update mFinalColorAspects.
- if (colorAspectsDiffer(mFinalColorAspects, newAspects)) {
- mFinalColorAspects = newAspects;
- mUpdateColorAspects = true;
- }
-}
-
-status_t C2SoftHevcDec::handleColorAspectsChange() {
- if (mPreference == kPreferBitstream) {
- updateFinalColorAspects(mDefaultColorAspects, mBitstreamColorAspects);
- } else if (mPreference == kPreferContainer) {
- updateFinalColorAspects(mBitstreamColorAspects, mDefaultColorAspects);
- } else {
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-bool C2SoftHevcDec::getVuiParams() {
- ivdext_ctl_get_vui_params_ip_t s_get_vui_params_ip;
- ivdext_ctl_get_vui_params_op_t s_get_vui_params_op;
-
- s_get_vui_params_ip.u4_size = sizeof(ivdext_ctl_get_vui_params_ip_t);
- s_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_get_vui_params_ip.e_sub_cmd =
- (IVD_CONTROL_API_COMMAND_TYPE_T) IHEVCD_CXA_CMD_CTL_GET_VUI_PARAMS;
- s_get_vui_params_op.u4_size = sizeof(ivdext_ctl_get_vui_params_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_get_vui_params_ip,
- &s_get_vui_params_op);
- if (status != IV_SUCCESS) {
- ALOGD("error in %s: 0x%x", __func__, s_get_vui_params_op.u4_error_code);
- return false;
- }
-
- int32_t primaries = s_get_vui_params_op.u1_colour_primaries;
- int32_t transfer = s_get_vui_params_op.u1_transfer_characteristics;
- int32_t coeffs = s_get_vui_params_op.u1_matrix_coefficients;
- bool full_range = s_get_vui_params_op.u1_video_full_range_flag;
-
- ColorAspects colorAspects;
- ColorUtils::convertIsoColorAspectsToCodecAspects(
- primaries, transfer, coeffs, full_range, colorAspects);
- // Update color aspects if necessary.
- if (colorAspectsDiffer(colorAspects, mBitstreamColorAspects)) {
- mBitstreamColorAspects = colorAspects;
- status_t err = handleColorAspectsChange();
- CHECK(err == OK);
- }
-
- return true;
-}
-
-status_t C2SoftHevcDec::setFlushMode() {
- ivd_ctl_flush_ip_t s_set_flush_ip;
- ivd_ctl_flush_op_t s_set_flush_op;
-
- s_set_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
- s_set_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH;
- s_set_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_flush_ip,
- &s_set_flush_op);
- if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__, s_set_flush_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftHevcDec::resetDecoder() {
- ivd_ctl_reset_ip_t s_reset_ip;
- ivd_ctl_reset_op_t s_reset_op;
-
- s_reset_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
- s_reset_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_reset_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
- s_reset_op.u4_size = sizeof(ivd_ctl_reset_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_reset_ip,
- &s_reset_op);
- if (IV_SUCCESS != status) {
- ALOGE("error in %s: 0x%x", __func__, s_reset_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
- mStride = 0;
- (void) setNumCores();
- mSignalledError = false;
-
- return OK;
-}
-
-void C2SoftHevcDec::resetPlugin() {
- mSignalledOutputEos = false;
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
-}
-
-status_t C2SoftHevcDec::deleteDecoder() {
- if (mDecHandle) {
- ivdext_delete_ip_t s_delete_ip;
- ivdext_delete_op_t s_delete_op;
-
- s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
- s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
- s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_delete_ip,
- &s_delete_op);
- if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__,
- s_delete_op.s_ivd_delete_op_t.u4_error_code);
- return UNKNOWN_ERROR;
- }
- mDecHandle = nullptr;
- }
-
- return OK;
-}
-
-void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-void C2SoftHevcDec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) {
- std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mOutBlock),
- C2Rect(mWidth, mHeight));
- mOutBlock = nullptr;
- auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
- (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
- if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
- fillWork(work);
- } else {
- finish(index, fillWork);
- }
-}
-
-c2_status_t C2SoftHevcDec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
- if (!mDecHandle) {
- ALOGE("not supposed to be here, invalid decoder context");
- return C2_CORRUPTED;
- }
- if (mStride != ALIGN64(mWidth)) {
- mStride = ALIGN64(mWidth);
- if (OK != setParams(mStride)) return C2_CORRUPTED;
- }
- if (mOutBlock &&
- (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
- mOutBlock.reset();
- }
- if (!mOutBlock) {
- uint32_t format = HAL_PIXEL_FORMAT_YV12;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
- if (err != C2_OK) {
- ALOGE("fetchGraphicBlock for Output failed with status %d", err);
- return err;
- }
- ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
- }
-
- return C2_OK;
-}
-
-// TODO: can overall error checking be improved?
-// TODO: allow configuration of color format and usage for graphic buffers instead
-// of hard coding them to HAL_PIXEL_FORMAT_YV12
-// TODO: pass coloraspects information to surface
-// TODO: test support for dynamic change in resolution
-// TODO: verify if the decoder sent back all frames
-void C2SoftHevcDec::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = rView.error();
- return;
- }
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- bool hasPicture = false;
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
- inSize, (int)work->input.ordinal.timestamp.peeku(),
- (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
- size_t inPos = 0;
- while (inPos < inSize) {
- if (C2_OK != ensureDecoderState(pool)) {
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- C2GraphicView wView = mOutBlock->map().get();
- if (wView.error()) {
- ALOGE("graphic view map failed %d", wView.error());
- work->result = wView.error();
- return;
- }
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, &rView, &wView,
- inOffset + inPos, inSize - inPos, workIndex)) {
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- WORD32 delay;
- GETTIME(&mTimeStart, NULL);
- TIME_DIFF(mTimeEnd, mTimeStart, delay);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- WORD32 decodeTime;
- GETTIME(&mTimeEnd, nullptr);
- TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
- s_decode_op.u4_num_bytes_consumed);
- if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & 0xFF)) {
- ALOGE("allocation failure in decoder");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & 0xFF)) {
- ALOGE("unsupported resolution : %dx%d", mWidth, mHeight);
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & 0xFF)) {
- ALOGV("resolution changed");
- drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
- resetDecoder();
- resetPlugin();
- continue;
- }
- if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
- if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
- mWidth = s_decode_op.u4_pic_wd;
- mHeight = s_decode_op.u4_pic_ht;
- CHECK_EQ(0u, s_decode_op.u4_output_present);
- }
- }
- (void) getVuiParams();
- if (mUpdateColorAspects) {
- mUpdateColorAspects = false;
- }
- hasPicture |= (1 == s_decode_op.u4_frame_decoded_flag);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
- }
- inPos += s_decode_op.u4_num_bytes_consumed;
- if (hasPicture && (inSize - inPos)) {
- ALOGD("decoded frame in current access nal, ignoring further trailing bytes %d",
- (int)inSize - (int)inPos);
- break;
- }
- }
-
- if (eos) {
- drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
- mSignalledOutputEos = true;
- } else if (!hasPicture) {
- fillEmptyWork(work);
- }
-}
-
-c2_status_t C2SoftHevcDec::drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work) {
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- if (OK != setFlushMode()) return C2_CORRUPTED;
- while (true) {
- if (C2_OK != ensureDecoderState(pool)) {
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return C2_CORRUPTED;
- }
- C2GraphicView wView = mOutBlock->map().get();
- if (wView.error()) {
- ALOGE("graphic view map failed %d", wView.error());
- return C2_CORRUPTED;
- }
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, &wView, 0, 0, 0)) {
- mSignalledError = true;
- return C2_CORRUPTED;
- }
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
- } else {
- break;
- }
- }
-
- if (drainMode == DRAIN_COMPONENT_WITH_EOS &&
- work && work->workletsProcessed == 0u) {
- fillEmptyWork(work);
- }
-
- return C2_OK;
-}
-
-c2_status_t C2SoftHevcDec::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- return drainInternal(drainMode, pool, nullptr);
-}
-
-class C2SoftHevcDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftHevcDec(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftHevcDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftHevcDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/hevcdec/C2SoftHevcDec.h b/media/libstagefright/codecs/hevcdec/C2SoftHevcDec.h
deleted file mode 100644
index 28a5a78..0000000
--- a/media/libstagefright/codecs/hevcdec/C2SoftHevcDec.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_HEVC_DEC_H_
-#define C2_SOFT_HEVC_DEC_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/foundation/ColorUtils.h>
-
-namespace android {
-
-#define ivdec_api_function ihevcd_cxa_api_function
-#define ivdext_create_ip_t ihevcd_cxa_create_ip_t
-#define ivdext_create_op_t ihevcd_cxa_create_op_t
-#define ivdext_delete_ip_t ihevcd_cxa_delete_ip_t
-#define ivdext_delete_op_t ihevcd_cxa_delete_op_t
-#define ivdext_ctl_set_num_cores_ip_t ihevcd_cxa_ctl_set_num_cores_ip_t
-#define ivdext_ctl_set_num_cores_op_t ihevcd_cxa_ctl_set_num_cores_op_t
-#define ivdext_ctl_get_vui_params_ip_t ihevcd_cxa_ctl_get_vui_params_ip_t
-#define ivdext_ctl_get_vui_params_op_t ihevcd_cxa_ctl_get_vui_params_op_t
-#define ALIGN64(x) ((((x) + 63) >> 6) << 6)
-#define MAX_NUM_CORES 4
-#define IVDEXT_CMD_CTL_SET_NUM_CORES \
- (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define GETTIME(a, b) gettimeofday(a, b);
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
-
-struct C2SoftHevcDec : public SimpleC2Component {
- C2SoftHevcDec(const char *name, c2_node_id_t id);
- virtual ~C2SoftHevcDec();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
- private:
- status_t createDecoder();
- status_t setNumCores();
- status_t setParams(size_t stride);
- status_t getVersion();
- status_t initDecoder();
- bool setDecodeArgs(ivd_video_decode_ip_t *ps_decode_ip,
- ivd_video_decode_op_t *ps_decode_op,
- C2ReadView *inBuffer,
- C2GraphicView *outBuffer,
- size_t inOffset,
- size_t inSize,
- uint32_t tsMarker);
- bool getVuiParams();
- // TODO:This is not the right place for colorAspects functions. These should
- // be part of c2-vndk so that they can be accessed by all video plugins
- // until then, make them feel at home
- bool colorAspectsDiffer(const ColorAspects &a, const ColorAspects &b);
- void updateFinalColorAspects(
- const ColorAspects &otherAspects, const ColorAspects &preferredAspects);
- status_t handleColorAspectsChange();
- c2_status_t ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool);
- void finishWork(uint64_t index, const std::unique_ptr<C2Work> &work);
- status_t setFlushMode();
- c2_status_t drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work);
- status_t resetDecoder();
- void resetPlugin();
- status_t deleteDecoder();
-
- // TODO:This is not the right place for this enum. These should
- // be part of c2-vndk so that they can be accessed by all video plugins
- // until then, make them feel at home
- enum {
- kNotSupported,
- kPreferBitstream,
- kPreferContainer,
- };
-
- iv_obj_t *mDecHandle;
- std::shared_ptr<C2GraphicBlock> mOutBlock;
- uint8_t *mOutBufferFlush;
-
- size_t mNumCores;
- IV_COLOR_FORMAT_T mIvColorformat;
-
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mStride;
- bool mSignalledOutputEos;
- bool mSignalledError;
-
- // ColorAspects
- Mutex mColorAspectsLock;
- int mPreference;
- ColorAspects mDefaultColorAspects;
- ColorAspects mBitstreamColorAspects;
- ColorAspects mFinalColorAspects;
- bool mUpdateColorAspects;
-
- // profile
- struct timeval mTimeStart;
- struct timeval mTimeEnd;
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftHevcDec);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_HEVC_DEC_H_
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
index d24a116..ca70cc2 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
@@ -112,91 +112,3 @@
},
compile_multilib: "32",
}
-
-//###############################################################################
-
-cc_library_shared {
- name: "libstagefright_soft_c2mpeg4dec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftMpeg4Dec.cpp"],
-
- cflags: [
- "-DOSCL_IMPORT_REF=",
- "-DMPEG4",
- "-Wall",
- "-Werror",
- ],
-
- local_include_dirs: ["src"],
- export_include_dirs: ["include"],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: ["libstagefright_m4vh263dec"],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- ldflags: ["-Wl,-Bsymbolic"],
-}
-
-//###############################################################################
-cc_library_shared {
- name: "libstagefright_soft_c2h263dec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftMpeg4Dec.cpp"],
-
- cflags: [
- "-DOSCL_IMPORT_REF=",
- "-Wall",
- "-Werror",
- ],
-
- local_include_dirs: ["src"],
- export_include_dirs: ["include"],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: ["libstagefright_m4vh263dec"],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- ldflags: ["-Wl,-Bsymbolic"],
-}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/C2SoftMpeg4Dec.cpp b/media/libstagefright/codecs/m4v_h263/dec/C2SoftMpeg4Dec.cpp
deleted file mode 100644
index eaef532..0000000
--- a/media/libstagefright/codecs/m4v_h263/dec/C2SoftMpeg4Dec.cpp
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftMpeg4Dec"
-#include <utils/Log.h>
-
-#include "C2SoftMpeg4Dec.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-#include "mp4dec_api.h"
-
-namespace android {
-
-#ifdef MPEG4
-constexpr char kComponentName[] = "c2.google.mpeg4.decoder";
-#else
-constexpr char kComponentName[] = "c2.google.h263.decoder";
-#endif
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .inputMediaType(
-#ifdef MPEG4
- MEDIA_MIMETYPE_VIDEO_MPEG4
-#else
- MEDIA_MIMETYPE_VIDEO_H263
-#endif
- )
- .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
- .build();
-}
-
-C2SoftMpeg4Dec::C2SoftMpeg4Dec(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mDecHandle(nullptr),
- mOutputBuffer{} {
-}
-
-C2SoftMpeg4Dec::~C2SoftMpeg4Dec() {
- onRelease();
-}
-
-c2_status_t C2SoftMpeg4Dec::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_CORRUPTED;
-}
-
-c2_status_t C2SoftMpeg4Dec::onStop() {
- if (mInitialized) {
- PVCleanUpVideoDecoder(mDecHandle);
- mInitialized = false;
- }
- for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
- if (mOutputBuffer[i]) {
- free(mOutputBuffer[i]);
- mOutputBuffer[i] = nullptr;
- }
- }
- mNumSamplesOutput = 0;
- mFramesConfigured = false;
- mSignalledOutputEos = false;
- mSignalledError = false;
-
- return C2_OK;
-}
-
-void C2SoftMpeg4Dec::onReset() {
- (void) onStop();
-}
-
-void C2SoftMpeg4Dec::onRelease() {
- if (mInitialized) {
- PVCleanUpVideoDecoder(mDecHandle);
- mInitialized = false;
- }
- if (mOutBlock) {
- mOutBlock.reset();
- }
- for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
- if (mOutputBuffer[i]) {
- free(mOutputBuffer[i]);
- mOutputBuffer[i] = nullptr;
- }
- }
-
- delete mDecHandle;
- mDecHandle = nullptr;
-}
-
-c2_status_t C2SoftMpeg4Dec::onFlush_sm() {
- if (mInitialized) {
- if (PV_TRUE != PVResetVideoDecoder(mDecHandle)) return C2_CORRUPTED;
- }
- mSignalledOutputEos = false;
- mSignalledError = false;
- return C2_OK;
-}
-
-status_t C2SoftMpeg4Dec::initDecoder() {
-#ifdef MPEG4
- mIsMpeg4 = true;
-#else
- mIsMpeg4 = false;
-#endif
- if (!mDecHandle) {
- mDecHandle = new tagvideoDecControls;
- }
- memset(mDecHandle, 0, sizeof(tagvideoDecControls));
-
- /* TODO: bring these values to 352 and 288. It cannot be done as of now
- * because, h263 doesn't seem to allow port reconfiguration. In OMX, the
- * problem of larger width and height than default width and height is
- * overcome by adaptivePlayBack() api call. This call gets width and height
- * information from extractor. Such a thing is not possible here.
- * So we are configuring to larger values.*/
- mWidth = 1408;
- mHeight = 1152;
- mNumSamplesOutput = 0;
- mInitialized = false;
- mFramesConfigured = false;
- mSignalledOutputEos = false;
- mSignalledError = false;
-
- return OK;
-}
-
-void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-void C2SoftMpeg4Dec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) {
- std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mOutBlock),
- C2Rect(mWidth, mHeight));
- mOutBlock = nullptr;
- auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
- (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
- if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
- fillWork(work);
- } else {
- finish(index, fillWork);
- }
-}
-
-c2_status_t C2SoftMpeg4Dec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
- if (!mDecHandle) {
- ALOGE("not supposed to be here, invalid decoder context");
- return C2_CORRUPTED;
- }
-
- uint32_t outSize = align(mWidth, 16) * align(mHeight, 16) * 3 / 2;
- for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
- if (!mOutputBuffer[i]) {
- mOutputBuffer[i] = (uint8_t *)malloc(outSize * sizeof(uint8_t));
- if (!mOutputBuffer[i]) return C2_NO_MEMORY;
- }
- }
- if (mOutBlock &&
- (mOutBlock->width() != align(mWidth, 16) || mOutBlock->height() != mHeight)) {
- mOutBlock.reset();
- }
- if (!mOutBlock) {
- uint32_t format = HAL_PIXEL_FORMAT_YV12;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight, format, usage, &mOutBlock);
- if (err != C2_OK) {
- ALOGE("fetchGraphicBlock for Output failed with status %d", err);
- return err;
- }
- ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), mWidth, mHeight);
- }
- return C2_OK;
-}
-
-bool C2SoftMpeg4Dec::handleResChange(const std::unique_ptr<C2Work> &work) {
- uint32_t disp_width, disp_height;
- PVGetVideoDimensions(mDecHandle, (int32 *)&disp_width, (int32 *)&disp_height);
-
- uint32_t buf_width, buf_height;
- PVGetBufferDimensions(mDecHandle, (int32 *)&buf_width, (int32 *)&buf_height);
-
- CHECK_LE(disp_width, buf_width);
- CHECK_LE(disp_height, buf_height);
-
- ALOGV("display size (%dx%d), buffer size (%dx%d)",
- disp_width, disp_height, buf_width, buf_height);
-
- bool resChanged = false;
- if (disp_width != mWidth || disp_height != mHeight) {
- mWidth = disp_width;
- mHeight = disp_height;
- resChanged = true;
- for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
- if (mOutputBuffer[i]) {
- free(mOutputBuffer[i]);
- mOutputBuffer[i] = nullptr;
- }
- }
-
- if (!mIsMpeg4) {
- PVCleanUpVideoDecoder(mDecHandle);
-
- uint8_t *vol_data[1]{};
- int32_t vol_size = 0;
-
- if (!PVInitVideoDecoder(
- mDecHandle, vol_data, &vol_size, 1, mWidth, mHeight, H263_MODE)) {
- ALOGE("Error in PVInitVideoDecoder H263_MODE while resChanged was set to true");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return true;
- }
- }
- mFramesConfigured = false;
- }
- return resChanged;
-}
-
-/* TODO: can remove temporary copy after library supports writing to display
- * buffer Y, U and V plane pointers using stride info. */
-static void copyOutputBufferToYV12Frame(uint8_t *dst, uint8_t *src, size_t dstYStride,
- size_t srcYStride, uint32_t width, uint32_t height) {
- size_t dstUVStride = align(dstYStride / 2, 16);
- size_t srcUVStride = srcYStride / 2;
- uint8_t *srcStart = src;
- uint8_t *dstStart = dst;
- size_t vStride = align(height, 16);
- for (size_t i = 0; i < height; ++i) {
- memcpy(dst, src, width);
- src += srcYStride;
- dst += dstYStride;
- }
- /* U buffer */
- src = srcStart + vStride * srcYStride;
- dst = dstStart + (dstYStride * height) + (dstUVStride * height / 2);
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dst, src, width / 2);
- src += srcUVStride;
- dst += dstUVStride;
- }
- /* V buffer */
- src = srcStart + vStride * srcYStride * 5 / 4;
- dst = dstStart + (dstYStride * height);
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dst, src, width / 2);
- src += srcUVStride;
- dst += dstUVStride;
- }
-}
-
-void C2SoftMpeg4Dec::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
- inSize, (int)work->input.ordinal.timestamp.peeku(),
- (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
-
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- if (inSize == 0) {
- fillEmptyWork(work);
- if (eos) {
- mSignalledOutputEos = true;
- }
- return;
- }
-
- uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
- uint32_t *start_code = (uint32_t *)bitstream;
- bool volHeader = *start_code == 0xB0010000;
- if (volHeader) {
- PVCleanUpVideoDecoder(mDecHandle);
- mInitialized = false;
- }
-
- if (!mInitialized) {
- uint8_t *vol_data[1]{};
- int32_t vol_size = 0;
-
- bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
- if (codecConfig || volHeader) {
- vol_data[0] = bitstream;
- vol_size = inSize;
- }
- MP4DecodingMode mode = (mIsMpeg4) ? MPEG4_MODE : H263_MODE;
-
- if (!PVInitVideoDecoder(
- mDecHandle, vol_data, &vol_size, 1,
- mWidth, mHeight, mode)) {
- ALOGE("PVInitVideoDecoder failed. Unsupported content?");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
- mInitialized = true;
- MP4DecodingMode actualMode = PVGetDecBitstreamMode(mDecHandle);
- if (mode != actualMode) {
- ALOGE("Decoded mode not same as actual mode of the decoder");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
-
- PVSetPostProcType(mDecHandle, 0);
- (void) handleResChange(work);
- if (codecConfig) {
- fillEmptyWork(work);
- return;
- }
- }
-
- size_t inPos = 0;
- while (inPos < inSize) {
- c2_status_t err = ensureDecoderState(pool);
- if (C2_OK != err) {
- mSignalledError = true;
- work->result = err;
- return;
- }
- C2GraphicView wView = mOutBlock->map().get();
- if (wView.error()) {
- ALOGE("graphic view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- uint32_t outSize = align(mWidth, 16) * align(mHeight, 16) * 3 / 2;
- uint32_t yFrameSize = sizeof(uint8) * mDecHandle->size;
- if (outSize < yFrameSize * 3 / 2){
- ALOGE("Too small output buffer: %d bytes", outSize);
- work->result = C2_NO_MEMORY;
- mSignalledError = true;
- return;
- }
-
- if (!mFramesConfigured) {
- PVSetReferenceYUV(mDecHandle,mOutputBuffer[1]);
- mFramesConfigured = true;
- }
-
- // Need to check if header contains new info, e.g., width/height, etc.
- VopHeaderInfo header_info;
- uint32_t useExtTimestamp = (inPos == 0);
- int32_t tmpInSize = (int32_t)inSize;
- uint8_t *bitstreamTmp = bitstream;
- uint32_t timestamp = workIndex;
- if (PVDecodeVopHeader(
- mDecHandle, &bitstreamTmp, ×tamp, &tmpInSize,
- &header_info, &useExtTimestamp,
- mOutputBuffer[mNumSamplesOutput & 1]) != PV_TRUE) {
- ALOGE("failed to decode vop header.");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
-
- // H263 doesn't have VOL header, the frame size information is in short header, i.e. the
- // decoder may detect size change after PVDecodeVopHeader.
- bool resChange = handleResChange(work);
- if (mIsMpeg4 && resChange) {
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- } else if (resChange) {
- continue;
- }
-
- if (PVDecodeVopBody(mDecHandle, &tmpInSize) != PV_TRUE) {
- ALOGE("failed to decode video frame.");
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
- if (handleResChange(work)) {
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
-
- uint8_t *outputBufferY = wView.data()[C2PlanarLayout::PLANE_Y];
- (void)copyOutputBufferToYV12Frame(outputBufferY, mOutputBuffer[mNumSamplesOutput & 1],
- wView.width(), align(mWidth, 16), mWidth, mHeight);
-
- inPos += inSize - (size_t)tmpInSize;
- finishWork(workIndex, work);
- ++mNumSamplesOutput;
- if (inSize - inPos != 0) {
- ALOGD("decoded frame, ignoring further trailing bytes %d",
- (int)inSize - (int)inPos);
- break;
- }
- }
-}
-
-c2_status_t C2SoftMpeg4Dec::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
- return C2_OK;
-}
-
-class C2SoftMpeg4DecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftMpeg4Dec(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftMpeg4DecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftMpeg4DecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/C2SoftMpeg4Dec.h b/media/libstagefright/codecs/m4v_h263/dec/C2SoftMpeg4Dec.h
deleted file mode 100644
index 8eb316e..0000000
--- a/media/libstagefright/codecs/m4v_h263/dec/C2SoftMpeg4Dec.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_MPEG4_DEC_H_
-#define C2_SOFT_MPEG4_DEC_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-struct tagvideoDecControls;
-
-namespace android {
-
-struct C2SoftMpeg4Dec : public SimpleC2Component {
- C2SoftMpeg4Dec(const char *name, c2_node_id_t id);
- virtual ~C2SoftMpeg4Dec();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
- private:
- enum {
- kNumOutputBuffers = 2,
- };
-
- status_t initDecoder();
- c2_status_t ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool);
- void finishWork(uint64_t index, const std::unique_ptr<C2Work> &work);
- bool handleResChange(const std::unique_ptr<C2Work> &work);
-
- tagvideoDecControls *mDecHandle;
- std::shared_ptr<C2GraphicBlock> mOutBlock;
- uint8_t *mOutputBuffer[kNumOutputBuffers];
-
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mNumSamplesOutput;
-
- bool mIsMpeg4;
- bool mInitialized;
- bool mFramesConfigured;
- bool mSignalledOutputEos;
- bool mSignalledError;
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftMpeg4Dec);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_MPEG4_DEC_H_
diff --git a/media/libstagefright/codecs/mp3dec/Android.bp b/media/libstagefright/codecs/mp3dec/Android.bp
index 9e41d17..9fa9a4c 100644
--- a/media/libstagefright/codecs/mp3dec/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/Android.bp
@@ -65,8 +65,11 @@
},
include_dirs: ["frameworks/av/media/libstagefright/include"],
- local_include_dirs: ["src"],
- export_include_dirs: ["include"],
+
+ export_include_dirs: [
+ "include",
+ "src",
+ ],
cflags: [
"-DOSCL_UNUSED_ARG(x)=(void)(x)",
@@ -119,50 +122,6 @@
compile_multilib: "32",
}
-cc_library_shared {
- name: "libstagefright_soft_c2mp3dec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftMP3.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- local_include_dirs: [
- "src",
- "include",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- static_libs: [
- "libstagefright_mp3dec"
- ],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-}
-
//###############################################################################
cc_test {
name: "libstagefright_mp3dec_test",
diff --git a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
deleted file mode 100644
index 51b9656..0000000
--- a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftMP3"
-#include <utils/Log.h>
-
-#include "pvmp3decoder_api.h"
-
-#include "C2SoftMP3.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-#include <numeric>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.mp3.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_MPEG)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mConfig(nullptr),
- mDecoderBuf(nullptr) {
-}
-
-C2SoftMP3::~C2SoftMP3() {
- onRelease();
-}
-
-c2_status_t C2SoftMP3::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_NO_MEMORY;
-}
-
-c2_status_t C2SoftMP3::onStop() {
- // Make sure that the next buffer output does not still
- // depend on fragments from the last one decoded.
- pvmp3_InitDecoder(mConfig, mDecoderBuf);
- mSignalledError = false;
- mIsFirst = true;
- mSignalledOutputEos = false;
- mAnchorTimeStamp = 0;
- mProcessedSamples = 0;
-
- return C2_OK;
-}
-
-void C2SoftMP3::onReset() {
- (void)onStop();
-}
-
-void C2SoftMP3::onRelease() {
- if (mDecoderBuf) {
- free(mDecoderBuf);
- mDecoderBuf = nullptr;
- }
-
- if (mConfig) {
- delete mConfig;
- mConfig = nullptr;
- }
-}
-
-status_t C2SoftMP3::initDecoder() {
- mConfig = new tPVMP3DecoderExternal{};
- if (!mConfig) return NO_MEMORY;
- mConfig->equalizerType = flat;
- mConfig->crcEnabled = false;
-
- size_t memRequirements = pvmp3_decoderMemRequirements();
- mDecoderBuf = malloc(memRequirements);
- if (!mDecoderBuf) return NO_MEMORY;
-
- pvmp3_InitDecoder(mConfig, mDecoderBuf);
-
- mNumChannels = 2;
- mSamplingRate = 44100;
- mIsFirst = true;
- mSignalledError = false;
- mSignalledOutputEos = false;
- mAnchorTimeStamp = 0;
- mProcessedSamples = 0;
-
- return OK;
-}
-
-/* The below code is borrowed from ./test/mp3reader.cpp */
-static bool parseMp3Header(uint32_t header, size_t *frame_size,
- uint32_t *out_sampling_rate = nullptr,
- uint32_t *out_channels = nullptr,
- uint32_t *out_bitrate = nullptr,
- uint32_t *out_num_samples = nullptr) {
- *frame_size = 0;
- if (out_sampling_rate) *out_sampling_rate = 0;
- if (out_channels) *out_channels = 0;
- if (out_bitrate) *out_bitrate = 0;
- if (out_num_samples) *out_num_samples = 1152;
-
- if ((header & 0xffe00000) != 0xffe00000) return false;
-
- unsigned version = (header >> 19) & 3;
- if (version == 0x01) return false;
-
- unsigned layer = (header >> 17) & 3;
- if (layer == 0x00) return false;
-
- unsigned bitrate_index = (header >> 12) & 0x0f;
- if (bitrate_index == 0 || bitrate_index == 0x0f) return false;
-
- unsigned sampling_rate_index = (header >> 10) & 3;
- if (sampling_rate_index == 3) return false;
-
- static const int kSamplingRateV1[] = { 44100, 48000, 32000 };
- int sampling_rate = kSamplingRateV1[sampling_rate_index];
- if (version == 2 /* V2 */) {
- sampling_rate /= 2;
- } else if (version == 0 /* V2.5 */) {
- sampling_rate /= 4;
- }
-
- unsigned padding = (header >> 9) & 1;
-
- if (layer == 3) { // layer I
- static const int kBitrateV1[] =
- {
- 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
- };
- static const int kBitrateV2[] =
- {
- 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256
- };
-
- int bitrate = (version == 3 /* V1 */) ? kBitrateV1[bitrate_index - 1] :
- kBitrateV2[bitrate_index - 1];
-
- if (out_bitrate) {
- *out_bitrate = bitrate;
- }
- *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
- if (out_num_samples) {
- *out_num_samples = 384;
- }
- } else { // layer II or III
- static const int kBitrateV1L2[] =
- {
- 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
- };
-
- static const int kBitrateV1L3[] =
- {
- 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
- };
-
- static const int kBitrateV2[] =
- {
- 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
- };
-
- int bitrate;
- if (version == 3 /* V1 */) {
- bitrate = (layer == 2 /* L2 */) ? kBitrateV1L2[bitrate_index - 1] :
- kBitrateV1L3[bitrate_index - 1];
-
- if (out_num_samples) {
- *out_num_samples = 1152;
- }
- } else { // V2 (or 2.5)
- bitrate = kBitrateV2[bitrate_index - 1];
- if (out_num_samples) {
- *out_num_samples = (layer == 1 /* L3 */) ? 576 : 1152;
- }
- }
-
- if (out_bitrate) {
- *out_bitrate = bitrate;
- }
-
- if (version == 3 /* V1 */) {
- *frame_size = 144000 * bitrate / sampling_rate + padding;
- } else { // V2 or V2.5
- size_t tmp = (layer == 1 /* L3 */) ? 72000 : 144000;
- *frame_size = tmp * bitrate / sampling_rate + padding;
- }
- }
-
- if (out_sampling_rate) {
- *out_sampling_rate = sampling_rate;
- }
-
- if (out_channels) {
- int channel_mode = (header >> 6) & 3;
-
- *out_channels = (channel_mode == 3) ? 1 : 2;
- }
-
- return true;
-}
-
-static uint32_t U32_AT(const uint8_t *ptr) {
- return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
-}
-
-static status_t calculateOutSize(uint8 *header, size_t inSize,
- std::vector<size_t> *decodedSizes) {
- uint32_t channels;
- uint32_t numSamples;
- size_t frameSize;
- size_t totalInSize = 0;
-
- while (totalInSize + 4 < inSize) {
- if (!parseMp3Header(U32_AT(header + totalInSize), &frameSize,
- nullptr, &channels, nullptr, &numSamples)) {
- ALOGE("Error in parse mp3 header during outSize estimation");
- return UNKNOWN_ERROR;
- }
- totalInSize += frameSize;
- decodedSizes->push_back(numSamples * channels * sizeof(int16_t));
- }
-
- if (decodedSizes->empty()) return UNKNOWN_ERROR;
-
- return OK;
-}
-
-c2_status_t C2SoftMP3::onFlush_sm() {
- return onStop();
-}
-
-c2_status_t C2SoftMP3::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- return C2_OK;
-}
-
-// TODO: Can overall error checking be improved? As in the check for validity of
-// work, pool ptr, work->input.buffers.size() == 1, ...
-// TODO: Blind removal of 529 samples from the output may not work. Because
-// mpeg layer 1 frame size is 384 samples per frame. This should introduce
-// negative values and can cause SEG faults. Soft omx mp3 plugin can have
-// this problem (CHECK!)
-void C2SoftMP3::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = rView.error();
- return;
- }
-
- if (inSize == 0) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
-
- size_t calOutSize;
- std::vector<size_t> decodedSizes;
- const uint8_t *inPtr = rView.data() + inOffset;
- if (OK != calculateOutSize(const_cast<uint8 *>(inPtr), inSize, &decodedSizes)) {
- work->result = C2_CORRUPTED;
- return;
- }
- calOutSize = std::accumulate(decodedSizes.begin(), decodedSizes.end(), 0);
- std::shared_ptr<C2LinearBlock> block;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(calOutSize, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = wView.error();
- return;
- }
-
- int outSize = 0;
- int outOffset = 0;
- auto it = decodedSizes.begin();
- size_t inPos = 0;
- while (inPos < inSize) {
- if (it == decodedSizes.end()) {
- ALOGE("unexpected trailing bytes, ignoring them");
- break;
- }
-
- mConfig->pInputBuffer = const_cast<uint8 *>(inPtr + inPos);
- mConfig->inputBufferCurrentLength = (inSize - inPos);
- mConfig->inputBufferMaxLength = 0;
- mConfig->inputBufferUsedLength = 0;
- mConfig->outputFrameSize = (calOutSize - outSize);
- mConfig->pOutputBuffer = reinterpret_cast<int16_t *> (wView.data() + outSize);
-
- ERROR_CODE decoderErr;
- if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
- != NO_DECODING_ERROR) {
- ALOGE("mp3 decoder returned error %d", decoderErr);
- if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
- && decoderErr != SIDE_INFO_ERROR) {
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
-
- // This is recoverable, just ignore the current frame and
- // play silence instead.
- ALOGV("ignoring error and sending silence");
- if (mConfig->outputFrameSize == 0) {
- mConfig->outputFrameSize = *it / sizeof(int16_t);
- }
- memset(mConfig->pOutputBuffer, 0, mConfig->outputFrameSize * sizeof(int16_t));
- } else if (mConfig->samplingRate != mSamplingRate
- || mConfig->num_channels != mNumChannels) {
- mSamplingRate = mConfig->samplingRate;
- mNumChannels = mConfig->num_channels;
- }
- if (*it != mConfig->outputFrameSize * sizeof(int16_t)) {
- ALOGE("panic, parsed size does not match decoded size");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- outSize += mConfig->outputFrameSize * sizeof(int16_t);
- inPos += mConfig->inputBufferUsedLength;
- it++;
- }
- if (mIsFirst) {
- mIsFirst = false;
- // The decoder delay is 529 samples, so trim that many samples off
- // the start of the first output buffer. This essentially makes this
- // decoder have zero delay, which the rest of the pipeline assumes.
- outOffset = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
- mAnchorTimeStamp = work->input.ordinal.timestamp.peekull();
- }
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / mSamplingRate;
- mProcessedSamples += ((outSize - outOffset) / (mNumChannels * sizeof(int16_t)));
- ALOGV("out buffer attr. offset %d size %d timestamp %u", outOffset, outSize - outOffset,
- (uint32_t)(mAnchorTimeStamp + outTimeStamp));
- decodedSizes.clear();
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(
- createLinearBuffer(block, outOffset, outSize - outOffset));
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
- work->workletsProcessed = 1u;
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-class C2SoftMp3DecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftMP3(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftMp3DecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftMp3DecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
-
diff --git a/media/libstagefright/codecs/mp3dec/C2SoftMP3.h b/media/libstagefright/codecs/mp3dec/C2SoftMP3.h
deleted file mode 100644
index 6e9a571..0000000
--- a/media/libstagefright/codecs/mp3dec/C2SoftMP3.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_MP3_H_
-#define C2_SOFT_MP3_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-struct tPVMP3DecoderExternal;
-
-bool parseMp3Header(uint32_t header, size_t *frame_size,
- uint32_t *out_sampling_rate = nullptr,
- uint32_t *out_channels = nullptr,
- uint32_t *out_bitrate = nullptr,
- uint32_t *out_num_samples = nullptr);
-
-namespace android {
-
-struct C2SoftMP3 : public SimpleC2Component {
- C2SoftMP3(const char *name, c2_node_id_t id);
- virtual ~C2SoftMP3();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
-private:
- enum {
- kPVMP3DecoderDelay = 529 // samples
- };
-
- tPVMP3DecoderExternal *mConfig;
- void *mDecoderBuf;
-
- int32_t mNumChannels;
- int32_t mSamplingRate;
- bool mIsFirst;
- bool mSignalledError;
- bool mSignalledOutputEos;
- uint64_t mAnchorTimeStamp;
- uint64_t mProcessedSamples;
-
- status_t initDecoder();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftMP3);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_MP3_H_
diff --git a/media/libstagefright/codecs/mpeg2dec/Android.bp b/media/libstagefright/codecs/mpeg2dec/Android.bp
index 3123376..fb0db8f 100644
--- a/media/libstagefright/codecs/mpeg2dec/Android.bp
+++ b/media/libstagefright/codecs/mpeg2dec/Android.bp
@@ -1,47 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2mpeg2dec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftMpeg2Dec.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- include_dirs: [
- "external/libmpeg2/decoder",
- "external/libmpeg2/common",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: false, // true,
- diag: {
- cfi: false, // true,
- },
- },
-
- static_libs: ["libmpeg2dec"],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- ldflags: ["-Wl,-Bsymbolic"],
-}
-
-cc_library_shared {
name: "libstagefright_soft_mpeg2dec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/mpeg2dec/C2SoftMpeg2Dec.cpp b/media/libstagefright/codecs/mpeg2dec/C2SoftMpeg2Dec.cpp
deleted file mode 100644
index f8008aa..0000000
--- a/media/libstagefright/codecs/mpeg2dec/C2SoftMpeg2Dec.cpp
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftMpeg2Dec"
-#include <utils/Log.h>
-
-#include "iv_datatypedef.h"
-#include "iv.h"
-#include "ivd.h"
-#include "impeg2d.h"
-#include "C2SoftMpeg2Dec.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.mpeg2.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .inputMediaType(MEDIA_MIMETYPE_VIDEO_MPEG2)
- .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
- .build();
-}
-
-static size_t getCpuCoreCount() {
- long cpuCoreCount = 1;
-#if defined(_SC_NPROCESSORS_ONLN)
- cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
-#else
- // _SC_NPROC_ONLN must be defined...
- cpuCoreCount = sysconf(_SC_NPROC_ONLN);
-#endif
- CHECK(cpuCoreCount >= 1);
- ALOGV("Number of CPU cores: %ld", cpuCoreCount);
- return (size_t)cpuCoreCount;
-}
-
-static void *ivd_aligned_malloc(WORD32 alignment, WORD32 size) {
- return memalign(alignment, size);
-}
-
-static void ivd_aligned_free(void *mem) {
- free(mem);
-}
-
-C2SoftMpeg2Dec::C2SoftMpeg2Dec(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mDecHandle(nullptr),
- mMemRecords(nullptr),
- mOutBufferDrain(nullptr),
- mIvColorformat(IV_YUV_420P),
- mWidth(320),
- mHeight(240) {
- // If input dump is enabled, then open create an empty file
- GENERATE_FILE_NAMES();
- CREATE_DUMP_FILE(mInFile);
-}
-
-C2SoftMpeg2Dec::~C2SoftMpeg2Dec() {
- onRelease();
-}
-
-c2_status_t C2SoftMpeg2Dec::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_CORRUPTED;
-}
-
-c2_status_t C2SoftMpeg2Dec::onStop() {
- if (OK != resetDecoder()) return C2_CORRUPTED;
- resetPlugin();
- return C2_OK;
-}
-
-void C2SoftMpeg2Dec::onReset() {
- (void) onStop();
-}
-
-void C2SoftMpeg2Dec::onRelease() {
- (void) deleteDecoder();
- if (mOutBufferDrain) {
- ivd_aligned_free(mOutBufferDrain);
- mOutBufferDrain = nullptr;
- }
- if (mOutBlock) {
- mOutBlock.reset();
- }
- if (mMemRecords) {
- ivd_aligned_free(mMemRecords);
- mMemRecords = nullptr;
- }
-}
-
-c2_status_t C2SoftMpeg2Dec::onFlush_sm() {
- if (OK != setFlushMode()) return C2_CORRUPTED;
-
- uint32_t displayStride = mStride;
- uint32_t displayHeight = mHeight;
- uint32_t bufferSize = displayStride * displayHeight * 3 / 2;
- mOutBufferDrain = (uint8_t *)ivd_aligned_malloc(128, bufferSize);
- if (!mOutBufferDrain) {
- ALOGE("could not allocate tmp output buffer (for flush) of size %u ", bufferSize);
- return C2_NO_MEMORY;
- }
-
- while (true) {
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
-
- setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, nullptr, 0, 0, 0);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (0 == s_decode_op.u4_output_present) {
- resetPlugin();
- break;
- }
- }
-
- ivd_aligned_free(mOutBufferDrain);
- mOutBufferDrain = nullptr;
-
- return C2_OK;
-}
-
-status_t C2SoftMpeg2Dec::getNumMemRecords() {
- iv_num_mem_rec_ip_t s_num_mem_rec_ip;
- iv_num_mem_rec_op_t s_num_mem_rec_op;
-
- s_num_mem_rec_ip.u4_size = sizeof(s_num_mem_rec_ip);
- s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
- s_num_mem_rec_op.u4_size = sizeof(s_num_mem_rec_op);
-
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_num_mem_rec_ip,
- &s_num_mem_rec_op);
- if (IV_SUCCESS != status) {
- ALOGE("Error in getting mem records: 0x%x", s_num_mem_rec_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
- mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::fillMemRecords() {
- iv_mem_rec_t *ps_mem_rec = (iv_mem_rec_t *) ivd_aligned_malloc(
- 128, mNumMemRecords * sizeof(iv_mem_rec_t));
- if (!ps_mem_rec) {
- ALOGE("Allocation failure");
- return NO_MEMORY;
- }
- memset(ps_mem_rec, 0, mNumMemRecords * sizeof(iv_mem_rec_t));
- for (size_t i = 0; i < mNumMemRecords; i++)
- ps_mem_rec[i].u4_size = sizeof(iv_mem_rec_t);
- mMemRecords = ps_mem_rec;
-
- ivdext_fill_mem_rec_ip_t s_fill_mem_ip;
- ivdext_fill_mem_rec_op_t s_fill_mem_op;
-
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_size = sizeof(ivdext_fill_mem_rec_ip_t);
- s_fill_mem_ip.u4_share_disp_buf = 0;
- s_fill_mem_ip.e_output_format = mIvColorformat;
- s_fill_mem_ip.u4_deinterlace = 1;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = mMemRecords;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = mWidth;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = mHeight;
- s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_size = sizeof(ivdext_fill_mem_rec_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_fill_mem_ip,
- &s_fill_mem_op);
- if (IV_SUCCESS != status) {
- ALOGE("Error in filling mem records: 0x%x",
- s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- CHECK_EQ(mNumMemRecords, s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_num_mem_rec_filled);
- for (size_t i = 0; i < mNumMemRecords; i++, ps_mem_rec++) {
- ps_mem_rec->pv_base = ivd_aligned_malloc(
- ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
- if (!ps_mem_rec->pv_base) {
- ALOGE("Allocation failure for memory record #%zu of size %u",
- i, ps_mem_rec->u4_mem_size);
- return NO_MEMORY;
- }
- }
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::createDecoder() {
- ivdext_init_ip_t s_init_ip;
- ivdext_init_op_t s_init_op;
-
- s_init_ip.s_ivd_init_ip_t.u4_size = sizeof(ivdext_init_ip_t);
- s_init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT;
- s_init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mMemRecords;
- s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = mWidth;
- s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = mHeight;
- s_init_ip.u4_share_disp_buf = 0;
- s_init_ip.u4_deinterlace = 1;
- s_init_ip.s_ivd_init_ip_t.u4_num_mem_rec = mNumMemRecords;
- s_init_ip.s_ivd_init_ip_t.e_output_format = mIvColorformat;
- s_init_op.s_ivd_init_op_t.u4_size = sizeof(ivdext_init_op_t);
-
- mDecHandle = (iv_obj_t *)mMemRecords[0].pv_base;
- mDecHandle->pv_fxns = (void *)ivdec_api_function;
- mDecHandle->u4_size = sizeof(iv_obj_t);
-
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_init_ip,
- &s_init_op);
- if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__,
- s_init_op.s_ivd_init_op_t.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::setNumCores() {
- ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip;
- ivdext_ctl_set_num_cores_op_t s_set_num_cores_op;
-
- s_set_num_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
- s_set_num_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_num_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES;
- s_set_num_cores_ip.u4_num_cores = mNumCores;
- s_set_num_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_num_cores_ip,
- &s_set_num_cores_op);
- if (status != IV_SUCCESS) {
- ALOGD("error in %s: 0x%x", __func__, s_set_num_cores_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::setParams(size_t stride) {
- ivd_ctl_set_config_ip_t s_set_dyn_params_ip;
- ivd_ctl_set_config_op_t s_set_dyn_params_op;
-
- s_set_dyn_params_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
- s_set_dyn_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_dyn_params_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
- s_set_dyn_params_ip.u4_disp_wd = (UWORD32) stride;
- s_set_dyn_params_ip.e_frm_skip_mode = IVD_SKIP_NONE;
- s_set_dyn_params_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
- s_set_dyn_params_ip.e_vid_dec_mode = IVD_DECODE_FRAME;
- s_set_dyn_params_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_dyn_params_ip,
- &s_set_dyn_params_op);
- if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__, s_set_dyn_params_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::getVersion() {
- ivd_ctl_getversioninfo_ip_t s_get_versioninfo_ip;
- ivd_ctl_getversioninfo_op_t s_get_versioninfo_op;
- UWORD8 au1_buf[512];
-
- s_get_versioninfo_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t);
- s_get_versioninfo_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_get_versioninfo_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION;
- s_get_versioninfo_ip.pv_version_buffer = au1_buf;
- s_get_versioninfo_ip.u4_version_buffer_size = sizeof(au1_buf);
- s_get_versioninfo_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_get_versioninfo_ip,
- &s_get_versioninfo_op);
- if (status != IV_SUCCESS) {
- ALOGD("error in %s: 0x%x", __func__,
- s_get_versioninfo_op.u4_error_code);
- } else {
- ALOGV("ittiam decoder version number: %s",
- (char *) s_get_versioninfo_ip.pv_version_buffer);
- }
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::initDecoder() {
- status_t ret = getNumMemRecords();
- if (OK != ret) return ret;
-
- ret = fillMemRecords();
- if (OK != ret) return ret;
-
- if (OK != createDecoder()) return UNKNOWN_ERROR;
-
- mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN64(mWidth);
- mSignalledError = false;
- mPreference = kPreferBitstream;
- memset(&mDefaultColorAspects, 0, sizeof(ColorAspects));
- memset(&mBitstreamColorAspects, 0, sizeof(ColorAspects));
- memset(&mFinalColorAspects, 0, sizeof(ColorAspects));
- mUpdateColorAspects = false;
- resetPlugin();
- (void) setNumCores();
- if (OK != setParams(mStride)) return UNKNOWN_ERROR;
- (void) getVersion();
-
- return OK;
-}
-
-bool C2SoftMpeg2Dec::setDecodeArgs(ivd_video_decode_ip_t *ps_decode_ip,
- ivd_video_decode_op_t *ps_decode_op,
- C2ReadView *inBuffer,
- C2GraphicView *outBuffer,
- size_t inOffset,
- size_t inSize,
- uint32_t tsMarker) {
- uint32_t displayStride = mStride;
- uint32_t displayHeight = mHeight;
- size_t lumaSize = displayStride * displayHeight;
- size_t chromaSize = lumaSize >> 2;
-
- ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
- ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
- if (inBuffer) {
- ps_decode_ip->u4_ts = tsMarker;
- ps_decode_ip->pv_stream_buffer = const_cast<uint8_t *>(inBuffer->data() + inOffset);
- ps_decode_ip->u4_num_Bytes = inSize;
- } else {
- ps_decode_ip->u4_ts = 0;
- ps_decode_ip->pv_stream_buffer = nullptr;
- ps_decode_ip->u4_num_Bytes = 0;
- }
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[0] = lumaSize;
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
- if (outBuffer) {
- if (outBuffer->width() < displayStride || outBuffer->height() < displayHeight) {
- ALOGE("Output buffer too small: provided (%dx%d) required (%ux%u)",
- outBuffer->width(), outBuffer->height(), displayStride, displayHeight);
- return false;
- }
- ps_decode_ip->s_out_buffer.pu1_bufs[0] = outBuffer->data()[C2PlanarLayout::PLANE_Y];
- ps_decode_ip->s_out_buffer.pu1_bufs[1] = outBuffer->data()[C2PlanarLayout::PLANE_U];
- ps_decode_ip->s_out_buffer.pu1_bufs[2] = outBuffer->data()[C2PlanarLayout::PLANE_V];
- } else {
- ps_decode_ip->s_out_buffer.pu1_bufs[0] = mOutBufferDrain;
- ps_decode_ip->s_out_buffer.pu1_bufs[1] = mOutBufferDrain + lumaSize;
- ps_decode_ip->s_out_buffer.pu1_bufs[2] = mOutBufferDrain + lumaSize + chromaSize;
- }
- ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
- ps_decode_op->u4_size = sizeof(ivd_video_decode_op_t);
-
- return true;
-}
-
-bool C2SoftMpeg2Dec::colorAspectsDiffer(
- const ColorAspects &a, const ColorAspects &b) {
- if (a.mRange != b.mRange
- || a.mPrimaries != b.mPrimaries
- || a.mTransfer != b.mTransfer
- || a.mMatrixCoeffs != b.mMatrixCoeffs) {
- return true;
- }
- return false;
-}
-
-void C2SoftMpeg2Dec::updateFinalColorAspects(
- const ColorAspects &otherAspects, const ColorAspects &preferredAspects) {
- Mutex::Autolock autoLock(mColorAspectsLock);
- ColorAspects newAspects;
- newAspects.mRange = preferredAspects.mRange != ColorAspects::RangeUnspecified ?
- preferredAspects.mRange : otherAspects.mRange;
- newAspects.mPrimaries = preferredAspects.mPrimaries != ColorAspects::PrimariesUnspecified ?
- preferredAspects.mPrimaries : otherAspects.mPrimaries;
- newAspects.mTransfer = preferredAspects.mTransfer != ColorAspects::TransferUnspecified ?
- preferredAspects.mTransfer : otherAspects.mTransfer;
- newAspects.mMatrixCoeffs = preferredAspects.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
- preferredAspects.mMatrixCoeffs : otherAspects.mMatrixCoeffs;
-
- // Check to see if need update mFinalColorAspects.
- if (colorAspectsDiffer(mFinalColorAspects, newAspects)) {
- mFinalColorAspects = newAspects;
- mUpdateColorAspects = true;
- }
-}
-
-status_t C2SoftMpeg2Dec::handleColorAspectsChange() {
- if (mPreference == kPreferBitstream) {
- updateFinalColorAspects(mDefaultColorAspects, mBitstreamColorAspects);
- } else if (mPreference == kPreferContainer) {
- updateFinalColorAspects(mBitstreamColorAspects, mDefaultColorAspects);
- } else {
- return C2_CORRUPTED;
- }
- return C2_OK;
-}
-
-bool C2SoftMpeg2Dec::getSeqInfo() {
- ivdext_ctl_get_seq_info_ip_t s_ctl_get_seq_info_ip;
- ivdext_ctl_get_seq_info_op_t s_ctl_get_seq_info_op;
-
- s_ctl_get_seq_info_ip.u4_size = sizeof(ivdext_ctl_get_seq_info_ip_t);
- s_ctl_get_seq_info_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_ctl_get_seq_info_ip.e_sub_cmd =
- (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_GET_SEQ_INFO;
- s_ctl_get_seq_info_op.u4_size = sizeof(ivdext_ctl_get_seq_info_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_ctl_get_seq_info_ip,
- &s_ctl_get_seq_info_op);
- if (status != IV_SUCCESS) {
- ALOGW("Error in getting Sequence info: 0x%x", s_ctl_get_seq_info_op.u4_error_code);
- return false;
- }
-
- int32_t primaries = s_ctl_get_seq_info_op.u1_colour_primaries;
- int32_t transfer = s_ctl_get_seq_info_op.u1_transfer_characteristics;
- int32_t coeffs = s_ctl_get_seq_info_op.u1_matrix_coefficients;
- bool full_range = false; // mpeg2 video has limited range.
-
- ColorAspects colorAspects;
- ColorUtils::convertIsoColorAspectsToCodecAspects(
- primaries, transfer, coeffs, full_range, colorAspects);
- // Update color aspects if necessary.
- if (colorAspectsDiffer(colorAspects, mBitstreamColorAspects)) {
- mBitstreamColorAspects = colorAspects;
- status_t err = handleColorAspectsChange();
- CHECK(err == OK);
- }
-
- return true;
-}
-
-status_t C2SoftMpeg2Dec::setFlushMode() {
- ivd_ctl_flush_ip_t s_set_flush_ip;
- ivd_ctl_flush_op_t s_set_flush_op;
-
- s_set_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
- s_set_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH;
- s_set_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_flush_ip,
- &s_set_flush_op);
- if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__, s_set_flush_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::resetDecoder() {
- ivd_ctl_reset_ip_t s_reset_ip;
- ivd_ctl_reset_op_t s_reset_op;
-
- s_reset_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
- s_reset_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_reset_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
- s_reset_op.u4_size = sizeof(ivd_ctl_reset_op_t);
- IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_reset_ip,
- &s_reset_op);
- if (IV_SUCCESS != status) {
- ALOGE("error in %s: 0x%x", __func__, s_reset_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
- (void) setNumCores();
- mStride = 0;
- mSignalledError = false;
-
- return OK;
-}
-
-void C2SoftMpeg2Dec::resetPlugin() {
- mSignalledOutputEos = false;
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
-}
-
-status_t C2SoftMpeg2Dec::deleteDecoder() {
- if (mMemRecords) {
- iv_mem_rec_t *ps_mem_rec = mMemRecords;
-
- for (size_t i = 0; i < mNumMemRecords; i++, ps_mem_rec++) {
- if (ps_mem_rec->pv_base) {
- ivd_aligned_free(ps_mem_rec->pv_base);
- }
- }
- ivd_aligned_free(mMemRecords);
- mMemRecords = nullptr;
- }
- mDecHandle = nullptr;
-
- return OK;
-}
-
-status_t C2SoftMpeg2Dec::reInitDecoder() {
- deleteDecoder();
-
- status_t ret = initDecoder();
- if (OK != ret) {
- ALOGE("Failed to initialize decoder");
- deleteDecoder();
- return ret;
- }
- return OK;
-}
-
-void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-void C2SoftMpeg2Dec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) {
- std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mOutBlock),
- C2Rect(mWidth, mHeight));
- mOutBlock = nullptr;
- auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
- (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
- if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
- fillWork(work);
- } else {
- finish(index, fillWork);
- }
-}
-
-c2_status_t C2SoftMpeg2Dec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
- if (!mDecHandle) {
- ALOGE("not supposed to be here, invalid decoder context");
- return C2_CORRUPTED;
- }
- if (mStride != ALIGN64(mWidth)) {
- mStride = ALIGN64(mWidth);
- if (OK != setParams(mStride)) return C2_CORRUPTED;
- }
- if (mOutBlock &&
- (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
- mOutBlock.reset();
- }
- if (!mOutBlock) {
- uint32_t format = HAL_PIXEL_FORMAT_YV12;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
- if (err != C2_OK) {
- ALOGE("fetchGraphicBlock for Output failed with status %d", err);
- return err;
- }
- ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
- }
-
- return C2_OK;
-}
-
-// TODO: can overall error checking be improved?
-// TODO: allow configuration of color format and usage for graphic buffers instead
-// of hard coding them to HAL_PIXEL_FORMAT_YV12
-// TODO: pass coloraspects information to surface
-// TODO: test support for dynamic change in resolution
-// TODO: verify if the decoder sent back all frames
-void C2SoftMpeg2Dec::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- bool hasPicture = false;
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
- inSize, (int)work->input.ordinal.timestamp.peeku(),
- (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
- size_t inPos = 0;
- while (inPos < inSize) {
- if (C2_OK != ensureDecoderState(pool)) {
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- C2GraphicView wView = mOutBlock->map().get();
- if (wView.error()) {
- ALOGE("graphic view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, &rView, &wView,
- inOffset + inPos, inSize - inPos, workIndex)) {
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- // If input dump is enabled, then write to file
- DUMP_TO_FILE(mInFile, s_decode_ip.pv_stream_buffer, s_decode_ip.u4_num_Bytes);
- WORD32 delay;
- GETTIME(&mTimeStart, NULL);
- TIME_DIFF(mTimeEnd, mTimeStart, delay);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- WORD32 decodeTime;
- GETTIME(&mTimeEnd, nullptr);
- TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- ALOGV("decodeTime=%6d delay=%6d numBytes=%6d ", decodeTime, delay,
- s_decode_op.u4_num_bytes_consumed);
- if (IMPEG2D_UNSUPPORTED_DIMENSIONS == s_decode_op.u4_error_code) {
- ALOGV("unsupported resolution : %dx%d", s_decode_op.u4_pic_wd, s_decode_op.u4_pic_ht);
- drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
- resetPlugin();
- mWidth = s_decode_op.u4_pic_wd;
- mHeight = s_decode_op.u4_pic_ht;
- if (OK != reInitDecoder()) {
- ALOGE("Failed to reinitialize decoder");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- continue;
- } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & 0xFF)) {
- ALOGV("resolution changed");
- drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
- resetDecoder();
- resetPlugin();
- mWidth = s_decode_op.u4_pic_wd;
- mHeight = s_decode_op.u4_pic_ht;
- continue;
- }
-
- (void) getSeqInfo();
- if (mUpdateColorAspects) {
- mUpdateColorAspects = false;
- }
- hasPicture |= (1 == s_decode_op.u4_frame_decoded_flag);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
- }
- inPos += s_decode_op.u4_num_bytes_consumed;
- if (hasPicture && (inSize - inPos) != 0) {
- ALOGD("decoded frame in current access nal, ignoring further trailing bytes %d",
- (int)inSize - (int)inPos);
- break;
- }
- }
-
- if (eos) {
- drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
- mSignalledOutputEos = true;
- } else if (!hasPicture) {
- fillEmptyWork(work);
- }
-}
-
-c2_status_t C2SoftMpeg2Dec::drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work) {
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- if (OK != setFlushMode()) return C2_CORRUPTED;
- while (true) {
- if (C2_OK != ensureDecoderState(pool)) {
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return C2_CORRUPTED;
- }
- C2GraphicView wView = mOutBlock->map().get();
- if (wView.error()) {
- ALOGE("graphic view map failed %d", wView.error());
- return C2_CORRUPTED;
- }
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, &wView, 0, 0, 0)) {
- mSignalledError = true;
- return C2_CORRUPTED;
- }
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
- } else {
- break;
- }
- }
- if (drainMode == DRAIN_COMPONENT_WITH_EOS &&
- work && work->workletsProcessed == 0u) {
- fillEmptyWork(work);
- }
-
- return C2_OK;
-}
-
-c2_status_t C2SoftMpeg2Dec::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- return drainInternal(drainMode, pool, nullptr);
-}
-
-class C2SoftMpeg2DecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftMpeg2Dec(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftMpeg2DecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftMpeg2DecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/mpeg2dec/C2SoftMpeg2Dec.h b/media/libstagefright/codecs/mpeg2dec/C2SoftMpeg2Dec.h
deleted file mode 100644
index 64e5b05..0000000
--- a/media/libstagefright/codecs/mpeg2dec/C2SoftMpeg2Dec.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_MPEG2_DEC_H_
-#define C2_SOFT_MPEG2_DEC_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/foundation/ColorUtils.h>
-
-namespace android {
-
-#define ivdec_api_function impeg2d_api_function
-#define ivdext_init_ip_t impeg2d_init_ip_t
-#define ivdext_init_op_t impeg2d_init_op_t
-#define ivdext_fill_mem_rec_ip_t impeg2d_fill_mem_rec_ip_t
-#define ivdext_fill_mem_rec_op_t impeg2d_fill_mem_rec_op_t
-#define ivdext_ctl_set_num_cores_ip_t impeg2d_ctl_set_num_cores_ip_t
-#define ivdext_ctl_set_num_cores_op_t impeg2d_ctl_set_num_cores_op_t
-#define ivdext_ctl_get_seq_info_ip_t impeg2d_ctl_get_seq_info_ip_t
-#define ivdext_ctl_get_seq_info_op_t impeg2d_ctl_get_seq_info_op_t
-#define ALIGN64(x) ((((x) + 63) >> 6) << 6)
-#define MAX_NUM_CORES 4
-#define IVDEXT_CMD_CTL_SET_NUM_CORES \
- (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define GETTIME(a, b) gettimeofday(a, b);
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
-#ifdef FILE_DUMP_ENABLE
- #define INPUT_DUMP_PATH "/sdcard/clips/mpeg2d_input"
- #define INPUT_DUMP_EXT "m2v"
- #define GENERATE_FILE_NAMES() { \
- GETTIME(&mTimeStart, NULL); \
- strcpy(mInFile, ""); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
- INPUT_DUMP_EXT); \
- }
- #define CREATE_DUMP_FILE(m_filename) { \
- FILE *fp = fopen(m_filename, "wb"); \
- if (fp != NULL) { \
- fclose(fp); \
- } else { \
- ALOGD("Could not open file %s", m_filename); \
- } \
- }
- #define DUMP_TO_FILE(m_filename, m_buf, m_size) \
- { \
- FILE *fp = fopen(m_filename, "ab"); \
- if (fp != NULL && m_buf != NULL) { \
- uint32_t i; \
- i = fwrite(m_buf, 1, m_size, fp); \
- ALOGD("fwrite ret %d to write %d", i, m_size); \
- if (i != (uint32_t)m_size) { \
- ALOGD("Error in fwrite, returned %d", i); \
- perror("Error in write to file"); \
- } \
- fclose(fp); \
- } else { \
- ALOGD("Could not write to file %s", m_filename);\
- } \
- }
-#else /* FILE_DUMP_ENABLE */
- #define INPUT_DUMP_PATH
- #define INPUT_DUMP_EXT
- #define OUTPUT_DUMP_PATH
- #define OUTPUT_DUMP_EXT
- #define GENERATE_FILE_NAMES()
- #define CREATE_DUMP_FILE(m_filename)
- #define DUMP_TO_FILE(m_filename, m_buf, m_size)
-#endif /* FILE_DUMP_ENABLE */
-
-struct C2SoftMpeg2Dec : public SimpleC2Component {
- C2SoftMpeg2Dec(const char *name, c2_node_id_t id);
- virtual ~C2SoftMpeg2Dec();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
- private:
- status_t getNumMemRecords();
- status_t fillMemRecords();
- status_t createDecoder();
- status_t setNumCores();
- status_t setParams(size_t stride);
- status_t getVersion();
- status_t initDecoder();
- bool setDecodeArgs(ivd_video_decode_ip_t *ps_decode_ip,
- ivd_video_decode_op_t *ps_decode_op,
- C2ReadView *inBuffer,
- C2GraphicView *outBuffer,
- size_t inOffset,
- size_t inSize,
- uint32_t tsMarker);
- bool getSeqInfo();
- // TODO:This is not the right place for colorAspects functions. These should
- // be part of c2-vndk so that they can be accessed by all video plugins
- // until then, make them feel at home
- bool colorAspectsDiffer(const ColorAspects &a, const ColorAspects &b);
- void updateFinalColorAspects(
- const ColorAspects &otherAspects, const ColorAspects &preferredAspects);
- status_t handleColorAspectsChange();
- c2_status_t ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool);
- void finishWork(uint64_t index, const std::unique_ptr<C2Work> &work);
- status_t setFlushMode();
- c2_status_t drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work);
- status_t resetDecoder();
- void resetPlugin();
- status_t deleteDecoder();
- status_t reInitDecoder();
-
- // TODO:This is not the right place for this enum. These should
- // be part of c2-vndk so that they can be accessed by all video plugins
- // until then, make them feel at home
- enum {
- kNotSupported,
- kPreferBitstream,
- kPreferContainer,
- };
-
- iv_obj_t *mDecHandle;
- iv_mem_rec_t *mMemRecords;
- size_t mNumMemRecords;
- std::shared_ptr<C2GraphicBlock> mOutBlock;
- uint8_t *mOutBufferDrain;
-
- size_t mNumCores;
- IV_COLOR_FORMAT_T mIvColorformat;
-
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mStride;
- bool mSignalledOutputEos;
- bool mSignalledError;
-
- // ColorAspects
- Mutex mColorAspectsLock;
- int mPreference;
- ColorAspects mDefaultColorAspects;
- ColorAspects mBitstreamColorAspects;
- ColorAspects mFinalColorAspects;
- bool mUpdateColorAspects;
-
- // profile
- struct timeval mTimeStart;
- struct timeval mTimeEnd;
-#ifdef FILE_DUMP_ENABLE
- char mInFile[200];
-#endif /* FILE_DUMP_ENABLE */
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftMpeg2Dec);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_MPEG2_DEC_H_
diff --git a/media/libstagefright/codecs/on2/dec/Android.bp b/media/libstagefright/codecs/on2/dec/Android.bp
index 03f0c05..8a9399a 100644
--- a/media/libstagefright/codecs/on2/dec/Android.bp
+++ b/media/libstagefright/codecs/on2/dec/Android.bp
@@ -37,82 +37,3 @@
},
compile_multilib: "32",
}
-
-cc_library_shared {
- name: "libstagefright_soft_c2vp9dec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftVpx.cpp"],
-
- static_libs: ["libvpx"],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- cflags: [
- "-DVP9",
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- ldflags: ["-Wl,-Bsymbolic"],
-}
-
-cc_library_shared {
- name: "libstagefright_soft_c2vp8dec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftVpx.cpp"],
-
- static_libs: ["libvpx"],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- ldflags: ["-Wl,-Bsymbolic"],
-}
diff --git a/media/libstagefright/codecs/on2/dec/C2SoftVpx.cpp b/media/libstagefright/codecs/on2/dec/C2SoftVpx.cpp
deleted file mode 100644
index 8528f26..0000000
--- a/media/libstagefright/codecs/on2/dec/C2SoftVpx.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftVpx"
-#include <utils/Log.h>
-
-#include "C2SoftVpx.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-#ifdef VP9
-constexpr char kComponentName[] = "c2.google.vp9.decoder";
-#else
-constexpr char kComponentName[] = "c2.google.vp8.decoder";
-#endif
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .inputMediaType(
-#ifdef VP9
- MEDIA_MIMETYPE_VIDEO_VP9
-#else
- MEDIA_MIMETYPE_VIDEO_VP8
-#endif
- )
- .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
- .build();
-}
-
-C2SoftVpx::C2SoftVpx(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mCodecCtx(nullptr) {
-}
-
-C2SoftVpx::~C2SoftVpx() {
- onRelease();
-}
-
-c2_status_t C2SoftVpx::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_CORRUPTED;
-}
-
-c2_status_t C2SoftVpx::onStop() {
- (void) onFlush_sm();
- destroyDecoder();
-
- mSignalledError = false;
- mSignalledOutputEos = false;
-
- return C2_OK;
-}
-
-void C2SoftVpx::onReset() {
- (void) onStop();
- (void) initDecoder();
-}
-
-void C2SoftVpx::onRelease() {
- destroyDecoder();
-}
-
-c2_status_t C2SoftVpx::onFlush_sm() {
- if (mFrameParallelMode) {
- // Flush decoder by passing nullptr data ptr and 0 size.
- // Ideally, this should never fail.
- if (vpx_codec_decode(mCodecCtx, nullptr, 0, nullptr, 0)) {
- ALOGE("Failed to flush on2 decoder.");
- return C2_CORRUPTED;
- }
- }
-
- // Drop all the decoded frames in decoder.
- vpx_codec_iter_t iter = nullptr;
- while (vpx_codec_get_frame(mCodecCtx, &iter)) {
- }
-
- mSignalledError = false;
- mSignalledOutputEos = false;
- return C2_OK;
-}
-
-static int GetCPUCoreCount() {
- int cpuCoreCount = 1;
-#if defined(_SC_NPROCESSORS_ONLN)
- cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
-#else
- // _SC_NPROC_ONLN must be defined...
- cpuCoreCount = sysconf(_SC_NPROC_ONLN);
-#endif
- CHECK(cpuCoreCount >= 1);
- ALOGV("Number of CPU cores: %d", cpuCoreCount);
- return cpuCoreCount;
-}
-
-status_t C2SoftVpx::initDecoder() {
-#ifdef VP9
- mMode = MODE_VP9;
-#else
- mMode = MODE_VP8;
-#endif
-
- mWidth = 320;
- mHeight = 240;
- mFrameParallelMode = false;
- mSignalledOutputEos = false;
- mSignalledError = false;
-
- mCodecCtx = new vpx_codec_ctx_t;
-
- vpx_codec_dec_cfg_t cfg;
- memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
- cfg.threads = GetCPUCoreCount();
-
- vpx_codec_flags_t flags;
- memset(&flags, 0, sizeof(vpx_codec_flags_t));
- if (mFrameParallelMode) flags |= VPX_CODEC_USE_FRAME_THREADING;
-
- vpx_codec_err_t vpx_err;
- if ((vpx_err = vpx_codec_dec_init(
- mCodecCtx, mMode == MODE_VP8 ? &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo,
- &cfg, flags))) {
- ALOGE("on2 decoder failed to initialize. (%d)", vpx_err);
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-status_t C2SoftVpx::destroyDecoder() {
- if (mCodecCtx) {
- vpx_codec_destroy(mCodecCtx);
- delete mCodecCtx;
- mCodecCtx = nullptr;
- }
-
- return OK;
-}
-
-void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-void C2SoftVpx::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2GraphicBlock> &block) {
- std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(block,
- C2Rect(mWidth, mHeight));
- auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
- uint32_t flags = 0;
- if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
- (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
- flags |= C2FrameData::FLAG_END_OF_STREAM;
- ALOGV("signalling eos");
- }
- work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- };
- if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
- fillWork(work);
- } else {
- finish(index, fillWork);
- }
-}
-
-void C2SoftVpx::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- bool codecConfig = ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) !=0);
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
- inSize, (int)work->input.ordinal.timestamp.peeku(),
- (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
-
- // Software VP9 Decoder does not need the Codec Specific Data (CSD)
- // (specified in http://www.webmproject.org/vp9/profiles/). Ignore it if
- // it was passed.
- if (codecConfig) {
- // Ignore CSD buffer for VP9.
- if (mMode == MODE_VP9) {
- fillEmptyWork(work);
- return;
- } else {
- // Tolerate the CSD buffer for VP8. This is a workaround
- // for b/28689536. continue
- ALOGW("WARNING: Got CSD buffer for VP8. Continue");
- }
- }
-
- uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
- int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
-
- if (inSize) {
- vpx_codec_err_t err = vpx_codec_decode(
- mCodecCtx, bitstream, inSize, &frameIndex, 0);
- if (err != VPX_CODEC_OK) {
- ALOGE("on2 decoder failed to decode frame. err: %d", err);
- work->result = C2_CORRUPTED;
- mSignalledError = true;
- return;
- }
- }
-
- (void)outputBuffer(pool, work);
-
- if (eos) {
- drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
- mSignalledOutputEos = true;
- } else if (!inSize) {
- fillEmptyWork(work);
- }
-}
-
-static void copyOutputBufferToYV12Frame(uint8_t *dst,
- const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- uint32_t width, uint32_t height, int32_t bpp) {
- size_t dstYStride = align(width, 16) * bpp ;
- size_t dstUVStride = align(dstYStride / 2, 16);
- uint8_t *dstStart = dst;
-
- for (size_t i = 0; i < height; ++i) {
- memcpy(dst, srcY, width * bpp);
- srcY += srcYStride;
- dst += dstYStride;
- }
-
- dst = dstStart + dstYStride * height;
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dst, srcV, width / 2 * bpp);
- srcV += srcVStride;
- dst += dstUVStride;
- }
-
- dst = dstStart + (dstYStride * height) + (dstUVStride * height / 2);
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dst, srcU, width / 2 * bpp);
- srcU += srcUStride;
- dst += dstUVStride;
- }
-}
-
-bool C2SoftVpx::outputBuffer(
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work)
-{
- if (!(work && pool)) return false;
-
- vpx_codec_iter_t iter = nullptr;
- vpx_image_t *img = vpx_codec_get_frame(mCodecCtx, &iter);
-
- if (!img) return false;
-
- mWidth = img->d_w;
- mHeight = img->d_h;
-
- CHECK(img->fmt == VPX_IMG_FMT_I420 || img->fmt == VPX_IMG_FMT_I42016);
- int32_t bpp = 1;
- if (img->fmt == VPX_IMG_FMT_I42016) {
- bpp = 2;
- }
-
- std::shared_ptr<C2GraphicBlock> block;
- uint32_t format = HAL_PIXEL_FORMAT_YV12;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16) * bpp, mHeight, format, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchGraphicBlock for Output failed with status %d", err);
- work->result = err;
- return false;
- }
-
- C2GraphicView wView = block->map().get();
- if (wView.error()) {
- ALOGE("graphic view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return false;
- }
-
- ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d",
- block->width(), block->height(), mWidth, mHeight, (int)*(int64_t *)img->user_priv);
-
- uint8_t *dst = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
- size_t srcYStride = img->stride[VPX_PLANE_Y];
- size_t srcUStride = img->stride[VPX_PLANE_U];
- size_t srcVStride = img->stride[VPX_PLANE_V];
- const uint8_t *srcY = (const uint8_t *)img->planes[VPX_PLANE_Y];
- const uint8_t *srcU = (const uint8_t *)img->planes[VPX_PLANE_U];
- const uint8_t *srcV = (const uint8_t *)img->planes[VPX_PLANE_V];
- copyOutputBufferToYV12Frame(dst, srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride, mWidth, mHeight, bpp);
-
- finishWork(*(int64_t *)img->user_priv, work, std::move(block));
- return true;
-}
-
-c2_status_t C2SoftVpx::drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work) {
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- while ((outputBuffer(pool, work))) {
- }
-
- if (drainMode == DRAIN_COMPONENT_WITH_EOS &&
- work && work->workletsProcessed == 0u) {
- fillEmptyWork(work);
- }
-
- return C2_OK;
-}
-c2_status_t C2SoftVpx::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- return drainInternal(drainMode, pool, nullptr);
-}
-
-class C2SoftVpxFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftVpx(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftVpxFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftVpxFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/on2/dec/C2SoftVpx.h b/media/libstagefright/codecs/on2/dec/C2SoftVpx.h
deleted file mode 100644
index b5d4e21..0000000
--- a/media/libstagefright/codecs/on2/dec/C2SoftVpx.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_VPX_H_
-#define C2_SOFT_VPX_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-#include "vpx/vpx_decoder.h"
-#include "vpx/vp8dx.h"
-
-namespace android {
-
-struct C2SoftVpx : public SimpleC2Component {
- C2SoftVpx(const char *name, c2_node_id_t id);
- virtual ~C2SoftVpx();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
- private:
- enum {
- MODE_VP8,
- MODE_VP9,
- } mMode;
-
- vpx_codec_ctx_t *mCodecCtx;
- bool mFrameParallelMode; // Frame parallel is only supported by VP9 decoder.
-
- uint32_t mWidth;
- uint32_t mHeight;
- bool mSignalledOutputEos;
- bool mSignalledError;
-
- status_t initDecoder();
- status_t destroyDecoder();
- void finishWork(uint64_t index, const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2GraphicBlock> &block);
- bool outputBuffer(
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work);
- c2_status_t drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work);
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftVpx);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_VPX_H_
diff --git a/media/libstagefright/codecs/opus/dec/Android.bp b/media/libstagefright/codecs/opus/dec/Android.bp
index 38d72e6..43318f2 100644
--- a/media/libstagefright/codecs/opus/dec/Android.bp
+++ b/media/libstagefright/codecs/opus/dec/Android.bp
@@ -1,40 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2opusdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftOpus.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libopus",
- ],
-}
-
-cc_library_shared {
name: "libstagefright_soft_opusdec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/opus/dec/C2SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/C2SoftOpus.cpp
deleted file mode 100644
index 47fb6de..0000000
--- a/media/libstagefright/codecs/opus/dec/C2SoftOpus.cpp
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftOpus"
-#include <utils/Log.h>
-
-#include "C2SoftOpus.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-extern "C" {
- #include <opus.h>
- #include <opus_multistream.h>
-}
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.opus.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_OPUS)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftOpus::C2SoftOpus(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mDecoder(nullptr) {
-}
-
-C2SoftOpus::~C2SoftOpus() {
- onRelease();
-}
-
-c2_status_t C2SoftOpus::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_NO_MEMORY;
-}
-
-c2_status_t C2SoftOpus::onStop() {
- if (mDecoder) {
- opus_multistream_decoder_destroy(mDecoder);
- mDecoder = nullptr;
- }
- memset(&mHeader, 0, sizeof(mHeader));
- mCodecDelay = 0;
- mSeekPreRoll = 0;
- mSamplesToDiscard = 0;
- mInputBufferCount = 0;
- mSignalledError = false;
- mSignalledOutputEos = false;
-
- return C2_OK;
-}
-
-void C2SoftOpus::onReset() {
- (void)onStop();
-}
-
-void C2SoftOpus::onRelease() {
- if (mDecoder) {
- opus_multistream_decoder_destroy(mDecoder);
- mDecoder = nullptr;
- }
-}
-
-status_t C2SoftOpus::initDecoder() {
- memset(&mHeader, 0, sizeof(mHeader));
- mCodecDelay = 0;
- mSeekPreRoll = 0;
- mSamplesToDiscard = 0;
- mInputBufferCount = 0;
- mSignalledError = false;
- mSignalledOutputEos = false;
-
- return OK;
-}
-
-c2_status_t C2SoftOpus::onFlush_sm() {
- if (mDecoder) {
- opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
- mSamplesToDiscard = mSeekPreRoll;
- mSignalledOutputEos = false;
- }
- return C2_OK;
-}
-
-c2_status_t C2SoftOpus::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- return C2_OK;
-}
-
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-static uint16_t ReadLE16(const uint8_t *data, size_t data_size,
- uint32_t read_offset) {
- if (read_offset + 1 > data_size)
- return 0;
- uint16_t val;
- val = data[read_offset];
- val |= data[read_offset + 1] << 8;
- return val;
-}
-
-static const int kRate = 48000;
-
-// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
-// mappings for up to 8 channels. This information is part of the Vorbis I
-// Specification:
-// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
-static const int kMaxChannels = 8;
-
-// Maximum packet size used in Xiph's opusdec.
-static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
-
-// Default audio output channel layout. Used to initialize |stream_map| in
-// OpusHeader, and passed to opus_multistream_decoder_create() when the header
-// does not contain mapping information. The values are valid only for mono and
-// stereo output: Opus streams with more than 2 channels require a stream map.
-static const int kMaxChannelsWithDefaultLayout = 2;
-static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 };
-
-// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
-static bool ParseOpusHeader(const uint8_t *data, size_t data_size,
- OpusHeader* header) {
- // Size of the Opus header excluding optional mapping information.
- const size_t kOpusHeaderSize = 19;
-
- // Offset to the channel count byte in the Opus header.
- const size_t kOpusHeaderChannelsOffset = 9;
-
- // Offset to the pre-skip value in the Opus header.
- const size_t kOpusHeaderSkipSamplesOffset = 10;
-
- // Offset to the gain value in the Opus header.
- const size_t kOpusHeaderGainOffset = 16;
-
- // Offset to the channel mapping byte in the Opus header.
- const size_t kOpusHeaderChannelMappingOffset = 18;
-
- // Opus Header contains a stream map. The mapping values are in the header
- // beyond the always present |kOpusHeaderSize| bytes of data. The mapping
- // data contains stream count, coupling information, and per channel mapping
- // values:
- // - Byte 0: Number of streams.
- // - Byte 1: Number coupled.
- // - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping
- // values.
- const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize;
- const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1;
- const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2;
-
- if (data_size < kOpusHeaderSize) {
- ALOGE("Header size is too small.");
- return false;
- }
- header->channels = *(data + kOpusHeaderChannelsOffset);
- if (header->channels <= 0 || header->channels > kMaxChannels) {
- ALOGE("Invalid Header, wrong channel count: %d", header->channels);
- return false;
- }
-
- header->skip_samples = ReadLE16(data,
- data_size,
- kOpusHeaderSkipSamplesOffset);
-
- header->gain_db = static_cast<int16_t>(ReadLE16(data,
- data_size,
- kOpusHeaderGainOffset));
-
- header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset);
- if (!header->channel_mapping) {
- if (header->channels > kMaxChannelsWithDefaultLayout) {
- ALOGE("Invalid Header, missing stream map.");
- return false;
- }
- header->num_streams = 1;
- header->num_coupled = header->channels > 1;
- header->stream_map[0] = 0;
- header->stream_map[1] = 1;
- return true;
- }
- if (data_size < kOpusHeaderStreamMapOffset + header->channels) {
- ALOGE("Invalid stream map; insufficient data for current channel "
- "count: %d", header->channels);
- return false;
- }
- header->num_streams = *(data + kOpusHeaderNumStreamsOffset);
- header->num_coupled = *(data + kOpusHeaderNumCoupledOffset);
- if (header->num_streams + header->num_coupled != header->channels) {
- ALOGE("Inconsistent channel mapping.");
- return false;
- }
- for (int i = 0; i < header->channels; ++i)
- header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i);
- return true;
-}
-
-// Convert nanoseconds to number of samples.
-static uint64_t ns_to_samples(uint64_t ns, int rate) {
- return static_cast<double>(ns) * rate / 1000000000;
-}
-
-void C2SoftOpus::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = C2_CORRUPTED;
- return;
- }
- if (inSize == 0) {
- fillEmptyWork(work);
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
- const uint8_t *data = rView.data() + inOffset;
- if (mInputBufferCount < 3) {
- if (mInputBufferCount == 0) {
- if (!ParseOpusHeader(data, inSize, &mHeader)) {
- ALOGE("Encountered error while Parsing Opus Header.");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- 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) {
- ALOGE("opus_multistream_decoder_create failed status = %s",
- opus_strerror(status));
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- status = opus_multistream_decoder_ctl(mDecoder,
- OPUS_SET_GAIN(mHeader.gain_db));
- if (status != OPUS_OK) {
- ALOGE("Failed to set OPUS header gain; status = %s",
- opus_strerror(status));
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- } else {
- if (inSize < 8) {
- ALOGE("Input sample size is too small.");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- int64_t samples = ns_to_samples( *(reinterpret_cast<int64_t*>
- (const_cast<uint8_t *> (data))), kRate);
- if (mInputBufferCount == 1) {
- mCodecDelay = samples;
- mSamplesToDiscard = mCodecDelay;
- }
- else {
- mSeekPreRoll = samples;
- }
- }
-
- ++mInputBufferCount;
- fillEmptyWork(work);
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
-
- // Ignore CSD re-submissions.
- if ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
- fillEmptyWork(work);
- return;
- }
-
- // When seeking to zero, |mCodecDelay| samples has to be discarded
- // instead of |mSeekPreRoll| samples (as we would when seeking to any
- // other timestamp).
- if (work->input.ordinal.timestamp.peeku() == 0) mSamplesToDiscard = mCodecDelay;
-
- std::shared_ptr<C2LinearBlock> block;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(
- kMaxNumSamplesPerBuffer * kMaxChannels * sizeof(int16_t),
- usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = C2_CORRUPTED;
- return;
- }
-
- int numSamples = opus_multistream_decode(mDecoder,
- data,
- inSize,
- reinterpret_cast<int16_t *> (wView.data()),
- kMaxOpusOutputPacketSizeSamples,
- 0);
- if (numSamples < 0) {
- ALOGE("opus_multistream_decode returned numSamples %d", numSamples);
- numSamples = 0;
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
-
- int outOffset = 0;
- if (mSamplesToDiscard > 0) {
- if (mSamplesToDiscard > numSamples) {
- mSamplesToDiscard -= numSamples;
- numSamples = 0;
- } else {
- numSamples -= mSamplesToDiscard;
- outOffset = mSamplesToDiscard * sizeof(int16_t) * mHeader.channels;
- mSamplesToDiscard = 0;
- }
- }
-
- if (numSamples) {
- int outSize = numSamples * sizeof(int16_t) * mHeader.channels;
- ALOGV("out buffer attr. offset %d size %d ", outOffset, outSize);
-
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, outOffset, outSize));
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- } else {
- fillEmptyWork(work);
- block.reset();
- }
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-class C2SoftOpusDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftOpus(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftOpusDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftOpusDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/opus/dec/C2SoftOpus.h b/media/libstagefright/codecs/opus/dec/C2SoftOpus.h
deleted file mode 100644
index 70ad2de..0000000
--- a/media/libstagefright/codecs/opus/dec/C2SoftOpus.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_OPUS_H_
-#define C2_SOFT_OPUS_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-struct OpusMSDecoder;
-
-namespace android {
-
-struct OpusHeader {
- int channels;
- int skip_samples;
- int channel_mapping;
- int num_streams;
- int num_coupled;
- int16_t gain_db;
- uint8_t stream_map[8];
-};
-
-struct C2SoftOpus : public SimpleC2Component {
- C2SoftOpus(const char *name, c2_node_id_t id);
- virtual ~C2SoftOpus();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-private:
- enum {
- kMaxNumSamplesPerBuffer = 960 * 6
- };
-
- OpusMSDecoder *mDecoder;
- OpusHeader mHeader;
-
- int64_t mCodecDelay;
- int64_t mSeekPreRoll;
- int64_t mSamplesToDiscard;
- size_t mInputBufferCount;
- bool mSignalledError;
- bool mSignalledOutputEos;
-
- status_t initDecoder();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftOpus);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_OPUS_H_
diff --git a/media/libstagefright/codecs/raw/Android.bp b/media/libstagefright/codecs/raw/Android.bp
index c431c18..c8d7d00 100644
--- a/media/libstagefright/codecs/raw/Android.bp
+++ b/media/libstagefright/codecs/raw/Android.bp
@@ -35,38 +35,3 @@
],
compile_multilib: "32",
}
-
-cc_library_shared {
- name: "libstagefright_soft_c2rawdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftRaw.cpp",],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- ],
-}
diff --git a/media/libstagefright/codecs/raw/C2SoftRaw.cpp b/media/libstagefright/codecs/raw/C2SoftRaw.cpp
deleted file mode 100644
index 91b920d..0000000
--- a/media/libstagefright/codecs/raw/C2SoftRaw.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftRAW"
-#include <utils/Log.h>
-
-#include "C2SoftRaw.h"
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.raw.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftRaw::C2SoftRaw(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)) {
-}
-
-C2SoftRaw::~C2SoftRaw() {
- onRelease();
-}
-
-c2_status_t C2SoftRaw::onInit() {
- mSignalledEos = false;
- return C2_OK;
-}
-
-c2_status_t C2SoftRaw::onStop() {
- mSignalledEos = false;
- return C2_OK;
-}
-
-void C2SoftRaw::onReset() {
- (void)onStop();
-}
-
-void C2SoftRaw::onRelease() {
-}
-
-c2_status_t C2SoftRaw::onFlush_sm() {
- return onStop();
-}
-
-void C2SoftRaw::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void)pool;
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- size_t inSize = inBuffer.size();
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
-
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- if (inSize != 0) {
- work->worklets.front()->output.buffers.push_back(work->input.buffers[0]);
- }
- work->workletsProcessed = 1u;
- if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
- mSignalledEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-c2_status_t C2SoftRaw::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- return C2_OK;
-}
-
-class C2SoftRawDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftRaw(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftRawDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftRawDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/raw/C2SoftRaw.h b/media/libstagefright/codecs/raw/C2SoftRaw.h
deleted file mode 100644
index f7d2cfd..0000000
--- a/media/libstagefright/codecs/raw/C2SoftRaw.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_RAW_H_
-#define C2_SOFT_RAW_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-
-struct C2SoftRaw : public SimpleC2Component {
- C2SoftRaw(const char *name, c2_node_id_t id);
- virtual ~C2SoftRaw();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-private:
- bool mSignalledEos;
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftRaw);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_RAW_H_
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.bp b/media/libstagefright/codecs/vorbis/dec/Android.bp
index 78dd61b..a9265cb 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.bp
+++ b/media/libstagefright/codecs/vorbis/dec/Android.bp
@@ -1,40 +1,4 @@
cc_library_shared {
- name: "libstagefright_soft_c2vorbisdec",
-// vendor_available: true,
-// vndk: {
-// enabled: true,
-// },
-
- srcs: ["C2SoftVorbis.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- "unsigned-integer-overflow",
- ],
- cfi: true,
- diag: {
- cfi: true,
- },
- },
-
- shared_libs: [
- "liblog",
- "libutils",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
- "libstagefright_foundation",
- "libstagefright_simple_c2component",
- "libvorbisidec",
- ],
-}
-
-cc_library_shared {
name: "libstagefright_soft_vorbisdec",
vendor_available: true,
vndk: {
diff --git a/media/libstagefright/codecs/vorbis/dec/C2SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/C2SoftVorbis.cpp
deleted file mode 100644
index 8342725..0000000
--- a/media/libstagefright/codecs/vorbis/dec/C2SoftVorbis.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2018 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 "C2SoftVorbis"
-#include <utils/Log.h>
-
-#include <C2PlatformSupport.h>
-#include <SimpleC2Interface.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/MediaDefs.h>
-
-#include "C2SoftVorbis.h"
-
-extern "C" {
- #include <Tremolo/codec_internal.h>
-
- int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
- int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
- int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
-}
-
-namespace android {
-
-constexpr char kComponentName[] = "c2.google.vorbis.decoder";
-
-static std::shared_ptr<C2ComponentInterface> BuildIntf(
- const char *name, c2_node_id_t id,
- std::function<void(C2ComponentInterface*)> deleter =
- std::default_delete<C2ComponentInterface>()) {
- return SimpleC2Interface::Builder(name, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .inputMediaType(MEDIA_MIMETYPE_AUDIO_VORBIS)
- .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
- .build();
-}
-
-C2SoftVorbis::C2SoftVorbis(const char *name, c2_node_id_t id)
- : SimpleC2Component(BuildIntf(name, id)),
- mState(nullptr),
- mVi(nullptr) {
-}
-
-C2SoftVorbis::~C2SoftVorbis() {
- onRelease();
-}
-
-c2_status_t C2SoftVorbis::onInit() {
- status_t err = initDecoder();
- return err == OK ? C2_OK : C2_NO_MEMORY;
-}
-
-c2_status_t C2SoftVorbis::onStop() {
- if (mState) vorbis_dsp_clear(mState);
- if (mVi) vorbis_info_clear(mVi);
- mNumFramesLeftOnPage = -1;
- mNumChannels = 1;
- mSamplingRate = 48000;
- mInputBufferCount = 0;
- mSignalledOutputEos = false;
- mSignalledError = false;
-
- return C2_OK;
-}
-
-void C2SoftVorbis::onReset() {
- (void)onStop();
-}
-
-void C2SoftVorbis::onRelease() {
- if (mState) {
- vorbis_dsp_clear(mState);
- delete mState;
- mState = nullptr;
- }
-
- if (mVi) {
- vorbis_info_clear(mVi);
- delete mVi;
- mVi = nullptr;
- }
-}
-
-status_t C2SoftVorbis::initDecoder() {
- mVi = new vorbis_info{};
- if (!mVi) return NO_MEMORY;
- vorbis_info_clear(mVi);
-
- mState = new vorbis_dsp_state{};
- if (!mState) return NO_MEMORY;
- vorbis_dsp_clear(mState);
-
- mNumFramesLeftOnPage = -1;
- mNumChannels = 1;
- mSamplingRate = 48000;
- mInputBufferCount = 0;
- mSignalledError = false;
- mSignalledOutputEos = false;
-
- return OK;
-}
-
-c2_status_t C2SoftVorbis::onFlush_sm() {
- mNumFramesLeftOnPage = -1;
- mSignalledOutputEos = false;
- if (mState) vorbis_dsp_restart(mState);
-
- return C2_OK;
-}
-
-c2_status_t C2SoftVorbis::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
- (void) pool;
- if (drainMode == NO_DRAIN) {
- ALOGW("drain with NO_DRAIN: no-op");
- return C2_OK;
- }
- if (drainMode == DRAIN_CHAIN) {
- ALOGW("DRAIN_CHAIN not supported");
- return C2_OMITTED;
- }
-
- return C2_OK;
-}
-
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
-}
-
-static void makeBitReader(
- const void *data, size_t size,
- ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) {
- buf->data = (uint8_t *)data;
- buf->size = size;
- buf->refcount = 1;
- buf->ptr.owner = nullptr;
-
- ref->buffer = buf;
- ref->begin = 0;
- ref->length = size;
- ref->next = nullptr;
-
- oggpack_readinit(bits, ref);
-}
-
-// (CHECK!) multiframe is tricky. decode call doesnt return the number of bytes
-// consumed by the component. Also it is unclear why numPageFrames is being
-// tagged at the end of input buffers for new pages. Refer lines 297-300 in
-// SimpleDecodingSource.cpp
-void C2SoftVorbis::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
- work->result = C2_OK;
- work->workletsProcessed = 0u;
- if (mSignalledError || mSignalledOutputEos) {
- work->result = C2_BAD_VALUE;
- return;
- }
-
- const C2ConstLinearBlock inBuffer = work->input.buffers[0]->data().linearBlocks().front();
- bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- size_t inOffset = inBuffer.offset();
- size_t inSize = inBuffer.size();
- C2ReadView rView = inBuffer.map().get();
- if (inSize && rView.error()) {
- ALOGE("read view map failed %d", rView.error());
- work->result = rView.error();
- return;
- }
-
- if (inSize == 0) {
- fillEmptyWork(work);
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
-
- ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
- (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
- const uint8_t *data = rView.data() + inOffset;
- if (mInputBufferCount < 2) {
- if (inSize < 7 || memcmp(&data[1], "vorbis", 6)) {
- ALOGE("unexpected first 7 bytes in CSD");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
-
- ogg_buffer buf;
- ogg_reference ref;
- oggpack_buffer bits;
-
- // skip 7 <type + "vorbis"> bytes
- makeBitReader((const uint8_t *)data + 7, inSize - 7, &buf, &ref, &bits);
- if (mInputBufferCount == 0) {
- if (data[0] != 1) {
- ALOGE("unexpected type received %d", data[0]);
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- vorbis_info_init(mVi);
- if (0 != _vorbis_unpack_info(mVi, &bits)) {
- ALOGE("Encountered error while unpacking info");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- if (mVi->rate != mSamplingRate ||
- mVi->channels != mNumChannels) {
- ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels);
- mSamplingRate = mVi->rate;
- mNumChannels = mVi->channels;
- }
- } else {
- if (data[0] != 5) {
- ALOGE("unexpected type received %d", data[0]);
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- if (0 != _vorbis_unpack_books(mVi, &bits)) {
- ALOGE("Encountered error while unpacking books");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- if (0 != vorbis_dsp_init(mState, mVi)) {
- ALOGE("Encountered error while dsp init");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- }
- ++mInputBufferCount;
- fillEmptyWork(work);
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
- return;
- }
- int32_t numPageFrames = 0;
- if (inSize < sizeof(numPageFrames)) {
- ALOGE("input header has size %zu, expected %zu", inSize, sizeof(numPageFrames));
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- }
- memcpy(&numPageFrames, data + inSize - sizeof(numPageFrames), sizeof(numPageFrames));
- inSize -= sizeof(numPageFrames);
- if (numPageFrames >= 0) {
- mNumFramesLeftOnPage = numPageFrames;
- }
-
- ogg_buffer buf;
- buf.data = const_cast<unsigned char*>(data);
- buf.size = inSize;
- buf.refcount = 1;
- buf.ptr.owner = nullptr;
-
- ogg_reference ref;
- ref.buffer = &buf;
- ref.begin = 0;
- ref.length = buf.size;
- ref.next = nullptr;
-
- ogg_packet pack;
- pack.packet = &ref;
- pack.bytes = ref.length;
- pack.b_o_s = 0;
- pack.e_o_s = 0;
- pack.granulepos = 0;
- pack.packetno = 0;
-
- size_t maxSamplesInBuffer = kMaxNumSamplesPerChannel * mVi->channels;
- size_t outCapacity = maxSamplesInBuffer * sizeof(int16_t);
- std::shared_ptr<C2LinearBlock> block;
- C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &block);
- if (err != C2_OK) {
- ALOGE("fetchLinearBlock for Output failed with status %d", err);
- work->result = C2_NO_MEMORY;
- return;
- }
- C2WriteView wView = block->map().get();
- if (wView.error()) {
- ALOGE("write view map failed %d", wView.error());
- work->result = wView.error();
- return;
- }
-
- int numFrames = 0;
- int ret = vorbis_dsp_synthesis(mState, &pack, 1);
- if (0 != ret) {
- ALOGE("vorbis_dsp_synthesis returned %d", ret);
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- return;
- } else {
- numFrames = vorbis_dsp_pcmout(
- mState, reinterpret_cast<int16_t *> (wView.data()),
- kMaxNumSamplesPerChannel);
- if (numFrames < 0) {
- ALOGD("vorbis_dsp_pcmout returned %d", numFrames);
- numFrames = 0;
- }
- }
-
- if (mNumFramesLeftOnPage >= 0) {
- if (numFrames > mNumFramesLeftOnPage) {
- ALOGV("discarding %d frames at end of page", numFrames - mNumFramesLeftOnPage);
- numFrames = mNumFramesLeftOnPage;
- }
- mNumFramesLeftOnPage -= numFrames;
- }
-
- if (numFrames) {
- int outSize = numFrames * sizeof(int16_t) * mVi->channels;
-
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, 0, outSize));
- work->worklets.front()->output.ordinal = work->input.ordinal;
- work->workletsProcessed = 1u;
- } else {
- fillEmptyWork(work);
- block.reset();
- }
- if (eos) {
- mSignalledOutputEos = true;
- ALOGV("signalled EOS");
- }
-}
-
-class C2SoftVorbisDecFactory : public C2ComponentFactory {
-public:
- virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftVorbis(kComponentName, id), deleter);
- return C2_OK;
- }
-
- virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
- *interface = BuildIntf(kComponentName, id, deleter);
- return C2_OK;
- }
-
- virtual ~C2SoftVorbisDecFactory() override = default;
-};
-
-} // namespace android
-
-extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
- ALOGV("in %s", __func__);
- return new ::android::C2SoftVorbisDecFactory();
-}
-
-extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
- ALOGV("in %s", __func__);
- delete factory;
-}
diff --git a/media/libstagefright/codecs/vorbis/dec/C2SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/C2SoftVorbis.h
deleted file mode 100644
index 340c235..0000000
--- a/media/libstagefright/codecs/vorbis/dec/C2SoftVorbis.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2018 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 C2_SOFT_VORBIS_H_
-#define C2_SOFT_VORBIS_H_
-
-#include <SimpleC2Component.h>
-
-#include <media/stagefright/foundation/ABase.h>
-
-struct vorbis_dsp_state;
-struct vorbis_info;
-
-namespace android {
-
-struct C2SoftVorbis : public SimpleC2Component {
- C2SoftVorbis(const char *name, c2_node_id_t id);
- virtual ~C2SoftVorbis();
-
- // From SimpleC2Component
- c2_status_t onInit() override;
- c2_status_t onStop() override;
- void onReset() override;
- void onRelease() override;
- c2_status_t onFlush_sm() override;
- void process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) override;
- c2_status_t drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) override;
-
- private:
- enum {
- kMaxNumSamplesPerChannel = 8192,
- };
-
- vorbis_dsp_state *mState;
- vorbis_info *mVi;
-
- int32_t mNumFramesLeftOnPage;
- int32_t mNumChannels;
- int32_t mSamplingRate;
- size_t mInputBufferCount;
- bool mSignalledError;
- bool mSignalledOutputEos;
-
- status_t initDecoder();
-
- DISALLOW_EVIL_CONSTRUCTORS(C2SoftVorbis);
-};
-
-} // namespace android
-
-#endif // C2_SOFT_VORBIS_H_
-
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 581e51b..8d486cf 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -9,6 +9,8 @@
"FLACDecoder.cpp",
],
+ export_include_dirs: [ "." ],
+
include_dirs: [
"external/flac/include",
"frameworks/av/media/libstagefright/include",
diff --git a/media/libstagefright/include/C2OMXNode.h b/media/libstagefright/include/C2OMXNode.h
deleted file mode 100644
index 3c007c4..0000000
--- a/media/libstagefright/include/C2OMXNode.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2018, 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 C2_OMX_NODE_H_
-#define C2_OMX_NODE_H_
-
-#include <atomic>
-
-#include <android/IOMXBufferSource.h>
-#include <media/IOMX.h>
-#include <media/OMXBuffer.h>
-
-namespace android {
-
-/**
- * IOmxNode implementation around codec 2.0 component, only to be used in
- * IGraphicBufferSource::configure. Only subset of IOmxNode API is implemented
- * and others are left as stub. As a result, one cannot expect this IOmxNode
- * to work in any other usage than IGraphicBufferSource.
- */
-struct C2OMXNode : public BnOMXNode {
- // TODO: this should take android::hardware::media::c2::V1_0::IComponent
- explicit C2OMXNode(const std::shared_ptr<C2Component> &comp);
- ~C2OMXNode() override = default;
-
- // IOMXNode
- status_t freeNode() override;
- status_t sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) override;
- status_t getParameter(
- OMX_INDEXTYPE index, void *params, size_t size) override;
- status_t setParameter(
- OMX_INDEXTYPE index, const void *params, size_t size) override;
- status_t getConfig(
- OMX_INDEXTYPE index, void *params, size_t size) override;
- status_t setConfig(
- OMX_INDEXTYPE index, const void *params, size_t size) override;
- status_t setPortMode(OMX_U32 port_index, IOMX::PortMode mode) override;
- status_t prepareForAdaptivePlayback(
- OMX_U32 portIndex, OMX_BOOL enable,
- OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) override;
- status_t configureVideoTunnelMode(
- OMX_U32 portIndex, OMX_BOOL tunneled,
- OMX_U32 audioHwSync, native_handle_t **sidebandHandle) override;
- status_t getGraphicBufferUsage(
- OMX_U32 port_index, OMX_U32* usage) override;
- status_t setInputSurface(
- const sp<IOMXBufferSource> &bufferSource) override;
- status_t allocateSecureBuffer(
- OMX_U32 port_index, size_t size, buffer_id *buffer,
- void **buffer_data, sp<NativeHandle> *native_handle) override;
- status_t useBuffer(
- OMX_U32 port_index, const OMXBuffer &omxBuf, buffer_id *buffer) override;
- status_t freeBuffer(
- OMX_U32 port_index, buffer_id buffer) override;
- status_t fillBuffer(
- buffer_id buffer, const OMXBuffer &omxBuf, int fenceFd) override;
- status_t emptyBuffer(
- buffer_id buffer, const OMXBuffer &omxBuf,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) override;
- status_t getExtensionIndex(
- const char *parameter_name,
- OMX_INDEXTYPE *index) override;
- status_t dispatchMessage(const omx_message &msg) override;
-
- sp<IOMXBufferSource> getSource();
-
-private:
- std::weak_ptr<C2Component> mComp;
- sp<IOMXBufferSource> mBufferSource;
- std::shared_ptr<C2Allocator> mAllocator;
- std::atomic_uint64_t mFrameIndex;
-};
-
-} // namespace android
-
-#endif // C2_OMX_NODE_H_
diff --git a/media/libstagefright/include/CCodecBufferChannel.h b/media/libstagefright/include/CCodecBufferChannel.h
deleted file mode 100644
index c8618db..0000000
--- a/media/libstagefright/include/CCodecBufferChannel.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef CCODEC_BUFFER_CHANNEL_H_
-
-#define CCODEC_BUFFER_CHANNEL_H_
-
-#include <map>
-#include <memory>
-#include <mutex>
-#include <vector>
-
-#include <C2Buffer.h>
-#include <C2Component.h>
-
-#include <media/stagefright/bqhelper/GraphicBufferSource.h>
-#include <media/stagefright/codec2/1.0/InputSurface.h>
-#include <media/stagefright/foundation/Mutexed.h>
-#include <media/stagefright/CodecBase.h>
-#include <media/ICrypto.h>
-
-#include "InputSurfaceWrapper.h"
-
-namespace android {
-
-using ::android::hardware::media::c2::V1_0::implementation::InputSurface;
-using ::android::hardware::media::c2::V1_0::implementation::InputSurfaceConnection;
-
-/**
- * BufferChannelBase implementation for CCodec.
- */
-class CCodecBufferChannel
- : public BufferChannelBase, public std::enable_shared_from_this<CCodecBufferChannel> {
-public:
- CCodecBufferChannel(const std::function<void(status_t, enum ActionCode)> &onError);
- virtual ~CCodecBufferChannel();
-
- // BufferChannelBase interface
- virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
- virtual status_t queueSecureInputBuffer(
- const sp<MediaCodecBuffer> &buffer,
- bool secure,
- const uint8_t *key,
- const uint8_t *iv,
- CryptoPlugin::Mode mode,
- CryptoPlugin::Pattern pattern,
- const CryptoPlugin::SubSample *subSamples,
- size_t numSubSamples,
- AString *errorDetailMsg) override;
- virtual status_t renderOutputBuffer(
- const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
- virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
- virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
- virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
-
- // Methods below are interface for CCodec to use.
-
- /**
- * Set the component object for buffer processing.
- */
- void setComponent(const std::shared_ptr<C2Component> &component);
-
- /**
- * Set output graphic surface for rendering.
- */
- status_t setSurface(const sp<Surface> &surface);
-
- /**
- * Set GraphicBufferSource object from which the component extracts input
- * buffers.
- */
- status_t setInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
-
- /**
- * Start queueing buffers to the component. This object should never queue
- * buffers before this call.
- */
- status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat);
-
- /**
- * Stop queueing buffers to the component. This object should never queue
- * buffers after this call, until start() is called.
- */
- void stop();
-
- void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork);
-
- /**
- * Notify input client about work done.
- *
- * @param workItems finished work item.
- */
- void onWorkDone(const std::unique_ptr<C2Work> &work);
-
- // Internal classes
- class Buffers;
- class InputBuffers;
- class OutputBuffers;
-
-private:
- class QueueGuard;
-
- /**
- * Special mutex-like object with the following properties:
- *
- * - At STOPPED state (initial, or after stop())
- * - QueueGuard object gets created at STOPPED state, and the client is
- * supposed to return immediately.
- * - At RUNNING state (after start())
- * - Each QueueGuard object
- */
- class QueueSync {
- public:
- /**
- * At construction the sync object is in STOPPED state.
- */
- inline QueueSync() : mCount(-1) {}
- ~QueueSync() = default;
-
- /**
- * Transition to RUNNING state when stopped. No-op if already in RUNNING
- * state.
- */
- void start();
-
- /**
- * At RUNNING state, wait until all QueueGuard object created during
- * RUNNING state are destroyed, and then transition to STOPPED state.
- * No-op if already in STOPPED state.
- */
- void stop();
-
- private:
- std::mutex mMutex;
- std::atomic_int32_t mCount;
-
- friend class CCodecBufferChannel::QueueGuard;
- };
-
- class QueueGuard {
- public:
- QueueGuard(QueueSync &sync);
- ~QueueGuard();
- inline bool isRunning() { return mRunning; }
-
- private:
- QueueSync &mSync;
- bool mRunning;
- };
-
- void feedInputBufferIfAvailable();
- status_t queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer);
-
- QueueSync mSync;
- sp<MemoryDealer> mDealer;
- sp<IMemory> mDecryptDestination;
- int32_t mHeapSeqNum;
-
- std::shared_ptr<C2Component> mComponent;
- std::function<void(status_t, enum ActionCode)> mOnError;
- std::shared_ptr<C2BlockPool> mInputAllocator;
- QueueSync mQueueSync;
-
- Mutexed<std::unique_ptr<InputBuffers>> mInputBuffers;
- Mutexed<std::unique_ptr<OutputBuffers>> mOutputBuffers;
-
- std::atomic_uint64_t mFrameIndex;
- std::atomic_uint64_t mFirstValidFrameIndex;
-
- sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
-
- struct OutputSurface {
- sp<Surface> surface;
- std::list<std::shared_ptr<C2Buffer>> bufferRefs;
- size_t maxBufferCount;
- };
- Mutexed<OutputSurface> mOutputSurface;
-
- std::shared_ptr<InputSurfaceWrapper> mInputSurface;
-
- inline bool hasCryptoOrDescrambler() {
- return mCrypto != NULL || mDescrambler != NULL;
- }
-};
-
-} // namespace android
-
-#endif // CCODEC_BUFFER_CHANNEL_H_
diff --git a/media/libstagefright/include/Codec2Buffer.h b/media/libstagefright/include/Codec2Buffer.h
deleted file mode 100644
index b2e3b1b..0000000
--- a/media/libstagefright/include/Codec2Buffer.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef CODEC2_BUFFER_H_
-
-#define CODEC2_BUFFER_H_
-
-#include <C2Buffer.h>
-
-#include <android/hardware/cas/native/1.0/types.h>
-#include <binder/IMemory.h>
-#include <media/hardware/VideoAPI.h>
-#include <media/MediaCodecBuffer.h>
-#include <media/ICrypto.h>
-
-namespace android {
-
-class Codec2Buffer : public MediaCodecBuffer {
-public:
- using MediaCodecBuffer::MediaCodecBuffer;
- ~Codec2Buffer() override = default;
-
- /**
- * \return C2Buffer object represents this buffer.
- */
- virtual std::shared_ptr<C2Buffer> asC2Buffer() = 0;
-
- /**
- * Test if we can copy the content of |buffer| into this object.
- *
- * \param buffer C2Buffer object to copy.
- * \return true if the content of buffer can be copied over to this buffer
- * false otherwise.
- */
- virtual bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
- (void)buffer;
- return false;
- }
-
- /**
- * Copy the content of |buffer| into this object. This method assumes that
- * canCopy() check already passed.
- *
- * \param buffer C2Buffer object to copy.
- * \return true if successful
- * false otherwise.
- */
- virtual bool copy(const std::shared_ptr<C2Buffer> &buffer) {
- (void)buffer;
- return false;
- }
-
-protected:
- /**
- * canCopy() implementation for linear buffers.
- */
- bool canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const;
-
- /**
- * copy() implementation for linear buffers.
- */
- bool copyLinear(const std::shared_ptr<C2Buffer> &buffer);
-};
-
-/**
- * MediaCodecBuffer implementation on top of local linear buffer. This cannot
- * cross process boundary so asC2Buffer() returns only nullptr.
- */
-class LocalLinearBuffer : public Codec2Buffer {
-public:
- using Codec2Buffer::Codec2Buffer;
-
- std::shared_ptr<C2Buffer> asC2Buffer() override { return nullptr; }
- bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
- bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
-};
-
-/**
- * MediaCodecBuffer implementation to be used only as a dummy wrapper around a
- * C2Buffer object.
- */
-class DummyContainerBuffer : public Codec2Buffer {
-public:
- DummyContainerBuffer(
- const sp<AMessage> &format,
- const std::shared_ptr<C2Buffer> &buffer = nullptr);
-
- std::shared_ptr<C2Buffer> asC2Buffer() override;
- bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
- bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
-
-private:
- std::shared_ptr<C2Buffer> mBufferRef;
-};
-
-/**
- * MediaCodecBuffer implementation wraps around C2LinearBlock.
- */
-class LinearBlockBuffer : public Codec2Buffer {
-public:
- /**
- * Allocate a new LinearBufferBlock wrapping around C2LinearBlock object.
- *
- * \param format mandatory buffer format for MediaCodecBuffer
- * \param block C2LinearBlock object to wrap around.
- * \return LinearBlockBuffer object with writable mapping.
- * nullptr if unsuccessful.
- */
- static sp<LinearBlockBuffer> Allocate(
- const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block);
-
- virtual ~LinearBlockBuffer() = default;
-
- std::shared_ptr<C2Buffer> asC2Buffer() override;
- bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
- bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
-
-private:
- LinearBlockBuffer(
- const sp<AMessage> &format,
- C2WriteView &&writeView,
- const std::shared_ptr<C2LinearBlock> &block);
- LinearBlockBuffer() = delete;
-
- C2WriteView mWriteView;
- std::shared_ptr<C2LinearBlock> mBlock;
-};
-
-/**
- * MediaCodecBuffer implementation wraps around C2ConstLinearBlock.
- */
-class ConstLinearBlockBuffer : public Codec2Buffer {
-public:
- /**
- * Allocate a new ConstLinearBlockBuffer wrapping around C2Buffer object.
- *
- * \param format mandatory buffer format for MediaCodecBuffer
- * \param buffer linear C2Buffer object to wrap around.
- * \return ConstLinearBlockBuffer object with readable mapping.
- * nullptr if unsuccessful.
- */
- static sp<ConstLinearBlockBuffer> Allocate(
- const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer);
-
- virtual ~ConstLinearBlockBuffer() = default;
-
- std::shared_ptr<C2Buffer> asC2Buffer() override;
-
-private:
- ConstLinearBlockBuffer(
- const sp<AMessage> &format,
- C2ReadView &&readView,
- const std::shared_ptr<C2Buffer> &buffer);
- ConstLinearBlockBuffer() = delete;
-
- C2ReadView mReadView;
- std::shared_ptr<C2Buffer> mBufferRef;
-};
-
-/**
- * MediaCodecBuffer implementation wraps around C2GraphicBlock.
- *
- * This object exposes the underlying bits via accessor APIs and "image-data"
- * metadata, created automatically at allocation time.
- */
-class GraphicBlockBuffer : public Codec2Buffer {
-public:
- /**
- * Allocate a new GraphicBlockBuffer wrapping around C2GraphicBlock object.
- * If |block| is not in good color formats, it allocates YV12 local buffer
- * and copies the content over at asC2Buffer().
- *
- * \param format mandatory buffer format for MediaCodecBuffer
- * \param block C2GraphicBlock object to wrap around.
- * \param alloc a function to allocate backing ABuffer if needed.
- * \return GraphicBlockBuffer object with writable mapping.
- * nullptr if unsuccessful.
- */
- static sp<GraphicBlockBuffer> Allocate(
- const sp<AMessage> &format,
- const std::shared_ptr<C2GraphicBlock> &block,
- std::function<sp<ABuffer>(size_t)> alloc);
-
- std::shared_ptr<C2Buffer> asC2Buffer() override;
-
- virtual ~GraphicBlockBuffer() = default;
-
-private:
- GraphicBlockBuffer(
- const sp<AMessage> &format,
- const sp<ABuffer> &buffer,
- C2GraphicView &&view,
- const std::shared_ptr<C2GraphicBlock> &block,
- const sp<ABuffer> &imageData,
- bool wrapped);
- GraphicBlockBuffer() = delete;
-
- inline MediaImage2 *imageData() { return (MediaImage2 *)mImageData->data(); }
-
- C2GraphicView mView;
- std::shared_ptr<C2GraphicBlock> mBlock;
- sp<ABuffer> mImageData;
- const bool mWrapped;
-};
-
-/**
- * MediaCodecBuffer implementation wraps around graphic C2Buffer object.
- *
- * This object exposes the underlying bits via accessor APIs and "image-data"
- * metadata, created automatically at allocation time.
- */
-class ConstGraphicBlockBuffer : public Codec2Buffer {
-public:
- /**
- * Allocate a new ConstGraphicBlockBuffer wrapping around C2Buffer object.
- * If |buffer| is not in good color formats, it allocates YV12 local buffer
- * and copies the content of |buffer| over to expose.
- *
- * \param format mandatory buffer format for MediaCodecBuffer
- * \param buffer graphic C2Buffer object to wrap around.
- * \param alloc a function to allocate backing ABuffer if needed.
- * \return ConstGraphicBlockBuffer object with readable mapping.
- * nullptr if unsuccessful.
- */
- static sp<ConstGraphicBlockBuffer> Allocate(
- const sp<AMessage> &format,
- const std::shared_ptr<C2Buffer> &buffer,
- std::function<sp<ABuffer>(size_t)> alloc);
-
- /**
- * Allocate a new ConstGraphicBlockBuffer which allocates YV12 local buffer
- * and copies the content of |buffer| over to expose.
- *
- * \param format mandatory buffer format for MediaCodecBuffer
- * \param alloc a function to allocate backing ABuffer if needed.
- * \return ConstGraphicBlockBuffer object with no wrapping buffer.
- */
- static sp<ConstGraphicBlockBuffer> AllocateEmpty(
- const sp<AMessage> &format,
- std::function<sp<ABuffer>(size_t)> alloc);
-
- std::shared_ptr<C2Buffer> asC2Buffer() override;
- bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
- bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
-
- virtual ~ConstGraphicBlockBuffer() = default;
-
-private:
- ConstGraphicBlockBuffer(
- const sp<AMessage> &format,
- const sp<ABuffer> &aBuffer,
- std::unique_ptr<const C2GraphicView> &&view,
- const std::shared_ptr<C2Buffer> &buffer,
- const sp<ABuffer> &imageData,
- bool wrapped);
- ConstGraphicBlockBuffer() = delete;
-
- sp<ABuffer> mImageData;
- std::unique_ptr<const C2GraphicView> mView;
- std::shared_ptr<C2Buffer> mBufferRef;
- const bool mWrapped;
-};
-
-/**
- * MediaCodecBuffer implementation wraps around C2LinearBlock for component
- * and IMemory for client. Underlying C2LinearBlock won't be mapped for secure
- * usecases..
- */
-class EncryptedLinearBlockBuffer : public Codec2Buffer {
-public:
- /**
- * Construct a new EncryptedLinearBufferBlock wrapping around C2LinearBlock
- * object and writable IMemory region.
- *
- * \param format mandatory buffer format for MediaCodecBuffer
- * \param block C2LinearBlock object to wrap around.
- * \param memory IMemory object to store encrypted content.
- * \param heapSeqNum Heap sequence number from ICrypto; -1 if N/A
- */
- EncryptedLinearBlockBuffer(
- const sp<AMessage> &format,
- const std::shared_ptr<C2LinearBlock> &block,
- const sp<IMemory> &memory,
- int32_t heapSeqNum = -1);
- EncryptedLinearBlockBuffer() = delete;
-
- virtual ~EncryptedLinearBlockBuffer() = default;
-
- std::shared_ptr<C2Buffer> asC2Buffer() override;
-
- /**
- * Fill the source buffer structure with appropriate value based on
- * internal IMemory object.
- *
- * \param source source buffer structure to fill.
- */
- void fillSourceBuffer(ICrypto::SourceBuffer *source);
- void fillSourceBuffer(
- hardware::cas::native::V1_0::SharedBuffer *source);
-
- /**
- * Copy the content of |decrypted| into C2LinearBlock inside. This shall
- * only be called in non-secure usecases.
- *
- * \param decrypted decrypted content to copy from.
- * \param length length of the content
- * \return true if successful
- * false otherwise.
- */
- bool copyDecryptedContent(const sp<IMemory> &decrypted, size_t length);
-
- /**
- * Copy the content of internal IMemory object into C2LinearBlock inside.
- * This shall only be called in non-secure usecases.
- *
- * \param length length of the content
- * \return true if successful
- * false otherwise.
- */
- bool copyDecryptedContentFromMemory(size_t length);
-
- /**
- * Return native handle of secure buffer understood by ICrypto.
- *
- * \return secure buffer handle
- */
- native_handle_t *handle() const;
-
-private:
-
- std::shared_ptr<C2LinearBlock> mBlock;
- sp<IMemory> mMemory;
- sp<hardware::HidlMemory> mHidlMemory;
- int32_t mHeapSeqNum;
-};
-
-} // namespace android
-
-#endif // CODEC2_BUFFER_H_
diff --git a/media/libstagefright/include/InputSurfaceWrapper.h b/media/libstagefright/include/InputSurfaceWrapper.h
deleted file mode 100644
index a4d8f29..0000000
--- a/media/libstagefright/include/InputSurfaceWrapper.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2018, 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 INPUT_SURFACE_WRAPPER_H_
-
-#define INPUT_SURFACE_WRAPPER_H_
-
-namespace android {
-
-/**
- * Wrapper interface around InputSurface.
- */
-class InputSurfaceWrapper {
-public:
- virtual ~InputSurfaceWrapper() = default;
-
- /**
- * Connect the surface with |comp| and start pushing buffers. A surface can
- * connect to at most one component at a time.
- *
- * \return OK successfully connected to |comp|
- * \return ALREADY_EXISTS already connected to another component.
- */
- virtual status_t connect(const std::shared_ptr<C2Component> &comp) = 0;
-
- /**
- * Disconnect the surface from the component if any.
- */
- virtual void disconnect() = 0;
-
- // TODO: intf()
-};
-
-} // namespace android
-
-#endif // INPUT_SURFACE_WRAPPER_H_
diff --git a/media/libstagefright/include/media/stagefright/CCodec.h b/media/libstagefright/include/media/stagefright/CCodec.h
deleted file mode 100644
index 86fbd3a..0000000
--- a/media/libstagefright/include/media/stagefright/CCodec.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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 C_CODEC_H_
-#define C_CODEC_H_
-
-#include <chrono>
-
-#include <C2Component.h>
-
-#include <android/native_window.h>
-#include <media/hardware/MetadataBufferType.h>
-#include <media/stagefright/foundation/Mutexed.h>
-#include <media/stagefright/CodecBase.h>
-#include <media/stagefright/FrameRenderTracker.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/SkipCutBuffer.h>
-#include <utils/NativeHandle.h>
-#include <hardware/gralloc.h>
-#include <nativebase/nativebase.h>
-
-namespace android {
-
-class CCodecBufferChannel;
-class InputSurfaceWrapper;
-struct MediaCodecInfo;
-
-class CCodec : public CodecBase {
-public:
- CCodec();
-
- virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
- virtual void initiateAllocateComponent(const sp<AMessage> &msg) override;
- virtual void initiateConfigureComponent(const sp<AMessage> &msg) override;
- virtual void initiateCreateInputSurface() override;
- virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface) override;
- virtual void initiateStart() override;
- virtual void initiateShutdown(bool keepComponentAllocated = false) override;
-
- virtual status_t setSurface(const sp<Surface> &surface) override;
-
- virtual void signalFlush() override;
- virtual void signalResume() override;
-
- virtual void signalSetParameters(const sp<AMessage> &msg) override;
- virtual void signalEndOfInputStream() override;
- virtual void signalRequestIDRFrame() override;
-
- void initiateReleaseIfStuck();
- void onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
-
-protected:
- virtual ~CCodec();
-
- virtual void onMessageReceived(const sp<AMessage> &msg) override;
-
-private:
- typedef std::chrono::time_point<std::chrono::steady_clock> TimePoint;
-
- status_t tryAndReportOnError(std::function<status_t()> job);
-
- void initiateStop();
- void initiateRelease(bool sendCallback = true);
-
- void allocate(const sp<MediaCodecInfo> &codecInfo);
- void configure(const sp<AMessage> &msg);
- void start();
- void stop();
- void flush();
- void release(bool sendCallback);
-
- void createInputSurface();
- void setInputSurface(const sp<PersistentSurface> &surface);
- status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
-
- void setDeadline(const TimePoint &deadline, const char *name);
-
- enum {
- kWhatAllocate,
- kWhatConfigure,
- kWhatStart,
- kWhatFlush,
- kWhatStop,
- kWhatRelease,
- kWhatCreateInputSurface,
- kWhatSetInputSurface,
- kWhatWorkDone,
- };
-
- enum {
- RELEASED,
- ALLOCATED,
- FLUSHED,
- RUNNING,
-
- ALLOCATING, // RELEASED -> ALLOCATED
- STARTING, // ALLOCATED -> RUNNING
- STOPPING, // RUNNING -> ALLOCATED
- FLUSHING, // RUNNING -> FLUSHED
- RESUMING, // FLUSHED -> RUNNING
- RELEASING, // {ANY EXCEPT RELEASED} -> RELEASED
- };
-
- struct State {
- inline State() : mState(RELEASED) {}
- inline int get() const { return mState; }
- inline void set(int newState) { mState = newState; }
-
- std::shared_ptr<C2Component> comp;
- private:
- int mState;
- };
-
- struct Formats {
- sp<AMessage> inputFormat;
- sp<AMessage> outputFormat;
- };
-
- struct NamedTimePoint {
- inline void set(
- const TimePoint &timePoint,
- const char *name) {
- mTimePoint = timePoint;
- mName = name;
- }
-
- inline TimePoint get() const { return mTimePoint; }
- inline const char *getName() const { return mName; }
- private:
- TimePoint mTimePoint;
- const char *mName;
- };
-
- Mutexed<State> mState;
- std::shared_ptr<CCodecBufferChannel> mChannel;
- std::shared_ptr<C2Component::Listener> mListener;
- Mutexed<NamedTimePoint> mDeadline;
- Mutexed<Formats> mFormats;
- Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
-
- DISALLOW_EVIL_CONSTRUCTORS(CCodec);
-};
-
-} // namespace android
-
-#endif // C_CODEC_H_
diff --git a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
deleted file mode 100644
index 30c189e..0000000
--- a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2018 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 CODEC2_INFO_BUILDER_H_
-#define CODEC2_INFO_BUILDER_H_
-
-#include <media/stagefright/MediaCodecList.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class Codec2InfoBuilder : public MediaCodecListBuilderBase {
-public:
- Codec2InfoBuilder() = default;
- ~Codec2InfoBuilder() override = default;
- status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
-};
-
-} // namespace android
-
-#endif // CODEC2_INFO_BUILDER_H_
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 675c932..54a7095 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -71,6 +71,8 @@
status_t getFileFormat(sp<AMessage> *format) const;
+ status_t getExifOffsetSize(off64_t *offset, size_t *size) const;
+
status_t selectTrack(size_t index, int64_t startTimeUs = -1ll,
MediaSource::ReadOptions::SeekMode mode =
MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
diff --git a/packages/MediaComponents/Android.mk b/packages/MediaComponents/Android.mk
index b6480a2..b0d8e7d 100644
--- a/packages/MediaComponents/Android.mk
+++ b/packages/MediaComponents/Android.mk
@@ -40,9 +40,6 @@
LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
-# TODO: Enable proguard (b/74090741)
-LOCAL_PROGUARD_ENABLED := disabled
-
LOCAL_MULTILIB := first
LOCAL_JAVA_LIBRARIES += android-support-annotations
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index 2b7c72a..89c29e6 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -48,6 +48,7 @@
import android.media.MediaSession2.CommandButton;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.OnDataSourceMissingHelper;
import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
import android.media.SessionToken2;
@@ -61,7 +62,6 @@
import android.os.ResultReceiver;
import android.support.annotation.GuardedBy;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.Log;
import java.lang.ref.WeakReference;
@@ -111,9 +111,13 @@
@GuardedBy("mLock")
private MediaPlaylistAgent mPlaylistAgent;
@GuardedBy("mLock")
+ private SessionPlaylistAgent mSessionPlaylistAgent;
+ @GuardedBy("mLock")
private VolumeProvider2 mVolumeProvider;
@GuardedBy("mLock")
private PlaybackInfo mPlaybackInfo;
+ @GuardedBy("mLock")
+ private OnDataSourceMissingHelper mDsmHelper;
/**
* Can be only called by the {@link Builder#build()}.
@@ -207,7 +211,7 @@
}
@Override
- public void updatePlayer_impl(MediaPlayerBase player, MediaPlaylistAgent playlistAgent,
+ public void updatePlayer_impl(@NonNull MediaPlayerBase player, MediaPlaylistAgent playlistAgent,
VolumeProvider2 volumeProvider) throws IllegalArgumentException {
ensureCallingThread();
if (player == null) {
@@ -225,9 +229,12 @@
oldPlayer = mPlayer;
oldAgent = mPlaylistAgent;
mPlayer = player;
- // TODO(jaewan): Replace this with the proper default agent (b/74090741)
if (agent == null) {
- agent = new MediaPlaylistAgent(mContext) {};
+ mSessionPlaylistAgent = new SessionPlaylistAgent(mContext, this, mPlayer);
+ if (mDsmHelper != null) {
+ mSessionPlaylistAgent.setOnDataSourceMissingHelper(mDsmHelper);
+ }
+ agent = mSessionPlaylistAgent;
}
mPlaylistAgent = agent;
mVolumeProvider = volumeProvider;
@@ -312,6 +319,7 @@
mPlayer = null;
agent = mPlaylistAgent;
mPlaylistAgent = null;
+ mSessionPlaylistAgent = null;
}
if (player != null) {
player.unregisterPlayerEventCallback(mPlayerEventCallback);
@@ -385,7 +393,7 @@
}
@Override
- public void skipToPlaylistItem_impl(MediaItem2 item) {
+ public void skipToPlaylistItem_impl(@NonNull MediaItem2 item) {
if (item == null) {
throw new IllegalArgumentException("item shouldn't be null");
}
@@ -418,7 +426,8 @@
}
@Override
- public void setCustomLayout_impl(ControllerInfo controller, List<CommandButton> layout) {
+ public void setCustomLayout_impl(@NonNull ControllerInfo controller,
+ @NonNull List<CommandButton> layout) {
ensureCallingThread();
if (controller == null) {
throw new IllegalArgumentException("controller shouldn't be null");
@@ -434,7 +443,8 @@
//////////////////////////////////////////////////////////////////////////////////////
@Override
- public void setAllowedCommands_impl(ControllerInfo controller, CommandGroup commands) {
+ public void setAllowedCommands_impl(@NonNull ControllerInfo controller,
+ @NonNull CommandGroup commands) {
if (controller == null) {
throw new IllegalArgumentException("controller shouldn't be null");
}
@@ -445,8 +455,8 @@
}
@Override
- public void sendCustomCommand_impl(ControllerInfo controller, Command command, Bundle args,
- ResultReceiver receiver) {
+ public void sendCustomCommand_impl(@NonNull ControllerInfo controller, @NonNull Command command,
+ Bundle args, ResultReceiver receiver) {
if (controller == null) {
throw new IllegalArgumentException("controller shouldn't be null");
}
@@ -457,7 +467,7 @@
}
@Override
- public void sendCustomCommand_impl(Command command, Bundle args) {
+ public void sendCustomCommand_impl(@NonNull Command command, Bundle args) {
if (command == null) {
throw new IllegalArgumentException("command shouldn't be null");
}
@@ -465,7 +475,7 @@
}
@Override
- public void setPlaylist_impl(List<MediaItem2> list, MediaMetadata2 metadata) {
+ public void setPlaylist_impl(@NonNull List<MediaItem2> list, MediaMetadata2 metadata) {
if (list == null) {
throw new IllegalArgumentException("list shouldn't be null");
}
@@ -489,7 +499,7 @@
}
@Override
- public void addPlaylistItem_impl(int index, MediaItem2 item) {
+ public void addPlaylistItem_impl(int index, @NonNull MediaItem2 item) {
if (index < 0) {
throw new IllegalArgumentException("index shouldn't be negative");
}
@@ -505,7 +515,7 @@
}
@Override
- public void removePlaylistItem_impl(MediaItem2 item) {
+ public void removePlaylistItem_impl(@NonNull MediaItem2 item) {
if (item == null) {
throw new IllegalArgumentException("item shouldn't be null");
}
@@ -518,7 +528,7 @@
}
@Override
- public void replacePlaylistItem_impl(int index, MediaItem2 item) {
+ public void replacePlaylistItem_impl(int index, @NonNull MediaItem2 item) {
if (index < 0) {
throw new IllegalArgumentException("index shouldn't be negative");
}
@@ -685,6 +695,29 @@
mSessionStub.notifyError(errorCode, extras);
}
+ @Override
+ public void setOnDataSourceMissingHelper_impl(@NonNull OnDataSourceMissingHelper helper) {
+ if (helper == null) {
+ throw new IllegalArgumentException("helper shouldn't be null");
+ }
+ synchronized (mLock) {
+ mDsmHelper = helper;
+ if (mSessionPlaylistAgent != null) {
+ mSessionPlaylistAgent.setOnDataSourceMissingHelper(helper);
+ }
+ }
+ }
+
+ @Override
+ public void clearOnDataSourceMissingHelper_impl() {
+ synchronized (mLock) {
+ mDsmHelper = null;
+ if (mSessionPlaylistAgent != null) {
+ mSessionPlaylistAgent.clearOnDataSourceMissingHelper();
+ }
+ }
+ }
+
///////////////////////////////////////////////////
// Protected or private methods
///////////////////////////////////////////////////
@@ -1022,7 +1055,7 @@
/**
* @return a new Command instance from the Bundle
*/
- public static Command fromBundle_impl(Context context, Bundle command) {
+ public static Command fromBundle_impl(Context context, @NonNull Bundle command) {
if (command == null) {
throw new IllegalArgumentException("command shouldn't be null");
}
@@ -1092,7 +1125,7 @@
}
@Override
- public void addCommand_impl(Command command) {
+ public void addCommand_impl(@NonNull Command command) {
if (command == null) {
throw new IllegalArgumentException("command shouldn't be null");
}
@@ -1129,7 +1162,7 @@
}
@Override
- public void removeCommand_impl(Command command) {
+ public void removeCommand_impl(@NonNull Command command) {
if (command == null) {
throw new IllegalArgumentException("command shouldn't be null");
}
@@ -1137,7 +1170,7 @@
}
@Override
- public boolean hasCommand_impl(Command command) {
+ public boolean hasCommand_impl(@NonNull Command command) {
if (command == null) {
throw new IllegalArgumentException("command shouldn't be null");
}
@@ -1217,7 +1250,7 @@
private final IMediaController2 mControllerBinder;
public ControllerInfoImpl(Context context, ControllerInfo instance, int uid,
- int pid, String packageName, IMediaController2 callback) {
+ int pid, @NonNull String packageName, @NonNull IMediaController2 callback) {
if (TextUtils.isEmpty(packageName)) {
throw new IllegalArgumentException("packageName shouldn't be empty");
}
@@ -1234,7 +1267,7 @@
// Ask server whether the controller is trusted.
// App cannot know this because apps cannot query enabled notification listener for
// another package, but system server can do.
- mIsTrusted = manager.isTrusted(uid, packageName);
+ mIsTrusted = manager.isTrusted(packageName, pid, uid);
}
@Override
@@ -1468,7 +1501,7 @@
* {@link MediaSession2} or {@link MediaController2}.
*/
// TODO(jaewan): Also need executor
- public BuilderBaseImpl(Context context) {
+ public BuilderBaseImpl(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("context shouldn't be null");
}
@@ -1478,7 +1511,7 @@
}
@Override
- public void setPlayer_impl(MediaPlayerBase player) {
+ public void setPlayer_impl(@NonNull MediaPlayerBase player) {
if (player == null) {
throw new IllegalArgumentException("player shouldn't be null");
}
@@ -1486,7 +1519,7 @@
}
@Override
- public void setPlaylistAgent_impl(MediaPlaylistAgent playlistAgent) {
+ public void setPlaylistAgent_impl(@NonNull MediaPlaylistAgent playlistAgent) {
if (playlistAgent == null) {
throw new IllegalArgumentException("playlistAgent shouldn't be null");
}
@@ -1504,7 +1537,7 @@
}
@Override
- public void setId_impl(String id) {
+ public void setId_impl(@NonNull String id) {
if (id == null) {
throw new IllegalArgumentException("id shouldn't be null");
}
@@ -1512,7 +1545,7 @@
}
@Override
- public void setSessionCallback_impl(Executor executor, C callback) {
+ public void setSessionCallback_impl(@NonNull Executor executor, @NonNull C callback) {
if (executor == null) {
throw new IllegalArgumentException("executor shouldn't be null");
}
diff --git a/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java b/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
index 6805dad..693e137 100644
--- a/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
+++ b/packages/MediaComponents/src/com/android/media/SessionPlaylistAgent.java
@@ -24,7 +24,6 @@
import android.media.MediaMetadata2;
import android.media.MediaPlayerBase;
import android.media.MediaPlaylistAgent;
-import android.media.MediaSession2;
import android.media.MediaSession2.OnDataSourceMissingHelper;
import android.util.ArrayMap;
@@ -47,14 +46,13 @@
private final PlayItem mEopPlayItem = new PlayItem(END_OF_PLAYLIST, null);
private final Object mLock = new Object();
- private final MediaSession2 mSession;
+ private final MediaSession2Impl mSessionImpl;
// TODO: Set data sources properly into mPlayer (b/74090741)
@GuardedBy("mLock")
private MediaPlayerBase mPlayer;
@GuardedBy("mLock")
- private OnDataSourceMissingHelper mDsdHelper;
-
+ private OnDataSourceMissingHelper mDsmHelper;
// TODO: Check if having the same item is okay (b/74090741)
@GuardedBy("mLock")
private ArrayList<MediaItem2> mPlaylist = new ArrayList<>();
@@ -118,16 +116,16 @@
}
}
- public SessionPlaylistAgent(@NonNull Context context, @NonNull MediaSession2 session,
+ public SessionPlaylistAgent(@NonNull Context context, @NonNull MediaSession2Impl sessionImpl,
@NonNull MediaPlayerBase player) {
super(context);
- if (session == null) {
- throw new IllegalArgumentException("session shouldn't be null");
+ if (sessionImpl == null) {
+ throw new IllegalArgumentException("sessionImpl shouldn't be null");
}
if (player == null) {
throw new IllegalArgumentException("player shouldn't be null");
}
- mSession = session;
+ mSessionImpl = sessionImpl;
mPlayer = player;
}
@@ -142,7 +140,13 @@
public void setOnDataSourceMissingHelper(OnDataSourceMissingHelper helper) {
synchronized (mLock) {
- mDsdHelper = helper;
+ mDsmHelper = helper;
+ }
+ }
+
+ public void clearOnDataSourceMissingHelper() {
+ synchronized (mLock) {
+ mDsmHelper = null;
}
}
@@ -154,8 +158,7 @@
}
@Override
- public void setPlaylist(@NonNull List<MediaItem2> list,
- @Nullable MediaMetadata2 metadata) {
+ public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) {
if (list == null) {
throw new IllegalArgumentException("list shouldn't be null");
}
@@ -359,10 +362,10 @@
if (dsd != null) {
return dsd;
}
- OnDataSourceMissingHelper helper = mDsdHelper;
+ OnDataSourceMissingHelper helper = mDsmHelper;
if (helper != null) {
// TODO: Do not call onDataSourceMissing with the lock (b/74090741).
- dsd = helper.onDataSourceMissing(mSession, item);
+ dsd = helper.onDataSourceMissing(mSessionImpl.getInstance(), item);
if (dsd != null) {
mItemDsdMap.put(item, dsd);
}
diff --git a/packages/MediaComponents/tests/Android.mk b/packages/MediaComponents/tests/Android.mk
index bf81efb..dddfd2a 100644
--- a/packages/MediaComponents/tests/Android.mk
+++ b/packages/MediaComponents/tests/Android.mk
@@ -20,6 +20,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android.test.runner.stubs \
android.test.base.stubs \
+ mockito-target-minus-junit4 \
junit
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java b/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
index 80370ec..ca941ab 100644
--- a/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
+++ b/packages/MediaComponents/tests/src/com/android/media/SessionPlaylistAgentTest.java
@@ -16,19 +16,21 @@
package com.android.media;
+import static org.mockito.Mockito.*;
+
import android.content.Context;
+import android.media.AudioAttributes;
import android.media.DataSourceDesc;
import android.media.MediaItem2;
import android.media.MediaMetadata2;
-import android.media.MediaPlayer2;
import android.media.MediaPlayerBase;
import android.media.MediaPlaylistAgent;
import android.media.MediaSession2;
+import android.media.MediaSession2.OnDataSourceMissingHelper;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.test.AndroidTestCase;
-import android.util.Log;
import org.junit.After;
import org.junit.Before;
@@ -52,10 +54,10 @@
private Object mWaitLock = new Object();
private Context mContext;
- private MediaSession2 mSession;
+ private MediaSession2Impl mSessionImpl;
private MediaPlayerBase mPlayer;
private SessionPlaylistAgent mAgent;
- private MyDataSourceHelper mDataSourceHelper;
+ private OnDataSourceMissingHelper mDataSourceHelper;
private MyPlaylistEventCallback mEventCallback;
public class MyPlaylistEventCallback extends MediaPlaylistAgent.PlaylistEventCallback {
@@ -108,7 +110,7 @@
}
}
- public class MyDataSourceHelper implements MediaSession2.OnDataSourceMissingHelper {
+ public class MyDataSourceHelper implements OnDataSourceMissingHelper {
@Override
public DataSourceDesc onDataSourceMissing(MediaSession2 session, MediaItem2 item) {
if (item.getMediaId().contains("WITHOUT_DSD")) {
@@ -121,8 +123,104 @@
}
}
+ public class MockPlayer extends MediaPlayerBase {
+ @Override
+ public void play() {
+ }
+
+ @Override
+ public void prepare() {
+ }
+
+ @Override
+ public void pause() {
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public void skipToNext() {
+ }
+
+ @Override
+ public void seekTo(long pos) {
+ }
+
+ @Override
+ public int getPlayerState() {
+ return 0;
+ }
+
+ @Override
+ public int getBufferingState() {
+ return 0;
+ }
+
+ @Override
+ public void setAudioAttributes(AudioAttributes attributes) {
+ }
+
+ @Override
+ public AudioAttributes getAudioAttributes() {
+ return null;
+ }
+
+ @Override
+ public void setDataSource(DataSourceDesc dsd) {
+ }
+
+ @Override
+ public void setNextDataSource(DataSourceDesc dsd) {
+ }
+
+ @Override
+ public void setNextDataSources(List<DataSourceDesc> dsds) {
+ }
+
+ @Override
+ public DataSourceDesc getCurrentDataSource() {
+ return null;
+ }
+
+ @Override
+ public void loopCurrent(boolean loop) {
+ }
+
+ @Override
+ public void setPlaybackSpeed(float speed) {
+ }
+
+ @Override
+ public void setPlayerVolume(float volume) {
+ }
+
+ @Override
+ public float getPlayerVolume() {
+ return 0;
+ }
+
+ @Override
+ public void registerPlayerEventCallback(Executor e, PlayerEventCallback cb) {
+ }
+
+ @Override
+ public void unregisterPlayerEventCallback(PlayerEventCallback cb) {
+ }
+
+ @Override
+ public void close() throws Exception {
+ }
+ }
+
@Before
public void setUp() throws Exception {
+ mContext = getContext();
+ // Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
+ // Dexmaker is used by mockito.
+ System.setProperty("dexmaker.dexcache", mContext.getCacheDir().getPath());
+
HandlerThread handlerThread = new HandlerThread("SessionPlaylistAgent");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
@@ -130,15 +228,10 @@
mHandler.post(runnable);
};
- mContext = getContext();
- mPlayer = MediaPlayer2.create();
- mSession = new MediaSession2.Builder(mContext)
- .setPlayer(mPlayer)
- .setSessionCallback(mHandlerExecutor,
- new MediaSession2.SessionCallback(mContext) {})
- .setId(TAG).build();
+ mPlayer = mock(MockPlayer.class);
+ mSessionImpl = mock(MediaSession2Impl.class);
mDataSourceHelper = new MyDataSourceHelper();
- mAgent = new SessionPlaylistAgent(mContext, mSession, mPlayer);
+ mAgent = new SessionPlaylistAgent(mContext, mSessionImpl, mPlayer);
mAgent.setOnDataSourceMissingHelper(mDataSourceHelper);
mEventCallback = new MyPlaylistEventCallback(mWaitLock);
mAgent.registerPlaylistEventCallback(mHandlerExecutor, mEventCallback);
@@ -146,8 +239,6 @@
@After
public void tearDown() throws Exception {
- mSession.close();
- mPlayer.close();
mHandler.getLooper().quitSafely();
mHandler = null;
mHandlerExecutor = null;
diff --git a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h b/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
index 31b7e0f..e4fd176 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
@@ -62,7 +62,8 @@
[AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
[AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
- [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround"
+ [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
+ [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
};
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 977a396..be7f7ec 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -154,6 +154,13 @@
}
mForceUse[usage] = config;
break;
+ case AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:
+ if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_NONE) {
+ ALOGW("setForceUse() invalid config %d for FOR_VIBRATE_RINGING", config);
+ return BAD_VALUE;
+ }
+ mForceUse[usage] = config;
+ break;
default:
ALOGW("setForceUse() invalid usage %d", usage);
break; // TODO return BAD_VALUE?
@@ -423,8 +430,7 @@
// if SCO headset is connected and we are told to use it, play ringtone over
// speaker and BT SCO
- if (((availableOutputDevicesType & AUDIO_DEVICE_OUT_ALL_SCO) != 0) &&
- (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO)) {
+ if ((availableOutputDevicesType & AUDIO_DEVICE_OUT_ALL_SCO) != 0) {
uint32_t device2 = AUDIO_DEVICE_NONE;
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
if (device2 == AUDIO_DEVICE_NONE) {
@@ -433,10 +439,23 @@
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
}
-
- if (device2 != AUDIO_DEVICE_NONE) {
- device |= device2;
- break;
+ // Use ONLY Bluetooth SCO output when ringing in vibration mode
+ if (!((mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
+ && (strategy == STRATEGY_ENFORCED_AUDIBLE))) {
+ if (mForceUse[AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING]
+ == AUDIO_POLICY_FORCE_BT_SCO) {
+ if (device2 != AUDIO_DEVICE_NONE) {
+ device = device2;
+ break;
+ }
+ }
+ }
+ // Use both Bluetooth SCO and phone default output when ringing in normal mode
+ if (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) {
+ if (device2 != AUDIO_DEVICE_NONE) {
+ device |= device2;
+ break;
+ }
}
}
// The second device used for sonification is the same as the device used by media strategy