CCodec: convert audio decoder output PCM format
Bug: 197719179
Test: cts/media/device-small
Change-Id: I861d29633358cf0c812b45f119f6ba00da1512c6
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 10a6896..5add96a 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1311,8 +1311,8 @@
}
}
- // set channel-mask
if (config->mDomain & Config::IS_AUDIO) {
+ // set channel-mask
int32_t mask;
if (msg->findInt32(KEY_CHANNEL_MASK, &mask)) {
if (config->mDomain & Config::IS_ENCODER) {
@@ -1321,6 +1321,15 @@
config->mOutputFormat->setInt32(KEY_CHANNEL_MASK, mask);
}
}
+
+ // set PCM encoding
+ int32_t pcmEncoding = kAudioEncodingPcm16bit;
+ msg->findInt32(KEY_PCM_ENCODING, &pcmEncoding);
+ if (encoder) {
+ config->mInputFormat->setInt32("android._config-pcm-encoding", pcmEncoding);
+ } else {
+ config->mOutputFormat->setInt32("android._config-pcm-encoding", pcmEncoding);
+ }
}
std::unique_ptr<C2Param> colorTransferRequestParam;
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index cfa89cf..412fd71 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -21,6 +21,7 @@
#include <C2PlatformSupport.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/SkipCutBuffer.h>
@@ -197,6 +198,56 @@
mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
}
+bool OutputBuffers::convert(
+ const std::shared_ptr<C2Buffer> &src, sp<Codec2Buffer> *dst) {
+ if (!src || src->data().type() != C2BufferData::LINEAR) {
+ return false;
+ }
+ int32_t configEncoding = kAudioEncodingPcm16bit;
+ int32_t codecEncoding = kAudioEncodingPcm16bit;
+ if (mFormat->findInt32("android._codec-pcm-encoding", &codecEncoding)
+ && mFormat->findInt32("android._config-pcm-encoding", &configEncoding)) {
+ if (mSrcEncoding != codecEncoding || mDstEncoding != configEncoding) {
+ if (codecEncoding != configEncoding) {
+ mDataConverter = AudioConverter::Create(
+ (AudioEncoding)codecEncoding, (AudioEncoding)configEncoding);
+ ALOGD_IF(mDataConverter, "[%s] Converter created from %d to %d",
+ mName, codecEncoding, configEncoding);
+ mFormatWithConverter = mFormat->dup();
+ mFormatWithConverter->setInt32(KEY_PCM_ENCODING, configEncoding);
+ } else {
+ mDataConverter = nullptr;
+ mFormatWithConverter = nullptr;
+ }
+ mSrcEncoding = codecEncoding;
+ mDstEncoding = configEncoding;
+ }
+ if (int encoding; !mFormat->findInt32(KEY_PCM_ENCODING, &encoding)
+ || encoding != mDstEncoding) {
+ }
+ }
+ if (!mDataConverter) {
+ return false;
+ }
+ sp<MediaCodecBuffer> srcBuffer = ConstLinearBlockBuffer::Allocate(mFormat, src);
+ if (!srcBuffer) {
+ return false;
+ }
+ if (!dst) {
+ *dst = new Codec2Buffer(
+ mFormat,
+ new ABuffer(mDataConverter->targetSize(srcBuffer->size())));
+ }
+ sp<MediaCodecBuffer> dstBuffer = *dst;
+ status_t err = mDataConverter->convert(srcBuffer, dstBuffer);
+ if (err != OK) {
+ ALOGD("[%s] buffer conversion failed: %d", mName, err);
+ return false;
+ }
+ dstBuffer->setFormat(mFormatWithConverter);
+ return true;
+}
+
void OutputBuffers::clearStash() {
mPending.clear();
mReorderStash.clear();
@@ -1074,7 +1125,7 @@
return err;
}
c2Buffer->setFormat(mFormat);
- if (!c2Buffer->copy(buffer)) {
+ if (!convert(buffer, &c2Buffer) && !c2Buffer->copy(buffer)) {
ALOGD("[%s] copy buffer failed", mName);
return WOULD_BLOCK;
}
@@ -1190,9 +1241,12 @@
const std::shared_ptr<C2Buffer> &buffer,
size_t *index,
sp<MediaCodecBuffer> *clientBuffer) {
- sp<Codec2Buffer> newBuffer = wrap(buffer);
- if (newBuffer == nullptr) {
- return NO_MEMORY;
+ sp<Codec2Buffer> newBuffer;
+ if (!convert(buffer, &newBuffer)) {
+ newBuffer = wrap(buffer);
+ if (newBuffer == nullptr) {
+ return NO_MEMORY;
+ }
}
newBuffer->setFormat(mFormat);
*index = mImpl.assignSlot(newBuffer);
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index 995d3a4..7f3a655 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -18,9 +18,11 @@
#define CCODEC_BUFFERS_H_
+#include <optional>
#include <string>
#include <C2Config.h>
+#include <DataConverter.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/MediaCodecBuffer.h>
@@ -382,6 +384,14 @@
*/
void submit(const sp<MediaCodecBuffer> &buffer);
+ /**
+ * Apply DataConverter from |src| to |*dst| if needed. If |dst| is nullptr,
+ * a new buffer is allocated.
+ *
+ * Returns true if conversion was needed and executed; false otherwise.
+ */
+ bool convert(const std::shared_ptr<C2Buffer> &src, sp<Codec2Buffer> *dst);
+
private:
// SkipCutBuffer
int32_t mDelay;
@@ -391,6 +401,12 @@
void setSkipCutBuffer(int32_t skip, int32_t cut);
+ // DataConverter
+ sp<DataConverter> mDataConverter;
+ sp<AMessage> mFormatWithConverter;
+ std::optional<int32_t> mSrcEncoding;
+ std::optional<int32_t> mDstEncoding;
+
// Output stash
// Struct for an entry in the output stash (mPending and mReorderStash)
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 5646095..0ab87dc 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -657,24 +657,29 @@
add(ConfigMapper(KEY_SAMPLE_RATE, C2_PARAMKEY_CODED_SAMPLE_RATE, "value")
.limitTo(D::AUDIO & D::CODED));
- add(ConfigMapper(KEY_PCM_ENCODING, C2_PARAMKEY_PCM_ENCODING, "value")
+ auto pcmEncodingMapper = [](C2Value v) -> C2Value {
+ int32_t value;
+ C2Config::pcm_encoding_t to;
+ if (v.get(&value) && C2Mapper::map(value, &to)) {
+ return to;
+ }
+ return C2Value();
+ };
+ auto pcmEncodingReverse = [](C2Value v) -> C2Value {
+ C2Config::pcm_encoding_t value;
+ int32_t to;
+ using C2ValueType=typename _c2_reduce_enum_to_underlying_type<decltype(value)>::type;
+ if (v.get((C2ValueType*)&value) && C2Mapper::map(value, &to)) {
+ return to;
+ }
+ return C2Value();
+ };
+ add(ConfigMapper(KEY_PCM_ENCODING, C2_PARAMKEY_PCM_ENCODING, "value")
.limitTo(D::AUDIO)
- .withMappers([](C2Value v) -> C2Value {
- int32_t value;
- C2Config::pcm_encoding_t to;
- if (v.get(&value) && C2Mapper::map(value, &to)) {
- return to;
- }
- return C2Value();
- }, [](C2Value v) -> C2Value {
- C2Config::pcm_encoding_t value;
- int32_t to;
- using C2ValueType=typename _c2_reduce_enum_to_underlying_type<decltype(value)>::type;
- if (v.get((C2ValueType*)&value) && C2Mapper::map(value, &to)) {
- return to;
- }
- return C2Value();
- }));
+ .withMappers(pcmEncodingMapper, pcmEncodingReverse));
+ add(ConfigMapper("android._codec-pcm-encoding", C2_PARAMKEY_PCM_ENCODING, "value")
+ .limitTo(D::AUDIO & D::READ)
+ .withMappers(pcmEncodingMapper, pcmEncodingReverse));
add(ConfigMapper(KEY_IS_ADTS, C2_PARAMKEY_AAC_PACKAGING, "value")
.limitTo(D::AUDIO & D::CODED)