MediaCodec: avoid touching output format at MediaCodec
For C2-based codecs, do not touch the output format at MediaCodec
and move the operation to CCodec level.
Bug: 174725427
Test: cts/media/device-small
Change-Id: I32f5e328d3f3fb81fd6a1c479a6a2fdfa46fbc7f
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 8def53d..c5b5871 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -38,6 +38,7 @@
#include <media/omx/1.0/WOmxNode.h>
#include <media/openmax/OMX_Core.h>
#include <media/openmax/OMX_IndexExt.h>
+#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
#include <media/stagefright/omx/OmxGraphicBufferSource.h>
#include <media/stagefright/CCodec.h>
@@ -513,6 +514,44 @@
}
}
+void AmendOutputFormatWithCodecSpecificData(
+ const uint8_t *data, size_t size, const std::string mediaType,
+ const sp<AMessage> &outputFormat) {
+ if (mediaType == MIMETYPE_VIDEO_AVC) {
+ // Codec specific data should be SPS and PPS in a single buffer,
+ // each prefixed by a startcode (0x00 0x00 0x00 0x01).
+ // We separate the two and put them into the output format
+ // under the keys "csd-0" and "csd-1".
+
+ unsigned csdIndex = 0;
+
+ const uint8_t *nalStart;
+ size_t nalSize;
+ while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
+ sp<ABuffer> csd = new ABuffer(nalSize + 4);
+ memcpy(csd->data(), "\x00\x00\x00\x01", 4);
+ memcpy(csd->data() + 4, nalStart, nalSize);
+
+ outputFormat->setBuffer(
+ AStringPrintf("csd-%u", csdIndex).c_str(), csd);
+
+ ++csdIndex;
+ }
+
+ if (csdIndex != 2) {
+ ALOGW("Expected two NAL units from AVC codec config, but %u found",
+ csdIndex);
+ }
+ } else {
+ // For everything else we just stash the codec specific data into
+ // the output format as a single piece of csd under "csd-0".
+ sp<ABuffer> csd = new ABuffer(size);
+ memcpy(csd->data(), data, size);
+ csd->setRange(0, size);
+ outputFormat->setBuffer("csd-0", csd);
+ }
+}
+
} // namespace
// CCodec::ClientListener
@@ -2149,7 +2188,7 @@
}
// handle configuration changes in work done
- std::unique_ptr<C2Param> initData;
+ std::shared_ptr<const C2StreamInitDataInfo::output> initData;
sp<AMessage> outputFormat = nullptr;
{
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
@@ -2228,13 +2267,15 @@
config->mInputSurface->onInputBufferDone(work->input.ordinal.frameIndex);
}
if (initDataWatcher.hasChanged()) {
- initData = C2Param::Copy(*initDataWatcher.update().get());
+ initData = initDataWatcher.update();
+ AmendOutputFormatWithCodecSpecificData(
+ initData->m.value, initData->flexCount(), config->mCodingMediaType,
+ config->mOutputFormat);
}
outputFormat = config->mOutputFormat;
}
mChannel->onWorkDone(
- std::move(work), outputFormat,
- initData ? (C2StreamInitDataInfo::output *)initData.get() : nullptr);
+ std::move(work), outputFormat, initData ? initData.get() : nullptr);
break;
}
case kWhatWatch: {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 8e721d4..4d43809 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -3656,7 +3656,8 @@
// format as necessary.
int32_t flags = 0;
(void) buffer->meta()->findInt32("flags", &flags);
- if ((flags & BUFFER_FLAG_CODECCONFIG) && !(mFlags & kFlagIsSecure)) {
+ if ((flags & BUFFER_FLAG_CODECCONFIG) && !(mFlags & kFlagIsSecure)
+ && !mOwnerName.startsWith("codec2::")) {
status_t err =
amendOutputFormatWithCodecSpecificData(buffer);