Merge "cameraserver: Stop appOps camera reporting for vendor clients." into qt-dev
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index d7dacb8..d74bc53 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -401,20 +401,25 @@
sendExpirationUpdate(sessionId, 100);
- std::vector<KeyStatus> keysStatus;
- KeyStatus keyStatus;
+ std::vector<KeyStatus_V1_2> keysStatus;
+ KeyStatus_V1_2 keyStatus;
std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC };
keyStatus.keyId = keyId1;
- keyStatus.type = V1_0::KeyStatusType::USABLE;
+ keyStatus.type = V1_2::KeyStatusType::USABLE;
keysStatus.push_back(keyStatus);
std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF };
keyStatus.keyId = keyId2;
- keyStatus.type = V1_0::KeyStatusType::EXPIRED;
+ keyStatus.type = V1_2::KeyStatusType::EXPIRED;
keysStatus.push_back(keyStatus);
- sendKeysChange(sessionId, keysStatus, true);
+ std::vector<uint8_t> keyId3 = { 0x0, 0x1, 0x2 };
+ keyStatus.keyId = keyId3;
+ keyStatus.type = V1_2::KeyStatusType::USABLEINFUTURE;
+ keysStatus.push_back(keyStatus);
+
+ sendKeysChange_1_2(sessionId, keysStatus, true);
installSecureStop(sessionId);
} else {
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index 384d58b..70d1965 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -471,11 +471,11 @@
uint8_t* outPtr = wView.data() + mBytesEncoded;
int encodedBytes =
opus_multistream_encode(mEncoder, mInputBufferPcm16,
- mNumSamplesPerFrame, outPtr, kMaxPayload);
+ mNumSamplesPerFrame, outPtr, kMaxPayload - mBytesEncoded);
ALOGV("encoded %i Opus bytes from %zu PCM bytes", encodedBytes,
processSize);
- if (encodedBytes < 0 || encodedBytes > kMaxPayload) {
+ if (encodedBytes < 0 || encodedBytes > (kMaxPayload - mBytesEncoded)) {
ALOGE("opus_encode failed, encodedBytes : %d", encodedBytes);
mSignalledError = true;
work->result = C2_CORRUPTED;
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.h b/media/codec2/components/opus/C2SoftOpusEnc.h
index 69e5240..2b4d8f2 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.h
+++ b/media/codec2/components/opus/C2SoftOpusEnc.h
@@ -47,7 +47,9 @@
private:
/* OPUS_FRAMESIZE_20_MS */
const int kFrameSize = 960;
- const int kMaxPayload = 4000;
+ const int kMaxSampleRate = 48000;
+ const int kMinSampleRate = 8000;
+ const int kMaxPayload = (4000 * kMaxSampleRate) / kMinSampleRate;
const int kMaxNumChannels = 8;
std::shared_ptr<IntfImpl> mIntf;
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 9f484a3..3820f90 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -117,7 +117,7 @@
/* pipeline characteristics */
kParamIndexMediaType,
- kParamIndexDelayRequest,
+ __kParamIndexRESERVED_0,
kParamIndexDelay,
kParamIndexMaxReferenceAge,
kParamIndexMaxReferenceCount,
@@ -151,6 +151,9 @@
/* protected content */
kParamIndexSecureMode,
+ // deprecated
+ kParamIndexDelayRequest = kParamIndexDelay | C2Param::CoreIndex::IS_REQUEST_FLAG,
+
/* ------------------------------------ (trans/en)coders ------------------------------------ */
kParamIndexBitrate = C2_PARAM_INDEX_CODER_PARAM_START,
@@ -779,22 +782,26 @@
* outstanding input frames queued to the component, it shall produce output.
*/
-typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexDelayRequest> C2PortRequestedDelayTuning;
-constexpr char C2_PARAMKEY_INPUT_DELAY_REQUEST[] = "input.delay.requested";
-constexpr char C2_PARAMKEY_OUTPUT_DELAY_REQUEST[] = "output.delay.requested";
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexDelay | C2Param::CoreIndex::IS_REQUEST_FLAG>
+ C2PortRequestedDelayTuning;
+constexpr char C2_PARAMKEY_INPUT_DELAY_REQUEST[] = "input.delay"; // deprecated
+constexpr char C2_PARAMKEY_OUTPUT_DELAY_REQUEST[] = "output.delay"; // deprecated
-typedef C2GlobalParam<C2Tuning, C2Uint32Value, kParamIndexDelayRequest>
+typedef C2GlobalParam<C2Tuning, C2Uint32Value,
+ kParamIndexDelay | C2Param::CoreIndex::IS_REQUEST_FLAG>
C2RequestedPipelineDelayTuning;
-constexpr char C2_PARAMKEY_PIPELINE_DELAY_REQUEST[] = "pipeline-delay.requested";
+constexpr char C2_PARAMKEY_PIPELINE_DELAY_REQUEST[] = "algo.delay"; // deprecated
// read-only
-typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexDelay> C2PortActualDelayTuning;
-constexpr char C2_PARAMKEY_INPUT_DELAY[] = "input.delay.actual";
-constexpr char C2_PARAMKEY_OUTPUT_DELAY[] = "output.delay.actual";
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexDelay> C2PortDelayTuning;
+typedef C2PortDelayTuning C2PortActualDelayTuning; // deprecated
+constexpr char C2_PARAMKEY_INPUT_DELAY[] = "input.delay";
+constexpr char C2_PARAMKEY_OUTPUT_DELAY[] = "output.delay";
// read-only
-typedef C2GlobalParam<C2Tuning, C2Uint32Value, kParamIndexDelay> C2ActualPipelineDelayTuning;
-constexpr char C2_PARAMKEY_PIPELINE_DELAY[] = "algo.delay.actual";
+typedef C2GlobalParam<C2Tuning, C2Uint32Value, kParamIndexDelay> C2PipelineDelayTuning;
+typedef C2PipelineDelayTuning C2ActualPipelineDelayTuning; // deprecated
+constexpr char C2_PARAMKEY_PIPELINE_DELAY[] = "algo.delay";
/**
* Reference characteristics.
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index d264bf3..cc8c17a 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -158,7 +158,8 @@
struct CoreIndex {
//public:
enum : uint32_t {
- IS_FLEX_FLAG = 0x00010000,
+ IS_FLEX_FLAG = 0x00010000,
+ IS_REQUEST_FLAG = 0x00020000,
};
protected:
@@ -175,9 +176,9 @@
DIR_INPUT = 0x00000000,
DIR_OUTPUT = 0x10000000,
- IS_STREAM_FLAG = 0x02000000,
- STREAM_ID_MASK = 0x01FE0000,
- STREAM_ID_SHIFT = 17,
+ IS_STREAM_FLAG = 0x00100000,
+ STREAM_ID_MASK = 0x03E00000,
+ STREAM_ID_SHIFT = 21,
MAX_STREAM_ID = STREAM_ID_MASK >> STREAM_ID_SHIFT,
STREAM_MASK = IS_STREAM_FLAG | STREAM_ID_MASK,
@@ -360,6 +361,10 @@
mIndex = (mIndex & ~(DIR_MASK | IS_STREAM_FLAG)) | DIR_GLOBAL;
}
+ inline void convertToRequest() {
+ mIndex = mIndex | IS_REQUEST_FLAG;
+ }
+
/**
* Sets the stream index.
* \return true on success, false if could not set index (e.g. not a stream param).
@@ -476,6 +481,15 @@
return copy;
}
+ /// Returns managed clone of |orig| as a stream parameter at heap.
+ inline static std::unique_ptr<C2Param> CopyAsRequest(const C2Param &orig) {
+ std::unique_ptr<C2Param> copy = Copy(orig);
+ if (copy) {
+ copy->_mIndex.convertToRequest();
+ }
+ return copy;
+ }
+
#if 0
template<typename P, class=decltype(C2Param(P()))>
P *As() { return P::From(this); }
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index f5a4d94..76f132c 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1724,8 +1724,11 @@
& C2FrameData::FLAG_DISCARD_FRAME) == 0) {
// copy buffer info to config
- std::vector<std::unique_ptr<C2Param>> updates =
- std::move(work->worklets.front()->output.configUpdate);
+ std::vector<std::unique_ptr<C2Param>> updates;
+ for (const std::unique_ptr<C2Param> ¶m
+ : work->worklets.front()->output.configUpdate) {
+ updates.push_back(C2Param::Copy(*param));
+ }
unsigned stream = 0;
for (const std::shared_ptr<C2Buffer> &buf : work->worklets.front()->output.buffers) {
for (const std::shared_ptr<const C2Info> &info : buf->info()) {
@@ -1739,7 +1742,7 @@
// block.width(), block.height());
updates.emplace_back(new C2StreamCropRectInfo::output(stream, block.crop()));
updates.emplace_back(new C2StreamPictureSizeInfo::output(
- stream, block.width(), block.height()));
+ stream, block.crop().width, block.crop().height));
break; // for now only do the first block
}
++stream;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 7669421..eb20b20 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -210,22 +210,36 @@
}
}
+// Input
+
+CCodecBufferChannel::Input::Input() : extraBuffers("extra") {}
+
// CCodecBufferChannel
CCodecBufferChannel::CCodecBufferChannel(
const std::shared_ptr<CCodecCallback> &callback)
: mHeapSeqNum(-1),
mCCodecCallback(callback),
- mNumInputSlots(kSmoothnessFactor),
- mNumOutputSlots(kSmoothnessFactor),
mDelay(0),
mFrameIndex(0u),
mFirstValidFrameIndex(0u),
mMetaMode(MODE_NONE),
mInputMetEos(false) {
mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + kRenderingDepth;
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- buffers->reset(new DummyInputBuffers(""));
+ {
+ Mutexed<Input>::Locked input(mInput);
+ input->buffers.reset(new DummyInputBuffers(""));
+ input->extraBuffers.flush();
+ input->inputDelay = 0u;
+ input->pipelineDelay = 0u;
+ input->numSlots = kSmoothnessFactor;
+ input->numExtraSlots = 0u;
+ }
+ {
+ Mutexed<Output>::Locked output(mOutput);
+ output->outputDelay = 0u;
+ output->numSlots = kSmoothnessFactor;
+ }
}
CCodecBufferChannel::~CCodecBufferChannel() {
@@ -255,7 +269,7 @@
return mInputSurface->signalEndOfInputStream();
}
-status_t CCodecBufferChannel::queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer) {
+status_t CCodecBufferChannel::queueInputBufferInternal(sp<MediaCodecBuffer> buffer) {
int64_t timeUs;
CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
@@ -287,13 +301,31 @@
uint64_t queuedFrameIndex = work->input.ordinal.frameIndex.peeku();
std::vector<std::shared_ptr<C2Buffer>> queuedBuffers;
+ sp<Codec2Buffer> copy;
if (buffer->size() > 0u) {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
+ Mutexed<Input>::Locked input(mInput);
std::shared_ptr<C2Buffer> c2buffer;
- if (!(*buffers)->releaseBuffer(buffer, &c2buffer, false)) {
+ if (!input->buffers->releaseBuffer(buffer, &c2buffer, false)) {
return -ENOENT;
}
+ // TODO: we want to delay copying buffers.
+ if (input->extraBuffers.numComponentBuffers() < input->numExtraSlots) {
+ copy = input->buffers->cloneAndReleaseBuffer(buffer);
+ if (copy != nullptr) {
+ (void)input->extraBuffers.assignSlot(copy);
+ if (!input->extraBuffers.releaseSlot(copy, &c2buffer, false)) {
+ return UNKNOWN_ERROR;
+ }
+ bool released = input->buffers->releaseBuffer(buffer, nullptr, true);
+ ALOGV("[%s] queueInputBuffer: buffer copied; %sreleased",
+ mName, released ? "" : "not ");
+ buffer.clear();
+ } else {
+ ALOGW("[%s] queueInputBuffer: failed to copy a buffer; this may cause input "
+ "buffer starvation on component.", mName);
+ }
+ }
work->input.buffers.push_back(c2buffer);
queuedBuffers.push_back(c2buffer);
} else if (eos) {
@@ -343,9 +375,15 @@
}
}
if (err == C2_OK) {
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- bool released = (*buffers)->releaseBuffer(buffer, nullptr, true);
- ALOGV("[%s] queueInputBuffer: buffer %sreleased", mName, released ? "" : "not ");
+ Mutexed<Input>::Locked input(mInput);
+ bool released = false;
+ if (buffer) {
+ released = input->buffers->releaseBuffer(buffer, nullptr, true);
+ } else if (copy) {
+ released = input->extraBuffers.releaseSlot(copy, nullptr, true);
+ }
+ ALOGV("[%s] queueInputBuffer: buffer%s %sreleased",
+ mName, (buffer == nullptr) ? "(copy)" : "", released ? "" : "not ");
}
feedInputBufferIfAvailableInternal();
@@ -492,20 +530,21 @@
mPipelineWatcher.lock()->pipelineFull()) {
return;
} else {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- if ((*buffers)->numClientBuffers() >= mNumOutputSlots) {
+ Mutexed<Output>::Locked output(mOutput);
+ if (output->buffers->numClientBuffers() >= output->numSlots) {
return;
}
}
- for (size_t i = 0; i < mNumInputSlots; ++i) {
+ size_t numInputSlots = mInput.lock()->numSlots;
+ for (size_t i = 0; i < numInputSlots; ++i) {
sp<MediaCodecBuffer> inBuffer;
size_t index;
{
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- if ((*buffers)->numClientBuffers() >= mNumInputSlots) {
+ Mutexed<Input>::Locked input(mInput);
+ if (input->buffers->numClientBuffers() >= input->numSlots) {
return;
}
- if (!(*buffers)->requestNewBuffer(&index, &inBuffer)) {
+ if (!input->buffers->requestNewBuffer(&index, &inBuffer)) {
ALOGV("[%s] no new buffer available", mName);
break;
}
@@ -521,9 +560,9 @@
std::shared_ptr<C2Buffer> c2Buffer;
bool released = false;
{
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- if (*buffers) {
- released = (*buffers)->releaseBuffer(buffer, &c2Buffer);
+ Mutexed<Output>::Locked output(mOutput);
+ if (output->buffers) {
+ released = output->buffers->releaseBuffer(buffer, &c2Buffer);
}
}
// NOTE: some apps try to releaseOutputBuffer() with timestamp and/or render
@@ -685,14 +724,14 @@
ALOGV("[%s] discardBuffer: %p", mName, buffer.get());
bool released = false;
{
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- if (*buffers && (*buffers)->releaseBuffer(buffer, nullptr, true)) {
+ Mutexed<Input>::Locked input(mInput);
+ if (input->buffers && input->buffers->releaseBuffer(buffer, nullptr, true)) {
released = true;
}
}
{
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- if (*buffers && (*buffers)->releaseBuffer(buffer, nullptr)) {
+ Mutexed<Output>::Locked output(mOutput);
+ if (output->buffers && output->buffers->releaseBuffer(buffer, nullptr)) {
released = true;
}
}
@@ -707,24 +746,24 @@
void CCodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
array->clear();
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
+ Mutexed<Input>::Locked input(mInput);
- if (!(*buffers)->isArrayMode()) {
- *buffers = (*buffers)->toArrayMode(mNumInputSlots);
+ if (!input->buffers->isArrayMode()) {
+ input->buffers = input->buffers->toArrayMode(input->numSlots);
}
- (*buffers)->getArray(array);
+ input->buffers->getArray(array);
}
void CCodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
array->clear();
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
+ Mutexed<Output>::Locked output(mOutput);
- if (!(*buffers)->isArrayMode()) {
- *buffers = (*buffers)->toArrayMode(mNumOutputSlots);
+ if (!output->buffers->isArrayMode()) {
+ output->buffers = output->buffers->toArrayMode(output->numSlots);
}
- (*buffers)->getArray(array);
+ output->buffers->getArray(array);
}
status_t CCodecBufferChannel::start(
@@ -773,8 +812,8 @@
uint32_t pipelineDelayValue = pipelineDelay ? pipelineDelay.value : 0;
uint32_t outputDelayValue = outputDelay ? outputDelay.value : 0;
- mNumInputSlots = inputDelayValue + pipelineDelayValue + kSmoothnessFactor;
- mNumOutputSlots = outputDelayValue + kSmoothnessFactor;
+ size_t numInputSlots = inputDelayValue + pipelineDelayValue + kSmoothnessFactor;
+ size_t numOutputSlots = outputDelayValue + kSmoothnessFactor;
mDelay = inputDelayValue + pipelineDelayValue + outputDelayValue;
// TODO: get this from input format
@@ -848,14 +887,17 @@
}
bool forceArrayMode = false;
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
+ Mutexed<Input>::Locked input(mInput);
+ input->numSlots = numInputSlots;
+ input->extraBuffers.flush();
+ input->numExtraSlots = 0u;
if (graphic) {
if (mInputSurface) {
- buffers->reset(new DummyInputBuffers(mName));
+ input->buffers.reset(new DummyInputBuffers(mName));
} else if (mMetaMode == MODE_ANW) {
- buffers->reset(new GraphicMetadataInputBuffers(mName));
+ input->buffers.reset(new GraphicMetadataInputBuffers(mName));
} else {
- buffers->reset(new GraphicInputBuffers(mNumInputSlots, mName));
+ input->buffers.reset(new GraphicInputBuffers(numInputSlots, mName));
}
} else {
if (hasCryptoOrDescrambler()) {
@@ -868,7 +910,7 @@
if (mDealer == nullptr) {
mDealer = new MemoryDealer(
align(capacity, MemoryDealer::getAllocationAlignment())
- * (mNumInputSlots + 1),
+ * (numInputSlots + 1),
"EncryptedLinearInputBuffers");
mDecryptDestination = mDealer->allocate((size_t)capacity);
}
@@ -877,24 +919,24 @@
} else {
mHeapSeqNum = -1;
}
- buffers->reset(new EncryptedLinearInputBuffers(
+ input->buffers.reset(new EncryptedLinearInputBuffers(
secure, mDealer, mCrypto, mHeapSeqNum, (size_t)capacity,
- mNumInputSlots, mName));
+ numInputSlots, mName));
forceArrayMode = true;
} else {
- buffers->reset(new LinearInputBuffers(mName));
+ input->buffers.reset(new LinearInputBuffers(mName));
}
}
- (*buffers)->setFormat(inputFormat);
+ input->buffers->setFormat(inputFormat);
if (err == C2_OK) {
- (*buffers)->setPool(pool);
+ input->buffers->setPool(pool);
} else {
// TODO: error
}
if (forceArrayMode) {
- *buffers = (*buffers)->toArrayMode(mNumInputSlots);
+ input->buffers = input->buffers->toArrayMode(numInputSlots);
}
}
@@ -903,7 +945,7 @@
uint32_t outputGeneration;
{
Mutexed<OutputSurface>::Locked output(mOutputSurface);
- output->maxDequeueBuffers = mNumOutputSlots + reorderDepth.value + kRenderingDepth;
+ output->maxDequeueBuffers = numOutputSlots + reorderDepth.value + kRenderingDepth;
outputSurface = output->surface ?
output->surface->getIGraphicBufferProducer() : nullptr;
if (outputSurface) {
@@ -1011,18 +1053,18 @@
outputPoolId_ = pools->outputPoolId;
}
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
-
+ Mutexed<Output>::Locked output(mOutput);
+ output->numSlots = numOutputSlots;
if (graphic) {
if (outputSurface) {
- buffers->reset(new GraphicOutputBuffers(mName));
+ output->buffers.reset(new GraphicOutputBuffers(mName));
} else {
- buffers->reset(new RawGraphicOutputBuffers(mNumOutputSlots, mName));
+ output->buffers.reset(new RawGraphicOutputBuffers(numOutputSlots, mName));
}
} else {
- buffers->reset(new LinearOutputBuffers(mName));
+ output->buffers.reset(new LinearOutputBuffers(mName));
}
- (*buffers)->setFormat(outputFormat->dup());
+ output->buffers->setFormat(outputFormat->dup());
// Try to set output surface to created block pool if given.
@@ -1038,7 +1080,7 @@
// WORKAROUND: if we're using early CSD workaround we convert to
// array mode, to appease apps assuming the output
// buffers to be of the same size.
- (*buffers) = (*buffers)->toArrayMode(mNumOutputSlots);
+ output->buffers = output->buffers->toArrayMode(numOutputSlots);
int32_t channelCount;
int32_t sampleRate;
@@ -1055,7 +1097,7 @@
if (delay || padding) {
// We need write access to the buffers, and we're already in
// array mode.
- (*buffers)->initSkipCutBuffer(delay, padding, sampleRate, channelCount);
+ output->buffers->initSkipCutBuffer(delay, padding, sampleRate, channelCount);
}
}
}
@@ -1090,14 +1132,14 @@
if (err != C2_OK) {
return UNKNOWN_ERROR;
}
+ size_t numInputSlots = mInput.lock()->numSlots;
std::vector<sp<MediaCodecBuffer>> toBeQueued;
- // TODO: use proper buffer depth instead of this random value
- for (size_t i = 0; i < mNumInputSlots; ++i) {
+ for (size_t i = 0; i < numInputSlots; ++i) {
size_t index;
sp<MediaCodecBuffer> buffer;
{
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- if (!(*buffers)->requestNewBuffer(&index, &buffer)) {
+ Mutexed<Input>::Locked input(mInput);
+ if (!input->buffers->requestNewBuffer(&index, &buffer)) {
if (i == 0) {
ALOGW("[%s] start: cannot allocate memory at all", mName);
return NO_MEMORY;
@@ -1182,12 +1224,13 @@
}
}
{
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- (*buffers)->flush();
+ Mutexed<Input>::Locked input(mInput);
+ input->buffers->flush();
+ input->extraBuffers.flush();
}
{
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- (*buffers)->flush(flushedWork);
+ Mutexed<Output>::Locked output(mOutput);
+ output->buffers->flush(flushedWork);
}
mReorderStash.lock()->flush();
mPipelineWatcher.lock()->flush();
@@ -1210,8 +1253,11 @@
mPipelineWatcher.lock()->onInputBufferReleased(frameIndex, arrayIndex);
bool newInputSlotAvailable;
{
- Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
- newInputSlotAvailable = (*buffers)->expireComponentBuffer(buffer);
+ Mutexed<Input>::Locked input(mInput);
+ newInputSlotAvailable = input->buffers->expireComponentBuffer(buffer);
+ if (!newInputSlotAvailable) {
+ (void)input->extraBuffers.expireComponentBuffer(buffer);
+ }
}
if (newInputSlotAvailable) {
feedInputBufferIfAvailable();
@@ -1269,6 +1315,7 @@
}
}
+ std::optional<uint32_t> newInputDelay, newPipelineDelay;
while (!worklet->output.configUpdate.empty()) {
std::unique_ptr<C2Param> param;
worklet->output.configUpdate.back().swap(param);
@@ -1280,8 +1327,10 @@
mReorderStash.lock()->setDepth(reorderDepth.value);
ALOGV("[%s] onWorkDone: updated reorder depth to %u",
mName, reorderDepth.value);
+ size_t numOutputSlots = mOutput.lock()->numSlots;
Mutexed<OutputSurface>::Locked output(mOutputSurface);
- output->maxDequeueBuffers = mNumOutputSlots + reorderDepth.value + kRenderingDepth;
+ output->maxDequeueBuffers =
+ numOutputSlots + reorderDepth.value + kRenderingDepth;
if (output->surface) {
output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
}
@@ -1301,18 +1350,86 @@
}
break;
}
+ case C2PortActualDelayTuning::CORE_INDEX: {
+ if (param->isGlobal()) {
+ C2ActualPipelineDelayTuning pipelineDelay;
+ if (pipelineDelay.updateFrom(*param)) {
+ ALOGV("[%s] onWorkDone: updating pipeline delay %u",
+ mName, pipelineDelay.value);
+ newPipelineDelay = pipelineDelay.value;
+ (void)mPipelineWatcher.lock()->pipelineDelay(pipelineDelay.value);
+ }
+ }
+ if (param->forInput()) {
+ C2PortActualDelayTuning::input inputDelay;
+ if (inputDelay.updateFrom(*param)) {
+ ALOGV("[%s] onWorkDone: updating input delay %u",
+ mName, inputDelay.value);
+ newInputDelay = inputDelay.value;
+ (void)mPipelineWatcher.lock()->inputDelay(inputDelay.value);
+ }
+ }
+ if (param->forOutput()) {
+ C2PortActualDelayTuning::output outputDelay;
+ if (outputDelay.updateFrom(*param)) {
+ ALOGV("[%s] onWorkDone: updating output delay %u",
+ mName, outputDelay.value);
+ (void)mPipelineWatcher.lock()->outputDelay(outputDelay.value);
+
+ bool outputBuffersChanged = false;
+ Mutexed<Output>::Locked output(mOutput);
+ output->outputDelay = outputDelay.value;
+ size_t numOutputSlots = outputDelay.value + kSmoothnessFactor;
+ if (output->numSlots < numOutputSlots) {
+ output->numSlots = numOutputSlots;
+ if (output->buffers->isArrayMode()) {
+ OutputBuffersArray *array =
+ (OutputBuffersArray *)output->buffers.get();
+ ALOGV("[%s] onWorkDone: growing output buffer array to %zu",
+ mName, numOutputSlots);
+ array->grow(numOutputSlots);
+ outputBuffersChanged = true;
+ }
+ }
+ output.unlock();
+
+ if (outputBuffersChanged) {
+ mCCodecCallback->onOutputBuffersChanged();
+ }
+ }
+ }
+ break;
+ }
default:
ALOGV("[%s] onWorkDone: unrecognized config update (%08X)",
mName, param->index());
break;
}
}
+ if (newInputDelay || newPipelineDelay) {
+ Mutexed<Input>::Locked input(mInput);
+ size_t newNumSlots =
+ newInputDelay.value_or(input->inputDelay) +
+ newPipelineDelay.value_or(input->pipelineDelay) +
+ kSmoothnessFactor;
+ if (input->buffers->isArrayMode()) {
+ if (input->numSlots >= newNumSlots) {
+ input->numExtraSlots = 0;
+ } else {
+ input->numExtraSlots = newNumSlots - input->numSlots;
+ }
+ ALOGV("[%s] onWorkDone: updated number of extra slots to %zu (input array mode)",
+ mName, input->numExtraSlots);
+ } else {
+ input->numSlots = newNumSlots;
+ }
+ }
if (outputFormat != nullptr) {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
+ Mutexed<Output>::Locked output(mOutput);
ALOGD("[%s] onWorkDone: output format changed to %s",
mName, outputFormat->debugString().c_str());
- (*buffers)->setFormat(outputFormat);
+ output->buffers->setFormat(outputFormat);
AString mediaType;
if (outputFormat->findString(KEY_MIME, &mediaType)
@@ -1321,7 +1438,7 @@
int32_t sampleRate;
if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
&& outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
- (*buffers)->updateSkipCutBuffer(sampleRate, channelCount);
+ output->buffers->updateSkipCutBuffer(sampleRate, channelCount);
}
}
}
@@ -1356,20 +1473,18 @@
timestamp.peekll());
if (initData != nullptr) {
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- if ((*buffers)->registerCsd(initData, &index, &outBuffer) == OK) {
+ Mutexed<Output>::Locked output(mOutput);
+ if (output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
outBuffer->meta()->setInt64("timeUs", timestamp.peek());
outBuffer->meta()->setInt32("flags", MediaCodec::BUFFER_FLAG_CODECCONFIG);
ALOGV("[%s] onWorkDone: csd index = %zu [%p]", mName, index, outBuffer.get());
- buffers.unlock();
+ output.unlock();
mCallback->onOutputBufferAvailable(index, outBuffer);
- buffers.lock();
} else {
ALOGD("[%s] onWorkDone: unable to register csd", mName);
- buffers.unlock();
+ output.unlock();
mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- buffers.lock();
return false;
}
}
@@ -1421,22 +1536,22 @@
break;
}
- Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
- status_t err = (*buffers)->registerBuffer(entry.buffer, &index, &outBuffer);
+ Mutexed<Output>::Locked output(mOutput);
+ status_t err = output->buffers->registerBuffer(entry.buffer, &index, &outBuffer);
if (err != OK) {
bool outputBuffersChanged = false;
if (err != WOULD_BLOCK) {
- if (!(*buffers)->isArrayMode()) {
- *buffers = (*buffers)->toArrayMode(mNumOutputSlots);
+ if (!output->buffers->isArrayMode()) {
+ output->buffers = output->buffers->toArrayMode(output->numSlots);
}
- OutputBuffersArray *array = (OutputBuffersArray *)buffers->get();
+ OutputBuffersArray *array = (OutputBuffersArray *)output->buffers.get();
array->realloc(entry.buffer);
outputBuffersChanged = true;
}
ALOGV("[%s] sendOutputBuffers: unable to register output buffer", mName);
reorder->defer(entry);
- buffers.unlock();
+ output.unlock();
reorder.unlock();
if (outputBuffersChanged) {
@@ -1444,7 +1559,7 @@
}
return;
}
- buffers.unlock();
+ output.unlock();
reorder.unlock();
outBuffer->meta()->setInt64("timeUs", entry.timestamp);
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 9aec82d..ae57678 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -209,7 +209,7 @@
void feedInputBufferIfAvailable();
void feedInputBufferIfAvailableInternal();
- status_t queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer);
+ status_t queueInputBufferInternal(sp<MediaCodecBuffer> buffer);
bool handleWork(
std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
const C2StreamInitDataInfo::output *initData);
@@ -228,13 +228,26 @@
QueueSync mQueueSync;
std::vector<std::unique_ptr<C2Param>> mParamsToBeSet;
- size_t mNumInputSlots;
- size_t mNumOutputSlots;
size_t mDelay;
- Mutexed<std::unique_ptr<InputBuffers>> mInputBuffers;
+ struct Input {
+ Input();
+
+ std::unique_ptr<InputBuffers> buffers;
+ size_t numSlots;
+ FlexBuffersImpl extraBuffers;
+ size_t numExtraSlots;
+ uint32_t inputDelay;
+ uint32_t pipelineDelay;
+ };
+ Mutexed<Input> mInput;
+ struct Output {
+ std::unique_ptr<OutputBuffers> buffers;
+ size_t numSlots;
+ uint32_t outputDelay;
+ };
+ Mutexed<Output> mOutput;
Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs;
- Mutexed<std::unique_ptr<OutputBuffers>> mOutputBuffers;
std::atomic_uint64_t mFrameIndex;
std::atomic_uint64_t mFirstValidFrameIndex;
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index fb0efce..5ebd5bd 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -98,6 +98,26 @@
}
}
+// InputBuffers
+
+sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
+ sp<Codec2Buffer> copy = createNewBuffer();
+ if (copy == nullptr) {
+ return nullptr;
+ }
+ std::shared_ptr<C2Buffer> c2buffer;
+ if (!releaseBuffer(buffer, &c2buffer, true)) {
+ return nullptr;
+ }
+ if (!copy->canCopy(c2buffer)) {
+ return nullptr;
+ }
+ if (!copy->copy(c2buffer)) {
+ return nullptr;
+ }
+ return copy;
+}
+
// OutputBuffers
void OutputBuffers::initSkipCutBuffer(
@@ -197,6 +217,8 @@
mPool.push_front(std::move(vec));
}
+// FlexBuffersImpl
+
size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
for (size_t i = 0; i < mBuffers.size(); ++i) {
if (mBuffers[i].clientBuffer == nullptr
@@ -209,8 +231,6 @@
return mBuffers.size() - 1;
}
-// FlexBuffersImpl
-
bool FlexBuffersImpl::releaseSlot(
const sp<MediaCodecBuffer> &buffer,
std::shared_ptr<C2Buffer> *c2buffer,
@@ -270,6 +290,14 @@
});
}
+size_t FlexBuffersImpl::numComponentBuffers() const {
+ return std::count_if(
+ mBuffers.begin(), mBuffers.end(),
+ [](const Entry &entry) {
+ return !entry.compBuffer.expired();
+ });
+}
+
// BuffersArrayImpl
void BuffersArrayImpl::initialize(
@@ -395,6 +423,14 @@
}
}
+void BuffersArrayImpl::grow(
+ size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
+ CHECK_LT(mBuffers.size(), newSize);
+ while (mBuffers.size() < newSize) {
+ mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
+ }
+}
+
size_t BuffersArrayImpl::numClientBuffers() const {
return std::count_if(
mBuffers.begin(), mBuffers.end(),
@@ -409,6 +445,7 @@
const FlexBuffersImpl &impl,
size_t minSize,
std::function<sp<Codec2Buffer>()> allocate) {
+ mAllocate = allocate;
mImpl.initialize(impl, minSize, allocate);
}
@@ -448,18 +485,14 @@
return mImpl.numClientBuffers();
}
+sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
+ return mAllocate();
+}
+
// LinearInputBuffers
bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
- int32_t capacity = kLinearBufferSize;
- (void)mFormat->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
- if ((size_t)capacity > kMaxLinearBufferSize) {
- ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
- capacity = kMaxLinearBufferSize;
- }
- // TODO: proper max input size
- // TODO: read usage from intf
- sp<Codec2Buffer> newBuffer = alloc((size_t)capacity);
+ sp<Codec2Buffer> newBuffer = createNewBuffer();
if (newBuffer == nullptr) {
return false;
}
@@ -486,16 +519,7 @@
mImpl.flush();
}
-std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(
- size_t size) {
- int32_t capacity = kLinearBufferSize;
- (void)mFormat->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
- if ((size_t)capacity > kMaxLinearBufferSize) {
- ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
- capacity = kMaxLinearBufferSize;
- }
- // TODO: proper max input size
- // TODO: read usage from intf
+std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
std::unique_ptr<InputBuffersArray> array(
new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
array->setPool(mPool);
@@ -503,7 +527,9 @@
array->initialize(
mImpl,
size,
- [this, capacity] () -> sp<Codec2Buffer> { return alloc(capacity); });
+ [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
+ return Alloc(pool, format);
+ });
return std::move(array);
}
@@ -511,16 +537,30 @@
return mImpl.numClientBuffers();
}
-sp<Codec2Buffer> LinearInputBuffers::alloc(size_t size) {
+// static
+sp<Codec2Buffer> LinearInputBuffers::Alloc(
+ const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
+ int32_t capacity = kLinearBufferSize;
+ (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
+ if ((size_t)capacity > kMaxLinearBufferSize) {
+ ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
+ capacity = kMaxLinearBufferSize;
+ }
+
+ // TODO: read usage from intf
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
std::shared_ptr<C2LinearBlock> block;
- c2_status_t err = mPool->fetchLinearBlock(size, usage, &block);
+ c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
if (err != C2_OK) {
return nullptr;
}
- return LinearBlockBuffer::Allocate(mFormat, block);
+ return LinearBlockBuffer::Allocate(format, block);
+}
+
+sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
+ return Alloc(mPool, mFormat);
}
// EncryptedLinearInputBuffers
@@ -537,7 +577,7 @@
mUsage({0, 0}),
mDealer(dealer),
mCrypto(crypto),
- mHeapSeqNum(heapSeqNum) {
+ mMemoryVector(new std::vector<Entry>){
if (secure) {
mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
} else {
@@ -550,16 +590,48 @@
mName, i);
break;
}
- mMemoryVector.push_back({std::weak_ptr<C2LinearBlock>(), memory});
+ mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
}
}
-sp<Codec2Buffer> EncryptedLinearInputBuffers::alloc(size_t size) {
+std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
+ std::unique_ptr<InputBuffersArray> array(
+ new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
+ array->setPool(mPool);
+ array->setFormat(mFormat);
+ array->initialize(
+ mImpl,
+ size,
+ [pool = mPool,
+ format = mFormat,
+ usage = mUsage,
+ memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
+ return Alloc(pool, format, usage, memoryVector);
+ });
+ return std::move(array);
+}
+
+
+// static
+sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
+ const std::shared_ptr<C2BlockPool> &pool,
+ const sp<AMessage> &format,
+ C2MemoryUsage usage,
+ const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
+ int32_t capacity = kLinearBufferSize;
+ (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
+ if ((size_t)capacity > kMaxLinearBufferSize) {
+ ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
+ capacity = kMaxLinearBufferSize;
+ }
+
sp<IMemory> memory;
size_t slot = 0;
- for (; slot < mMemoryVector.size(); ++slot) {
- if (mMemoryVector[slot].block.expired()) {
- memory = mMemoryVector[slot].memory;
+ int32_t heapSeqNum = -1;
+ for (; slot < memoryVector->size(); ++slot) {
+ if (memoryVector->at(slot).block.expired()) {
+ memory = memoryVector->at(slot).memory;
+ heapSeqNum = memoryVector->at(slot).heapSeqNum;
break;
}
}
@@ -568,13 +640,18 @@
}
std::shared_ptr<C2LinearBlock> block;
- c2_status_t err = mPool->fetchLinearBlock(size, mUsage, &block);
+ c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
if (err != C2_OK || block == nullptr) {
return nullptr;
}
- mMemoryVector[slot].block = block;
- return new EncryptedLinearBlockBuffer(mFormat, block, memory, mHeapSeqNum);
+ memoryVector->at(slot).block = block;
+ return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
+}
+
+sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
+ // TODO: android_2020
+ return nullptr;
}
// GraphicMetadataInputBuffers
@@ -587,12 +664,7 @@
bool GraphicMetadataInputBuffers::requestNewBuffer(
size_t *index, sp<MediaCodecBuffer> *buffer) {
- std::shared_ptr<C2Allocator> alloc;
- c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
- if (err != C2_OK) {
- return false;
- }
- sp<GraphicMetadataBuffer> newBuffer = new GraphicMetadataBuffer(mFormat, alloc);
+ sp<Codec2Buffer> newBuffer = createNewBuffer();
if (newBuffer == nullptr) {
return false;
}
@@ -642,6 +714,15 @@
return mImpl.numClientBuffers();
}
+sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
+ std::shared_ptr<C2Allocator> alloc;
+ c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
+ if (err != C2_OK) {
+ return nullptr;
+ }
+ return new GraphicMetadataBuffer(mFormat, alloc);
+}
+
// GraphicInputBuffers
GraphicInputBuffers::GraphicInputBuffers(
@@ -652,11 +733,7 @@
kMaxLinearBufferSize * numInputSlots)) { }
bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
- // 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);
+ sp<Codec2Buffer> newBuffer = createNewBuffer();
if (newBuffer == nullptr) {
return false;
}
@@ -703,12 +780,20 @@
return mImpl.numClientBuffers();
}
+sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
+ // TODO: read usage from intf
+ C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+ return AllocateGraphicBuffer(
+ mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
+}
+
// OutputBuffersArray
void OutputBuffersArray::initialize(
const FlexBuffersImpl &impl,
size_t minSize,
std::function<sp<Codec2Buffer>()> allocate) {
+ mAlloc = allocate;
mImpl.initialize(impl, minSize, allocate);
}
@@ -781,8 +866,11 @@
mImpl.getArray(array);
}
+size_t OutputBuffersArray::numClientBuffers() const {
+ return mImpl.numClientBuffers();
+}
+
void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
- std::function<sp<Codec2Buffer>()> alloc;
switch (c2buffer->data().type()) {
case C2BufferData::LINEAR: {
uint32_t size = kLinearBufferSize;
@@ -792,7 +880,7 @@
} else {
size = kMaxLinearBufferSize;
}
- alloc = [format = mFormat, size] {
+ mAlloc = [format = mFormat, size] {
return new LocalLinearBuffer(format, new ABuffer(size));
};
break;
@@ -808,11 +896,11 @@
ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
return;
}
- mImpl.realloc(alloc);
+ mImpl.realloc(mAlloc);
}
-size_t OutputBuffersArray::numClientBuffers() const {
- return mImpl.numClientBuffers();
+void OutputBuffersArray::grow(size_t newSize) {
+ mImpl.grow(newSize, mAlloc);
}
// FlexOutputBuffers
@@ -861,10 +949,8 @@
std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
array->setFormat(mFormat);
array->transferSkipCutBuffer(mSkipCutBuffer);
- array->initialize(
- mImpl,
- size,
- [this]() { return allocateArrayBuffer(); });
+ std::function<sp<Codec2Buffer>()> alloc = getAlloc();
+ array->initialize(mImpl, size, alloc);
return std::move(array);
}
@@ -906,9 +992,11 @@
return clientBuffer;
}
-sp<Codec2Buffer> LinearOutputBuffers::allocateArrayBuffer() {
- // TODO: proper max output size
- return new LocalLinearBuffer(mFormat, new ABuffer(kLinearBufferSize));
+std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
+ return [format = mFormat]{
+ // TODO: proper max output size
+ return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
+ };
}
// GraphicOutputBuffers
@@ -917,8 +1005,10 @@
return new DummyContainerBuffer(mFormat, buffer);
}
-sp<Codec2Buffer> GraphicOutputBuffers::allocateArrayBuffer() {
- return new DummyContainerBuffer(mFormat);
+std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
+ return [format = mFormat]{
+ return new DummyContainerBuffer(format);
+ };
}
// RawGraphicOutputBuffers
@@ -952,12 +1042,14 @@
}
}
-sp<Codec2Buffer> RawGraphicOutputBuffers::allocateArrayBuffer() {
- return ConstGraphicBlockBuffer::AllocateEmpty(
- mFormat,
- [lbp = mLocalBufferPool](size_t capacity) {
- return lbp->newBuffer(capacity);
- });
+std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
+ return [format = mFormat, lbp = mLocalBufferPool]{
+ return ConstGraphicBlockBuffer::AllocateEmpty(
+ format,
+ [lbp](size_t capacity) {
+ return lbp->newBuffer(capacity);
+ });
+ };
}
} // namespace android
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index f5d9fee..e4f2809 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -31,7 +31,7 @@
constexpr size_t kLinearBufferSize = 1048576;
// This can fit 4K RGBA frame, and most likely client won't need more than this.
-constexpr size_t kMaxLinearBufferSize = 3840 * 2160 * 4;
+constexpr size_t kMaxLinearBufferSize = 4096 * 2304 * 4;
/**
* Base class for representation of buffers at one port.
@@ -134,7 +134,18 @@
*/
virtual std::unique_ptr<InputBuffers> toArrayMode(size_t size) = 0;
+ /**
+ * Release the buffer obtained from requestNewBuffer(), and create a deep
+ * copy clone of the buffer.
+ *
+ * \return the deep copy clone of the buffer; nullptr if cloning is not
+ * possible.
+ */
+ sp<Codec2Buffer> cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer);
+
protected:
+ virtual sp<Codec2Buffer> createNewBuffer() = 0;
+
// Pool to obtain blocks for input buffers.
std::shared_ptr<C2BlockPool> mPool;
@@ -346,6 +357,12 @@
*/
size_t numClientBuffers() const;
+ /**
+ * Return the number of buffers that are sent to the component but not
+ * returned back yet.
+ */
+ size_t numComponentBuffers() const;
+
private:
friend class BuffersArrayImpl;
@@ -446,6 +463,16 @@
void realloc(std::function<sp<Codec2Buffer>()> alloc);
/**
+ * Grow the array to the new size. It is a programming error to supply
+ * smaller size as the new size.
+ *
+ * \param newSize[in] new size of the array.
+ * \param alloc[in] the alllocation function for client buffers to fill
+ * the new empty slots.
+ */
+ void grow(size_t newSize, std::function<sp<Codec2Buffer>()> alloc);
+
+ /**
* Return the number of buffers that are sent to the client but not released
* yet.
*/
@@ -506,8 +533,12 @@
size_t numClientBuffers() const final;
+protected:
+ sp<Codec2Buffer> createNewBuffer() override;
+
private:
BuffersArrayImpl mImpl;
+ std::function<sp<Codec2Buffer>()> mAllocate;
};
class LinearInputBuffers : public InputBuffers {
@@ -529,18 +560,18 @@
void flush() override;
- std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
+ std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
size_t numClientBuffers() const final;
- /**
- * Allocate a client buffer with the given size. This method may be
- * overridden to support different kind of linear buffers (e.g. encrypted).
- */
- virtual sp<Codec2Buffer> alloc(size_t size);
+protected:
+ sp<Codec2Buffer> createNewBuffer() override;
+
+ FlexBuffersImpl mImpl;
private:
- FlexBuffersImpl mImpl;
+ static sp<Codec2Buffer> Alloc(
+ const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format);
};
class EncryptedLinearInputBuffers : public LinearInputBuffers {
@@ -556,18 +587,28 @@
~EncryptedLinearInputBuffers() override = default;
- sp<Codec2Buffer> alloc(size_t size) override;
+ std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
+
+protected:
+ sp<Codec2Buffer> createNewBuffer() override;
private:
- C2MemoryUsage mUsage;
- sp<MemoryDealer> mDealer;
- sp<ICrypto> mCrypto;
- int32_t mHeapSeqNum;
struct Entry {
std::weak_ptr<C2LinearBlock> block;
sp<IMemory> memory;
+ int32_t heapSeqNum;
};
- std::vector<Entry> mMemoryVector;
+
+ static sp<Codec2Buffer> Alloc(
+ const std::shared_ptr<C2BlockPool> &pool,
+ const sp<AMessage> &format,
+ C2MemoryUsage usage,
+ const std::shared_ptr<std::vector<Entry>> &memoryVector);
+
+ C2MemoryUsage mUsage;
+ sp<MemoryDealer> mDealer;
+ sp<ICrypto> mCrypto;
+ std::shared_ptr<std::vector<Entry>> mMemoryVector;
};
class GraphicMetadataInputBuffers : public InputBuffers {
@@ -591,6 +632,9 @@
size_t numClientBuffers() const final;
+protected:
+ sp<Codec2Buffer> createNewBuffer() override;
+
private:
FlexBuffersImpl mImpl;
std::shared_ptr<C2AllocatorStore> mStore;
@@ -619,6 +663,9 @@
size_t numClientBuffers() const final;
+protected:
+ sp<Codec2Buffer> createNewBuffer() override;
+
private:
FlexBuffersImpl mImpl;
std::shared_ptr<LocalBufferPool> mLocalBufferPool;
@@ -658,6 +705,11 @@
size_t numClientBuffers() const final {
return 0u;
}
+
+protected:
+ sp<Codec2Buffer> createNewBuffer() override {
+ return nullptr;
+ }
};
class OutputBuffersArray : public OutputBuffers {
@@ -704,6 +756,8 @@
void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
+ size_t numClientBuffers() const final;
+
/**
* Reallocate the array, filled with buffers with the same size as given
* buffer.
@@ -712,10 +766,17 @@
*/
void realloc(const std::shared_ptr<C2Buffer> &c2buffer);
- size_t numClientBuffers() const final;
+ /**
+ * Grow the array to the new size. It is a programming error to supply
+ * smaller size as the new size.
+ *
+ * \param newSize[in] new size of the array.
+ */
+ void grow(size_t newSize);
private:
BuffersArrayImpl mImpl;
+ std::function<sp<Codec2Buffer>()> mAlloc;
};
class FlexOutputBuffers : public OutputBuffers {
@@ -755,12 +816,15 @@
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 a function that allocates an appropriate Codec2Buffer object for
+ * the type of buffers, to be used as an empty array buffer. The function
+ * must not refer to this pointer, since it may be used after this object
+ * destructs.
*
- * \return appropriate Codec2Buffer object which can copy() from C2Buffers.
+ * \return a function that allocates appropriate Codec2Buffer object,
+ * which can copy() from C2Buffers.
*/
- virtual sp<Codec2Buffer> allocateArrayBuffer() = 0;
+ virtual std::function<sp<Codec2Buffer>()> getAlloc() = 0;
private:
FlexBuffersImpl mImpl;
@@ -776,7 +840,7 @@
sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
- sp<Codec2Buffer> allocateArrayBuffer() override;
+ std::function<sp<Codec2Buffer>()> getAlloc() override;
};
class GraphicOutputBuffers : public FlexOutputBuffers {
@@ -786,7 +850,7 @@
sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
- sp<Codec2Buffer> allocateArrayBuffer() override;
+ std::function<sp<Codec2Buffer>()> getAlloc() override;
};
class RawGraphicOutputBuffers : public FlexOutputBuffers {
@@ -797,7 +861,7 @@
sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
- sp<Codec2Buffer> allocateArrayBuffer() override;
+ std::function<sp<Codec2Buffer>()> getAlloc() override;
private:
std::shared_ptr<LocalBufferPool> mLocalBufferPool;
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 4c3fff7..077a91f 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -532,7 +532,6 @@
}
return C2Value();
}));
- add(ConfigMapper(KEY_QUALITY, C2_PARAMKEY_QUALITY, "value"));
deprecated(ConfigMapper(PARAMETER_KEY_REQUEST_SYNC_FRAME,
"coding.request-sync", "value")
.limitTo(D::PARAM & D::ENCODER)
@@ -798,11 +797,12 @@
}
}));
- add(ConfigMapper(KEY_QUALITY, C2_PARAMKEY_QUALITY, "value"));
+ add(ConfigMapper(KEY_QUALITY, C2_PARAMKEY_QUALITY, "value")
+ .limitTo(D::ENCODER & (D::CONFIG | D::PARAM)));
add(ConfigMapper(KEY_FLAC_COMPRESSION_LEVEL, C2_PARAMKEY_COMPLEXITY, "value")
.limitTo(D::AUDIO & D::ENCODER));
add(ConfigMapper("complexity", C2_PARAMKEY_COMPLEXITY, "value")
- .limitTo(D::ENCODER));
+ .limitTo(D::ENCODER & (D::CONFIG | D::PARAM)));
add(ConfigMapper(KEY_GRID_COLUMNS, C2_PARAMKEY_TILE_LAYOUT, "columns")
.limitTo(D::IMAGE));
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index c6cbad3..702ad6f 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -201,9 +201,10 @@
* \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format,
* an attempt is made to simply represent the graphic view as a flexible SDK format
* without a memcpy)
+ * \param copy whether the converter is used for copy or not
*/
GraphicView2MediaImageConverter(
- const C2GraphicView &view, int32_t colorFormat)
+ const C2GraphicView &view, int32_t colorFormat, bool copy)
: mInitCheck(NO_INIT),
mView(view),
mWidth(view.width()),
@@ -229,8 +230,8 @@
uint32_t bitDepth = layout.planes[0].bitDepth;
// align width and height to support subsampling cleanly
- uint32_t mStride = align(mWidth, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
- uint32_t mVStride = align(mHeight, 2);
+ uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
+ uint32_t vStride = align(view.crop().height, 2);
switch (layout.type) {
case C2PlanarLayout::TYPE_YUV:
@@ -255,59 +256,62 @@
}
switch (mColorFormat) {
case COLOR_FormatYUV420Flexible:
- { // try to map directly. check if the planes are near one another
- 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) * align(mHeight, 64)
- / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
- }
-
- if ((maxPtr - minPtr + 1) <= planeSize) {
- // FIXME: this is risky as reading/writing data out of bound results in
- // an undefined behavior, but gralloc does assume a contiguous
- // mapping
+ if (!copy) {
+ // try to map directly. check if the planes are near one another
+ 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];
- 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;
+ 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) * align(mHeight, 64)
+ / plane.rowSampling / plane.colSampling
+ * divUp(mAllocatedDepth, 8u);
}
- mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr + 1);
- break;
+
+ if ((maxPtr - minPtr + 1) <= planeSize) {
+ // FIXME: this is risky as reading/writing data out of bound results
+ // in an undefined behavior, but gralloc does assume a
+ // contiguous mapping
+ 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;
+ }
+ mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
+ maxPtr - minPtr + 1);
+ break;
+ }
}
- }
- [[fallthrough]];
+ [[fallthrough]];
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420PackedPlanar:
mediaImage->mPlane[mediaImage->Y].mOffset = 0;
mediaImage->mPlane[mediaImage->Y].mColInc = 1;
- mediaImage->mPlane[mediaImage->Y].mRowInc = mStride;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
- mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride;
+ mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
mediaImage->mPlane[mediaImage->U].mColInc = 1;
- mediaImage->mPlane[mediaImage->U].mRowInc = mStride / 2;
+ mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
- mediaImage->mPlane[mediaImage->V].mOffset = mStride * mVStride * 5 / 4;
+ mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
mediaImage->mPlane[mediaImage->V].mColInc = 1;
- mediaImage->mPlane[mediaImage->V].mRowInc = mStride / 2;
+ mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
break;
@@ -316,19 +320,19 @@
case COLOR_FormatYUV420PackedSemiPlanar:
mediaImage->mPlane[mediaImage->Y].mOffset = 0;
mediaImage->mPlane[mediaImage->Y].mColInc = 1;
- mediaImage->mPlane[mediaImage->Y].mRowInc = mStride;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
- mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride;
+ mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
mediaImage->mPlane[mediaImage->U].mColInc = 2;
- mediaImage->mPlane[mediaImage->U].mRowInc = mStride;
+ mediaImage->mPlane[mediaImage->U].mRowInc = stride;
mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
- mediaImage->mPlane[mediaImage->V].mOffset = mStride * mVStride + 1;
+ mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
mediaImage->mPlane[mediaImage->V].mColInc = 2;
- mediaImage->mPlane[mediaImage->V].mRowInc = mStride;
+ mediaImage->mPlane[mediaImage->V].mRowInc = stride;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
break;
@@ -391,8 +395,8 @@
return;
}
mediaImage->mNumPlanes = layout.numPlanes;
- mediaImage->mWidth = mWidth;
- mediaImage->mHeight = mHeight;
+ mediaImage->mWidth = view.crop().width;
+ mediaImage->mHeight = view.crop().height;
mediaImage->mBitDepth = bitDepth;
mediaImage->mBitDepthAllocated = mAllocatedDepth;
@@ -415,7 +419,7 @@
mInitCheck = BAD_VALUE;
return;
}
- bufferSize += mStride * mVStride
+ bufferSize += stride * vStride
/ plane.rowSampling / plane.colSampling;
}
@@ -503,7 +507,7 @@
int32_t colorFormat = COLOR_FormatYUV420Flexible;
(void)format->findInt32("color-format", &colorFormat);
- GraphicView2MediaImageConverter converter(view, colorFormat);
+ GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -615,7 +619,7 @@
int32_t colorFormat = COLOR_FormatYUV420Flexible;
(void)format->findInt32("color-format", &colorFormat);
- GraphicView2MediaImageConverter converter(*view, colorFormat);
+ GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -652,7 +656,8 @@
ALOGD("format had no width / height");
return nullptr;
}
- sp<ABuffer> aBuffer(alloc(width * height * 4));
+ // NOTE: we currently only support YUV420 formats for byte-buffer mode.
+ sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * 3 / 2));
return new ConstGraphicBlockBuffer(
format,
aBuffer,
@@ -707,7 +712,7 @@
const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat);
+ buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
return false;
@@ -729,7 +734,7 @@
format()->findInt32("color-format", &colorFormat);
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat);
+ buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
return false;
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index dd618aa..36dcab9 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -226,10 +226,10 @@
const std::shared_ptr<C2GraphicBlock> &block,
std::function<sp<ABuffer>(size_t)> alloc);
- std::shared_ptr<C2Buffer> asC2Buffer() override;
-
virtual ~GraphicBlockBuffer() = default;
+ std::shared_ptr<C2Buffer> asC2Buffer() override;
+
private:
GraphicBlockBuffer(
const sp<AMessage> &format,
@@ -260,11 +260,10 @@
*/
GraphicMetadataBuffer(
const sp<AMessage> &format, const std::shared_ptr<C2Allocator> &alloc);
+ virtual ~GraphicMetadataBuffer() = default;
std::shared_ptr<C2Buffer> asC2Buffer() override;
- virtual ~GraphicMetadataBuffer() = default;
-
private:
GraphicMetadataBuffer() = delete;
@@ -307,12 +306,12 @@
const sp<AMessage> &format,
std::function<sp<ABuffer>(size_t)> alloc);
+ virtual ~ConstGraphicBlockBuffer() = 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;
- virtual ~ConstGraphicBlockBuffer() = default;
-
private:
ConstGraphicBlockBuffer(
const sp<AMessage> &format,
diff --git a/media/codec2/sfplugin/ReflectedParamUpdater.cpp b/media/codec2/sfplugin/ReflectedParamUpdater.cpp
index 880d4a5..55b0ec9 100644
--- a/media/codec2/sfplugin/ReflectedParamUpdater.cpp
+++ b/media/codec2/sfplugin/ReflectedParamUpdater.cpp
@@ -205,6 +205,13 @@
const std::shared_ptr<C2ParamReflector> &reflector, bool markVendor) {
C2String paramName = desc->name();
+ // Do not reflect requested parameters
+ // TODO: split these once aliases are introduced into '.actual' and '.requested' and alias
+ // the name to '.actual'.
+ if (desc->index() & C2Param::CoreIndex::IS_REQUEST_FLAG) {
+ return;
+ }
+
// prefix vendor parameters
if (desc->index().isVendor() && markVendor) {
paramName = "vendor." + paramName;
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 6b8663f..bf2a07e 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -118,7 +118,7 @@
} // namespace
status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView &view) {
- if (view.width() != img->mWidth || view.height() != img->mHeight) {
+ if (view.crop().width != img->mWidth || view.crop().height != img->mHeight) {
return BAD_VALUE;
}
if ((IsNV12(view) && IsI420(img)) || (IsI420(view) && IsNV12(img))) {
@@ -137,14 +137,14 @@
int32_t dst_stride_v = img->mPlane[2].mRowInc;
if (IsNV12(view) && IsI420(img)) {
if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
- dst_u, dst_stride_u, dst_v, dst_stride_v, view.width(),
- view.height())) {
+ dst_u, dst_stride_u, dst_v, dst_stride_v, view.crop().width,
+ view.crop().height)) {
return OK;
}
} else {
if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
- dst_y, dst_stride_y, dst_u, dst_stride_u, view.width(),
- view.height())) {
+ dst_y, dst_stride_y, dst_u, dst_stride_u, view.crop().width,
+ view.crop().height)) {
return OK;
}
}
@@ -153,7 +153,7 @@
}
status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage2 *img) {
- if (view.width() != img->mWidth || view.height() != img->mHeight) {
+ if (view.crop().width != img->mWidth || view.crop().height != img->mHeight) {
return BAD_VALUE;
}
if ((IsNV12(img) && IsI420(view)) || (IsI420(img) && IsNV12(view))) {
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index d22153d..752bc46 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -554,7 +554,11 @@
} else {
*align = 0; // TODO make this 1
*heapMask = ~0; // default mask
- *flags = 0; // default flags
+ if (usage.expected & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)) {
+ *flags = ION_FLAG_CACHED; // cache CPU accessed buffers
+ } else {
+ *flags = 0; // default flags
+ }
res = C2_NO_INIT;
}
// add usage to cache
diff --git a/media/codec2/vndk/util/C2InterfaceHelper.cpp b/media/codec2/vndk/util/C2InterfaceHelper.cpp
index e447fbe..9eb52d2 100644
--- a/media/codec2/vndk/util/C2InterfaceHelper.cpp
+++ b/media/codec2/vndk/util/C2InterfaceHelper.cpp
@@ -609,6 +609,9 @@
// { depIx, paramIx } may be a suitable key
std::map<size_t, std::pair<C2Param::Index, bool>> dependencies;
+ std::vector<std::unique_ptr<C2Param>> paramRequests;
+ std::vector<C2Param*> lateReadParams;
+
// we cannot determine the last valid parameter, so add an extra
// loop iteration after the last parameter
for (size_t p_ix = 0; p_ix <= params.size(); ++p_ix) {
@@ -625,7 +628,27 @@
}
paramIx = p->index();
- paramDepIx = getDependencyIndex_l(paramIx);
+
+ // convert parameter to request in case this is a split parameter
+ C2Param::Index requestParamIx = paramIx | C2Param::CoreIndex::IS_REQUEST_FLAG;
+
+ // setting a request directly is handled as normal
+ if (paramIx != requestParamIx) {
+ paramDepIx = getDependencyIndex_l(requestParamIx);
+ if (paramDepIx == SIZE_MAX) {
+ // not a split parameter, handle it normally
+ paramDepIx = getDependencyIndex_l(paramIx);
+ } else {
+ // split parameter - replace with setting for the request - and queue to
+ // read back actual value
+ // TODO: read late params at the right time
+ lateReadParams.emplace_back(p);
+ std::unique_ptr<C2Param> request(C2Param::CopyAsRequest(*p));
+ p = request.get();
+ paramRequests.emplace_back(std::move(request));
+ }
+ }
+
if (paramDepIx == SIZE_MAX) {
// unsupported parameter
paramNotFound = true;
@@ -715,6 +738,16 @@
}
}
+ // get late read parameters
+ for (C2Param *p : lateReadParams) {
+ std::shared_ptr<C2Param> value = _mFactory->getParamValue(p->index());
+ if (value) {
+ p->updateFrom(*value);
+ } else {
+ p->invalidate();
+ }
+ }
+
return (paramCorrupted ? C2_CORRUPTED :
paramBlocking ? C2_BLOCKING :
paramTimedOut ? C2_TIMED_OUT :
@@ -761,9 +794,11 @@
if (p != nullptr) {
heapParams->push_back(std::move(p));
} else {
+ heapParams->push_back(nullptr);
paramNoMemory = true;
}
} else {
+ heapParams->push_back(nullptr);
paramNotFound = true;
}
}
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index b1eb301..23022e4 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -2109,8 +2109,10 @@
if (!strcmp("A_AAC", codecID)) {
AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AAC);
- CHECK(codecPrivateSize >= 2);
-
+ if (codecPrivateSize < 2) {
+ ALOGW("Incomplete AAC Codec Info %zu byte", codecPrivateSize);
+ continue;
+ }
addESDSFromCodecPrivate(
meta, true, codecPrivate, codecPrivateSize);
} else if (!strcmp("A_VORBIS", codecID)) {
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 527bb77..9d5890c 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1197,45 +1197,16 @@
AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
}
- // If format type is 'alac', it is necessary to get the parameters
- // from a alac atom spreading behind the frma atom.
- // See 'external/alac/ALACMagicCookieDescription.txt'.
- if (original_fourcc == FOURCC("alac")) {
- // Store ALAC magic cookie (decoder needs it).
- uint8_t alacInfo[12];
- data_offset = *offset;
- if (mDataSource->readAt(
- data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
- return ERROR_IO;
+ if (!mIsQT && original_fourcc == FOURCC("alac")) {
+ off64_t tmpOffset = *offset;
+ status_t err = parseALACSampleEntry(&tmpOffset);
+ if (err != OK) {
+ ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+ return err;
}
- uint32_t size = U32_AT(&alacInfo[0]);
- if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
- (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
- (U32_AT(&alacInfo[8]) != 0)) {
- return ERROR_MALFORMED;
- }
-
- data_offset += sizeof(alacInfo);
- uint8_t cookie[size - sizeof(alacInfo)];
- if (mDataSource->readAt(
- data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
- return ERROR_IO;
- }
-
- uint8_t bitsPerSample = cookie[5];
- AMediaFormat_setInt32(mLastTrack->meta,
- AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
- AMediaFormat_setInt32(mLastTrack->meta,
- AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
- AMediaFormat_setInt32(mLastTrack->meta,
- AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
- AMediaFormat_setBuffer(mLastTrack->meta,
- AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
-
- // Add the size of ALAC Specific Info (36 bytes) and terminator
- // atom (8 bytes).
- *offset += (size + 8);
+ *offset = tmpOffset + 8;
}
+
break;
}
@@ -1653,7 +1624,18 @@
case 0x6D730055: // "ms U" mp3 audio
{
if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
+
+ if (chunk_type == FOURCC("alac")) {
+ off64_t offsetTmp = *offset;
+ status_t err = parseALACSampleEntry(&offsetTmp);
+ if (err != OK) {
+ ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+ return err;
+ }
+ }
+
// Ignore all atoms embedded in QT wave atom
+ ALOGV("Ignore all atoms embedded in QT wave atom");
*offset += chunk_size;
break;
}
@@ -1792,39 +1774,14 @@
CHECK_EQ(*offset, stop_offset);
}
- if (chunk_type == FOURCC("alac")) {
-
- // See 'external/alac/ALACMagicCookieDescription.txt for the detail'.
- // Store ALAC magic cookie (decoder needs it).
- uint8_t alacInfo[12];
+ if (!mIsQT && chunk_type == FOURCC("alac")) {
data_offset += sizeof(buffer);
- if (mDataSource->readAt(
- data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
- return ERROR_IO;
- }
- uint32_t size = U32_AT(&alacInfo[0]);
- if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
- (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
- (U32_AT(&alacInfo[8]) != 0)) {
- return ERROR_MALFORMED;
- }
- data_offset += sizeof(alacInfo);
- uint8_t cookie[size - sizeof(alacInfo)];
- if (mDataSource->readAt(
- data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
- return ERROR_IO;
- }
- uint8_t bitsPerSample = cookie[5];
- AMediaFormat_setInt32(mLastTrack->meta,
- AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
- AMediaFormat_setInt32(mLastTrack->meta,
- AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
- AMediaFormat_setInt32(mLastTrack->meta,
- AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
- AMediaFormat_setBuffer(mLastTrack->meta,
- AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
- data_offset += sizeof(cookie);
+ status_t err = parseALACSampleEntry(&data_offset);
+ if (err != OK) {
+ ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+ return err;
+ }
*offset = data_offset;
CHECK_EQ(*offset, stop_offset);
}
@@ -3289,6 +3246,45 @@
return OK;
}
+status_t MPEG4Extractor::parseALACSampleEntry(off64_t *offset) {
+ // See 'external/alac/ALACMagicCookieDescription.txt for the detail'.
+ // Store ALAC magic cookie (decoder needs it).
+ uint8_t alacInfo[12];
+ off64_t data_offset = *offset;
+
+ if (mDataSource->readAt(
+ data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
+ return ERROR_IO;
+ }
+ uint32_t size = U32_AT(&alacInfo[0]);
+ if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
+ (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
+ (U32_AT(&alacInfo[8]) != 0)) {
+ ALOGV("Size:%u, U32_AT(&alacInfo[4]):%u, U32_AT(&alacInfo[8]):%u",
+ size, U32_AT(&alacInfo[4]), U32_AT(&alacInfo[8]));
+ return ERROR_MALFORMED;
+ }
+ data_offset += sizeof(alacInfo);
+ uint8_t cookie[size - sizeof(alacInfo)];
+ if (mDataSource->readAt(
+ data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
+ return ERROR_IO;
+ }
+
+ uint8_t bitsPerSample = cookie[5];
+ AMediaFormat_setInt32(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
+ AMediaFormat_setInt32(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
+ AMediaFormat_setInt32(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
+ data_offset += sizeof(cookie);
+ *offset = data_offset;
+ return OK;
+}
+
status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
ALOGV("MPEG4Extractor::parseSegmentIndex");
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index e10bf8a..fcddbb8 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -179,6 +179,7 @@
status_t parseAC3SpecificBox(off64_t offset);
status_t parseEAC3SpecificBox(off64_t offset);
status_t parseAC4SpecificBox(off64_t offset);
+ status_t parseALACSampleEntry(off64_t *offset);
void adjustRawDefaultFrameSize();
MPEG4Extractor(const MPEG4Extractor &);
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 8b539c2ff..4fa7f27 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -505,45 +505,40 @@
// TODO: add capability to return data as float PCM instead of 16 bit PCM.
if (mWaveFormat == WAVE_FORMAT_PCM) {
+ const size_t bytesPerFrame = (mBitsPerSample >> 3) * mNumChannels;
+ const size_t numFrames = n / bytesPerFrame;
+ const size_t numSamples = numFrames * mNumChannels;
if (mOutputFloat) {
float *fdest = (float *)buffer->data();
+ buffer->set_range(0, 4 * numSamples);
switch (mBitsPerSample) {
case 8: {
- buffer->set_range(0, 4 * n);
- memcpy_to_float_from_u8(fdest, (const uint8_t *)buffer->data(), n);
+ memcpy_to_float_from_u8(fdest, (const uint8_t *)buffer->data(), numSamples);
} break;
case 16: {
- const size_t numSamples = n / 2;
- buffer->set_range(0, 4 * numSamples);
memcpy_to_float_from_i16(fdest, (const int16_t *)buffer->data(), numSamples);
} break;
case 24: {
- const size_t numSamples = n / 3;
- buffer->set_range(0, 4 * numSamples);
memcpy_to_float_from_p24(fdest, (const uint8_t *)buffer->data(), numSamples);
} break;
case 32: { // buffer range is correct
- const size_t numSamples = n / 4;
memcpy_to_float_from_i32(fdest, (const int32_t *)buffer->data(), numSamples);
} break;
}
} else {
int16_t *idest = (int16_t *)buffer->data();
+ buffer->set_range(0, 2 * numSamples);
switch (mBitsPerSample) {
case 8: {
- buffer->set_range(0, 2 * n);
- memcpy_to_i16_from_u8(idest, (const uint8_t *)buffer->data(), n);
+ memcpy_to_i16_from_u8(idest, (const uint8_t *)buffer->data(), numSamples);
} break;
case 16:
- break; // no translation needed
+ // no conversion needed
+ break;
case 24: {
- const size_t numSamples = n / 3;
- buffer->set_range(0, 2 * numSamples);
memcpy_to_i16_from_p24(idest, (const uint8_t *)buffer->data(), numSamples);
} break;
case 32: {
- const size_t numSamples = n / 4;
- buffer->set_range(0, 2 * numSamples);
memcpy_to_i16_from_i32(idest, (const int32_t *)buffer->data(), numSamples);
} break;
}
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index 59265fe..c7e92cd 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -157,6 +157,12 @@
buffer->size() + bufferRemaining);
sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
+ if (copy->data() == NULL) {
+ android_errorWriteLog(0x534e4554, "68399439");
+ ALOGE("not enough memory to download: requesting %zu + %zu",
+ buffer->size(), bufferRemaining);
+ return NO_MEMORY;
+ }
memcpy(copy->data(), buffer->data(), buffer->size());
copy->setRange(0, buffer->size());
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
index 088eaae..0dc7722 100644
--- a/media/libstagefright/timedtext/TextDescriptions.cpp
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -383,7 +383,7 @@
tmpData += 8;
size_t remaining = size - 8;
- if (size < chunkSize) {
+ if (chunkSize <= 8 || size < chunkSize) {
return OK;
}
switch(chunkType) {
diff --git a/media/libstagefright/timedtext/TextDescriptions2.cpp b/media/libstagefright/timedtext/TextDescriptions2.cpp
index f48eacc..fd42d3a 100644
--- a/media/libstagefright/timedtext/TextDescriptions2.cpp
+++ b/media/libstagefright/timedtext/TextDescriptions2.cpp
@@ -145,7 +145,7 @@
tmpData += 8;
size_t remaining = size - 8;
- if (size < chunkSize) {
+ if (chunkSize <= 8 || size < chunkSize) {
return OK;
}
switch(chunkType) {