CCodec: handle dataspace update from GraphicBufferSource
Bug: 178675686
Test: manual
Change-Id: Ibc2013cf2208a369dda52616507e4ade8b607caa
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index ab73245..1a92c08 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -33,12 +33,14 @@
#include <OMX_IndexExt.h>
#include <android/fdsan.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/omx/OMXUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
#include <utils/Thread.h>
+#include "utils/Codec2Mapper.h"
#include "C2OMXNode.h"
namespace android {
@@ -71,6 +73,25 @@
jobs->cond.broadcast();
}
+ void setDataspace(android_dataspace dataspace) {
+ Mutexed<Jobs>::Locked jobs(mJobs);
+ ColorUtils::convertDataSpaceToV0(dataspace);
+ jobs->configUpdate.emplace_back(new C2StreamDataSpaceInfo::input(0u, dataspace));
+ int32_t standard = (int32_t(dataspace) & HAL_DATASPACE_STANDARD_MASK)
+ >> HAL_DATASPACE_STANDARD_SHIFT;
+ int32_t transfer = (int32_t(dataspace) & HAL_DATASPACE_TRANSFER_MASK)
+ >> HAL_DATASPACE_TRANSFER_SHIFT;
+ int32_t range = (int32_t(dataspace) & HAL_DATASPACE_RANGE_MASK)
+ >> HAL_DATASPACE_RANGE_SHIFT;
+ std::unique_ptr<C2StreamColorAspectsInfo::input> colorAspects =
+ std::make_unique<C2StreamColorAspectsInfo::input>(0u);
+ if (C2Mapper::map(standard, &colorAspects->primaries, &colorAspects->matrix)
+ && C2Mapper::map(transfer, &colorAspects->transfer)
+ && C2Mapper::map(range, &colorAspects->range)) {
+ jobs->configUpdate.push_back(std::move(colorAspects));
+ }
+ }
+
protected:
bool threadLoop() override {
constexpr nsecs_t kIntervalNs = nsecs_t(10) * 1000 * 1000; // 10ms
@@ -102,6 +123,9 @@
uniqueFds.push_back(std::move(queue.workList.front().fd1));
queue.workList.pop_front();
}
+ for (const std::unique_ptr<C2Param> ¶m : jobs->configUpdate) {
+ items.front()->input.configUpdate.emplace_back(C2Param::Copy(*param));
+ }
jobs.unlock();
for (int fenceFd : fenceFds) {
@@ -119,6 +143,7 @@
queued = true;
}
if (queued) {
+ jobs->configUpdate.clear();
return true;
}
if (i == 0) {
@@ -161,6 +186,7 @@
std::map<std::weak_ptr<Codec2Client::Component>,
Queue,
std::owner_less<std::weak_ptr<Codec2Client::Component>>> queues;
+ std::vector<std::unique_ptr<C2Param>> configUpdate;
Condition cond;
};
Mutexed<Jobs> mJobs;
@@ -172,6 +198,9 @@
mQueueThread(new QueueThread) {
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS);
mQueueThread->run("C2OMXNode", PRIORITY_AUDIO);
+
+ Mutexed<android_dataspace>::Locked ds(mDataspace);
+ *ds = HAL_DATASPACE_UNKNOWN;
}
status_t C2OMXNode::freeNode() {
@@ -459,8 +488,11 @@
android_dataspace dataSpace = (android_dataspace)msg.u.event_data.data1;
uint32_t pixelFormat = msg.u.event_data.data3;
- // TODO: set dataspace on component to see if it impacts color aspects
ALOGD("dataspace changed to %#x pixel format: %#x", dataSpace, pixelFormat);
+ mQueueThread->setDataspace(dataSpace);
+
+ Mutexed<android_dataspace>::Locked ds(mDataspace);
+ *ds = dataSpace;
return OK;
}
@@ -493,4 +525,8 @@
(void)mBufferSource->onInputBufferEmptied(bufferId, -1);
}
+android_dataspace C2OMXNode::getDataspace() {
+ return *mDataspace.lock();
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/C2OMXNode.h b/media/codec2/sfplugin/C2OMXNode.h
index 1717c96..5d587bc 100644
--- a/media/codec2/sfplugin/C2OMXNode.h
+++ b/media/codec2/sfplugin/C2OMXNode.h
@@ -93,6 +93,8 @@
*/
void onInputBufferDone(c2_cntr64_t index);
+ android_dataspace getDataspace();
+
private:
std::weak_ptr<Codec2Client::Component> mComp;
sp<IOMXBufferSource> mBufferSource;
@@ -101,6 +103,7 @@
uint32_t mWidth;
uint32_t mHeight;
uint64_t mUsage;
+ Mutexed<android_dataspace> mDataspace;
// WORKAROUND: timestamp adjustment
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index b88dc8b..092d6ee 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -210,8 +210,6 @@
(OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
&usage, sizeof(usage));
- // NOTE: we do not use/pass through color aspects from GraphicBufferSource as we
- // communicate that directly to the component.
mSource->configure(
mOmxNode, static_cast<hardware::graphics::common::V1_0::Dataspace>(mDataSpace));
return OK;
@@ -410,6 +408,10 @@
mNode->onInputBufferDone(index);
}
+ android_dataspace getDataspace() override {
+ return mNode->getDataspace();
+ }
+
private:
sp<HGraphicBufferSource> mSource;
sp<C2OMXNode> mNode;
@@ -1007,6 +1009,9 @@
}
}
+ // get color aspects
+ getColorAspectsFromFormat(msg, config->mClientColorAspects);
+
/*
* Handle dataspace
*/
@@ -1016,12 +1021,12 @@
int32_t width, height;
if (msg->findInt32("width", &width)
&& msg->findInt32("height", &height)) {
- ColorAspects aspects;
- getColorAspectsFromFormat(msg, aspects);
- setDefaultCodecColorAspectsIfNeeded(aspects, width, height);
+ setDefaultCodecColorAspectsIfNeeded(config->mClientColorAspects, width, height);
// TODO: read dataspace / color aspect from the component
- setColorAspectsIntoFormat(aspects, const_cast<sp<AMessage> &>(msg));
- dataSpace = getDataSpaceForColorAspects(aspects, true /* mayexpand */);
+ setColorAspectsIntoFormat(
+ config->mClientColorAspects, const_cast<sp<AMessage> &>(msg));
+ dataSpace = getDataSpaceForColorAspects(
+ config->mClientColorAspects, true /* mayexpand */);
}
msg->setInt32("android._dataspace", (int32_t)dataSpace);
ALOGD("setting dataspace to %x", dataSpace);
@@ -1946,6 +1951,44 @@
}
}
+static void HandleDataspace(
+ android_dataspace dataspace, ColorAspects *colorAspects, sp<AMessage> *format) {
+ ColorUtils::convertDataSpaceToV0(dataspace);
+ int32_t range, standard, transfer;
+ range = (dataspace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
+ if (range == 0) {
+ range = ColorUtils::wrapColorAspectsIntoColorRange(
+ colorAspects->mRange);
+ }
+ standard = (dataspace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
+ if (standard == 0) {
+ standard = ColorUtils::wrapColorAspectsIntoColorStandard(
+ colorAspects->mPrimaries,
+ colorAspects->mMatrixCoeffs);
+ }
+ transfer = (dataspace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
+ if (transfer == 0) {
+ transfer = ColorUtils::wrapColorAspectsIntoColorTransfer(
+ colorAspects->mTransfer);
+ }
+ ColorAspects newColorAspects;
+ ColorUtils::convertPlatformColorAspectsToCodecAspects(
+ range, standard, transfer, newColorAspects);
+ if (ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
+ newColorAspects, *colorAspects)) {
+ *format = (*format)->dup();
+ (*format)->setInt32(KEY_COLOR_RANGE, range);
+ (*format)->setInt32(KEY_COLOR_STANDARD, standard);
+ (*format)->setInt32(KEY_COLOR_TRANSFER, transfer);
+ // Record current color aspects into |colorAspects|.
+ // NOTE: newColorAspects could have been modified by
+ // checkIfAspectsChangedAndUnspecifyThem() above,
+ // so *colorAspects = newColorAspects does not work as intended.
+ ColorUtils::convertPlatformColorAspectsToCodecAspects(
+ range, standard, transfer, *colorAspects);
+ }
+}
+
void CCodec::onMessageReceived(const sp<AMessage> &msg) {
TimePoint now = std::chrono::steady_clock::now();
CCodecWatchdog::getInstance()->watch(this);
@@ -2060,6 +2103,10 @@
sp<AMessage> outputFormat = config->mOutputFormat;
config->updateConfiguration(updates, config->mOutputDomain);
+ if (config->mInputSurface) {
+ android_dataspace ds = config->mInputSurface->getDataspace();
+ HandleDataspace(ds, &config->mClientColorAspects, &config->mOutputFormat);
+ }
RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
// copy standard infos to graphic buffers if not already present (otherwise, we
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index 2895746..2a31714 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -27,6 +27,7 @@
#include <C2Debug.h>
#include <codec2/hidl/client.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <utils/RefBase.h>
#include "InputSurfaceWrapper.h"
@@ -123,6 +124,7 @@
std::shared_ptr<InputSurfaceWrapper> mInputSurface;
std::unique_ptr<InputSurfaceWrapper::Config> mISConfig;
+ ColorAspects mClientColorAspects;
/// the current configuration. Updated after configure() and based on configUpdate in
/// onWorkDone
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index bb35763..bb7ca02 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -106,6 +106,8 @@
*/
virtual void onInputBufferDone(c2_cntr64_t /* index */) {}
+ virtual android_dataspace getDataspace() { return mDataSpace; }
+
protected:
android_dataspace mDataSpace;
};