diff options
Diffstat (limited to 'media')
122 files changed, 0 insertions, 36020 deletions
diff --git a/media/codecs/aac/Android.bp b/media/codecs/aac/Android.bp deleted file mode 100644 index b70f30a..0000000 --- a/media/codecs/aac/Android.bp +++ /dev/null @@ -1,30 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2aacdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: [ - "C2SoftAacDec.cpp", - "DrcPresModeWrap.cpp", - ], - - static_libs: [ - "libFraunhoferAAC", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2aacenc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftAacEnc.cpp"], - - static_libs: [ - "libFraunhoferAAC", - ], -} diff --git a/media/codecs/aac/C2SoftAacDec.cpp b/media/codecs/aac/C2SoftAacDec.cpp deleted file mode 100644 index c7c8442..0000000 --- a/media/codecs/aac/C2SoftAacDec.cpp +++ /dev/null @@ -1,941 +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 "C2SoftAacDec" -#include <log/log.h> - -#include <inttypes.h> -#include <math.h> -#include <numeric> - -#include <cutils/properties.h> -#include <media/stagefright/foundation/MediaDefs.h> -#include <media/stagefright/foundation/hexdump.h> -#include <media/stagefright/MediaErrors.h> -#include <utils/misc.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftAacDec.h" - -#define FILEREAD_MAX_LAYERS 2 - -#define DRC_DEFAULT_MOBILE_REF_LEVEL -16.0 /* 64*-0.25dB = -16 dB below full scale for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_CUT 1.0 /* maximum compression of dynamic range for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_BOOST 1.0 /* maximum compression of dynamic range for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_HEAVY C2Config::DRC_COMPRESSION_HEAVY /* switch for heavy compression for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */ -#define DRC_DEFAULT_MOBILE_ENC_LEVEL (0.25) /* 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" -#define PROP_DRC_OVERRIDE_EFFECT "ro.aac_drc_effect_type" - -namespace android { - -class C2SoftAacDec::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_AAC)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 44100)) - .withFields({C2F(mSampleRate, value).oneOf({ - 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 - })}) - .withSetter(Setter<decltype(*mSampleRate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).inRange(1, 8)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(8000, 960000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .build()); - - addParameter( - DefineParam(mAacFormat, C2_NAME_STREAM_AAC_FORMAT_SETTING) - .withDefault(new C2StreamAacFormatInfo::input(0u, C2AacStreamFormatRaw)) - .withFields({C2F(mAacFormat, value).oneOf({ - C2AacStreamFormatRaw, C2AacStreamFormatAdts - })}) - .withSetter(Setter<decltype(*mAacFormat)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_AAC_LC, C2Config::LEVEL_UNUSED)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_AAC_LC, - C2Config::PROFILE_AAC_HE, - C2Config::PROFILE_AAC_HE_PS, - C2Config::PROFILE_AAC_LD, - C2Config::PROFILE_AAC_ELD, - C2Config::PROFILE_AAC_ER_SCALABLE, - C2Config::PROFILE_AAC_XHE}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_UNUSED - }) - }) - .withSetter(ProfileLevelSetter) - .build()); - - addParameter( - DefineParam(mDrcCompressMode, C2_PARAMKEY_DRC_COMPRESSION_MODE) - .withDefault(new C2StreamDrcCompressionModeTuning::input(0u, C2Config::DRC_COMPRESSION_HEAVY)) - .withFields({ - C2F(mDrcCompressMode, value).oneOf({ - C2Config::DRC_COMPRESSION_ODM_DEFAULT, - C2Config::DRC_COMPRESSION_NONE, - C2Config::DRC_COMPRESSION_LIGHT, - C2Config::DRC_COMPRESSION_HEAVY}) - }) - .withSetter(Setter<decltype(*mDrcCompressMode)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcTargetRefLevel, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL) - .withDefault(new C2StreamDrcTargetReferenceLevelTuning::input(0u, DRC_DEFAULT_MOBILE_REF_LEVEL)) - .withFields({C2F(mDrcTargetRefLevel, value).inRange(-31.75, 0.25)}) - .withSetter(Setter<decltype(*mDrcTargetRefLevel)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcEncTargetLevel, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL) - .withDefault(new C2StreamDrcEncodedTargetLevelTuning::input(0u, DRC_DEFAULT_MOBILE_ENC_LEVEL)) - .withFields({C2F(mDrcEncTargetLevel, value).inRange(-31.75, 0.25)}) - .withSetter(Setter<decltype(*mDrcEncTargetLevel)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcBoostFactor, C2_PARAMKEY_DRC_BOOST_FACTOR) - .withDefault(new C2StreamDrcBoostFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_BOOST)) - .withFields({C2F(mDrcBoostFactor, value).inRange(0, 1.)}) - .withSetter(Setter<decltype(*mDrcBoostFactor)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcAttenuationFactor, C2_PARAMKEY_DRC_ATTENUATION_FACTOR) - .withDefault(new C2StreamDrcAttenuationFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_CUT)) - .withFields({C2F(mDrcAttenuationFactor, value).inRange(0, 1.)}) - .withSetter(Setter<decltype(*mDrcAttenuationFactor)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcEffectType, C2_PARAMKEY_DRC_EFFECT_TYPE) - .withDefault(new C2StreamDrcEffectTypeTuning::input(0u, C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE)) - .withFields({ - C2F(mDrcEffectType, value).oneOf({ - C2Config::DRC_EFFECT_ODM_DEFAULT, - C2Config::DRC_EFFECT_OFF, - C2Config::DRC_EFFECT_NONE, - C2Config::DRC_EFFECT_LATE_NIGHT, - C2Config::DRC_EFFECT_NOISY_ENVIRONMENT, - C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE, - C2Config::DRC_EFFECT_LOW_PLAYBACK_LEVEL, - C2Config::DRC_EFFECT_DIALOG_ENHANCEMENT, - C2Config::DRC_EFFECT_GENERAL_COMPRESSION}) - }) - .withSetter(Setter<decltype(*mDrcEffectType)>::StrictValueWithNoDeps) - .build()); - } - - bool isAdts() const { return mAacFormat->value == C2AacStreamFormatAdts; } - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me) { - (void)mayBlock; - (void)me; // TODO: validate - return C2R::Ok(); - } - int32_t getDrcCompressMode() const { return mDrcCompressMode->value == C2Config::DRC_COMPRESSION_HEAVY ? 1 : 0; } - int32_t getDrcTargetRefLevel() const { return (mDrcTargetRefLevel->value <= 0 ? -mDrcTargetRefLevel->value * 4. + 0.5 : -1); } - int32_t getDrcEncTargetLevel() const { return (mDrcEncTargetLevel->value <= 0 ? -mDrcEncTargetLevel->value * 4. + 0.5 : -1); } - int32_t getDrcBoostFactor() const { return mDrcBoostFactor->value * 127. + 0.5; } - int32_t getDrcAttenuationFactor() const { return mDrcAttenuationFactor->value * 127. + 0.5; } - int32_t getDrcEffectType() const { return mDrcEffectType->value; } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; - std::shared_ptr<C2StreamAacFormatInfo::input> mAacFormat; - std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; - std::shared_ptr<C2StreamDrcCompressionModeTuning::input> mDrcCompressMode; - std::shared_ptr<C2StreamDrcTargetReferenceLevelTuning::input> mDrcTargetRefLevel; - std::shared_ptr<C2StreamDrcEncodedTargetLevelTuning::input> mDrcEncTargetLevel; - std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor; - std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor; - std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType; - // TODO Add : C2StreamAacSbrModeTuning -}; - -constexpr char COMPONENT_NAME[] = "c2.android.aac.decoder"; - -C2SoftAacDec::C2SoftAacDec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mAACDecoder(nullptr), - mStreamInfo(nullptr), - mSignalledError(false), - mOutputDelayRingBuffer(nullptr) { -} - -C2SoftAacDec::~C2SoftAacDec() { - onRelease(); -} - -c2_status_t C2SoftAacDec::onInit() { - status_t err = initDecoder(); - return err == OK ? C2_OK : C2_CORRUPTED; -} - -c2_status_t C2SoftAacDec::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 C2SoftAacDec::onReset() { - (void)onStop(); -} - -void C2SoftAacDec::onRelease() { - if (mAACDecoder) { - aacDecoder_Close(mAACDecoder); - mAACDecoder = nullptr; - } - if (mOutputDelayRingBuffer) { - delete[] mOutputDelayRingBuffer; - mOutputDelayRingBuffer = nullptr; - } -} - -status_t C2SoftAacDec::initDecoder() { - ALOGV("initDecoder()"); - status_t status = UNKNOWN_ERROR; - mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1); - if (mAACDecoder != nullptr) { - mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder); - if (mStreamInfo != nullptr) { - status = OK; - } - } - - mOutputDelayCompensated = 0; - mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax; - mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize]; - mOutputDelayRingBufferWritePos = 0; - mOutputDelayRingBufferReadPos = 0; - mOutputDelayRingBufferFilled = 0; - - if (mAACDecoder == nullptr) { - 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) - - // DRC_PRES_MODE_WRAP_DESIRED_TARGET - int32_t targetRefLevel = mIntf->getDrcTargetRefLevel(); - ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel); - mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, (unsigned)targetRefLevel); - - // DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR - - int32_t attenuationFactor = mIntf->getDrcAttenuationFactor(); - ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor); - mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, (unsigned)attenuationFactor); - - // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR - int32_t boostFactor = mIntf->getDrcBoostFactor(); - ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor); - mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, (unsigned)boostFactor); - - // DRC_PRES_MODE_WRAP_DESIRED_HEAVY - int32_t compressMode = mIntf->getDrcCompressMode(); - ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode); - mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode); - - // DRC_PRES_MODE_WRAP_ENCODER_TARGET - int32_t encTargetLevel = mIntf->getDrcEncTargetLevel(); - ALOGV("AAC decoder using encoder-side DRC reference level of %d", encTargetLevel); - mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, (unsigned)encTargetLevel); - - // AAC_UNIDRC_SET_EFFECT - int32_t effectType = mIntf->getDrcEffectType(); - ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType); - aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType); - - // 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 C2SoftAacDec::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 C2SoftAacDec::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 C2SoftAacDec::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 != nullptr) { - for (int32_t i = 0; i < numSamples; i++) { - samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos++]; - } - } else { - mOutputDelayRingBufferReadPos += numSamples; - } - if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) { - mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize; - } - } else { - ALOGV("slow C2SoftAacDec::outputDelayRingBufferGetSamples()"); - - for (int32_t i = 0; i < numSamples; i++) { - if (samples != nullptr) { - samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos]; - } - mOutputDelayRingBufferReadPos++; - if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) { - mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize; - } - } - } - mOutputDelayRingBufferFilled -= numSamples; - return numSamples; -} - -int32_t C2SoftAacDec::outputDelayRingBufferSamplesAvailable() { - return mOutputDelayRingBufferFilled; -} - -int32_t C2SoftAacDec::outputDelayRingBufferSpaceLeft() { - return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable(); -} - -void C2SoftAacDec::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 __unused = 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; - C2FrameData &output = work->worklets.front()->output; - output.flags = work->input.flags; - output.buffers.clear(); - 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); - 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; - C2FrameData &output = work->worklets.front()->output; - output.flags = work->input.flags; - output.buffers.clear(); - output.buffers.push_back(buffer); - 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 C2SoftAacDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - 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 = mDummyReadView; - size_t offset = 0u; - size_t size = 0u; - if (!work->input.buffers.empty()) { - view = work->input.buffers[0]->data().linearBlocks().front().map().get(); - 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 && size > 0u) { - // 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; - work->result = C2_CORRUPTED; - return; - } - work->worklets.front()->output.flags = work->input.flags; - 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 (mIntf->isAdts()) { - 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; - work->result = C2_CORRUPTED; - 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"); - // discard buffer - size = 0; - 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; - work->result = C2_CORRUPTED; - 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; - work->result = C2_CORRUPTED; - 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; - work->result = C2_CORRUPTED; - 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) { - // if ((mInputBufferCount > 2) && (mOutputBufferCount <= 1)) { - ALOGD("Invalid AAC stream"); - // TODO: notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); - // mSignalledError = true; - // } - } else if ((mStreamInfo->sampleRate != prevSampleRate) || - (mStreamInfo->numChannels != prevNumChannels)) { - ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", - prevSampleRate, mStreamInfo->sampleRate, - prevNumChannels, mStreamInfo->numChannels); - - C2StreamSampleRateInfo::output sampleRateInfo(0u, mStreamInfo->sampleRate); - C2StreamChannelCountInfo::output channelCountInfo(0u, mStreamInfo->numChannels); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config( - { &sampleRateInfo, &channelCountInfo }, - C2_MAY_BLOCK, - &failures); - if (err == OK) { - // TODO: this does not handle the case where the values are - // altered during config. - C2FrameData &output = work->worklets.front()->output; - output.configUpdate.push_back(C2Param::Copy(sampleRateInfo)); - output.configUpdate.push_back(C2Param::Copy(channelCountInfo)); - } else { - ALOGE("Config Update failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - ALOGV("size = %zu", size); - } while (decoderErr == AAC_DEC_OK); - } - - int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels; - - mBuffersInfo.push_back(std::move(inInfo)); - work->workletsProcessed = 0u; - 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(nullptr, discard); - mOutputDelayCompensated += discarded; - return; - } - - if (eos) { - drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work); - } else { - drainRingBuffer(work, pool, false /* not EOS */); - } -} - -c2_status_t C2SoftAacDec::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 && work->workletsProcessed == 0u) { - fillEmptyWork(work); - } - mBuffersInfo.clear(); - } - - return C2_OK; -} - -c2_status_t C2SoftAacDec::drain( - uint32_t drainMode, - const std::shared_ptr<C2BlockPool> &pool) { - return drainInternal(drainMode, pool, nullptr); -} - -c2_status_t C2SoftAacDec::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(nullptr, avail); - if (ns != avail) { - ALOGW("not a complete frame of samples available"); - break; - } - } - mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos; - - return C2_OK; -} - -void C2SoftAacDec::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: - C2SoftAacDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftAacDec(COMPONENT_NAME, - id, - std::make_shared<C2SoftAacDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftAacDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftAacDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftAacDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/aac/C2SoftAacDec.h b/media/codecs/aac/C2SoftAacDec.h deleted file mode 100644 index 965c29e..0000000 --- a/media/codecs/aac/C2SoftAacDec.h +++ /dev/null @@ -1,109 +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 ANDROID_C2_SOFT_AAC_DEC_H_ -#define ANDROID_C2_SOFT_AAC_DEC_H_ - -#include <SimpleC2Component.h> - - -#include "aacdecoder_lib.h" -#include "DrcPresModeWrap.h" - -namespace android { - -struct C2SoftAacDec : public SimpleC2Component { - class IntfImpl; - - C2SoftAacDec(const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl); - virtual ~C2SoftAacDec(); - - // 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, - }; - - std::shared_ptr<IntfImpl> mIntf; - - HANDLE_AACDECODER mAACDecoder; - CStreamInfo *mStreamInfo; - 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(); - - C2_DO_NOT_COPY(C2SoftAacDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_AAC_DEC_H_ diff --git a/media/codecs/aac/C2SoftAacEnc.cpp b/media/codecs/aac/C2SoftAacEnc.cpp deleted file mode 100644 index 87730ae..0000000 --- a/media/codecs/aac/C2SoftAacEnc.cpp +++ /dev/null @@ -1,603 +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 { - -class C2SoftAacEnc::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_AAC)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::input(0u, 44100)) - .withFields({C2F(mSampleRate, value).oneOf({ - 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 - })}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::input(0u, 1)) - .withFields({C2F(mChannelCount, value).inRange(1, 6)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::output(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(8000, 960000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .calculatedAs(MaxBufSizeCalculator, mChannelCount) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::output(0u, - C2Config::PROFILE_AAC_LC, C2Config::LEVEL_UNUSED)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_AAC_LC, - C2Config::PROFILE_AAC_HE, - C2Config::PROFILE_AAC_HE_PS, - C2Config::PROFILE_AAC_LD, - C2Config::PROFILE_AAC_ELD}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_UNUSED - }) - }) - .withSetter(ProfileLevelSetter) - .build()); - } - - uint32_t getSampleRate() const { return mSampleRate->value; } - uint32_t getChannelCount() const { return mChannelCount->value; } - uint32_t getBitrate() const { return mBitrate->value; } - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::output> &me) { - (void)mayBlock; - (void)me; // TODO: validate - return C2R::Ok(); - } - - static C2R MaxBufSizeCalculator( - bool mayBlock, - C2P<C2StreamMaxBufferSizeInfo::input> &me, - const C2P<C2StreamChannelCountInfo::input> &channelCount) { - (void)mayBlock; - me.set().value = 1024 * sizeof(short) * channelCount.v.value; - return C2R::Ok(); - } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount; - std::shared_ptr<C2BitrateTuning::output> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; - std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel; -}; - -constexpr char COMPONENT_NAME[] = "c2.android.aac.encoder"; - -C2SoftAacEnc::C2SoftAacEnc( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mAACEncoder(nullptr), - mSBRMode(-1), - mSBRRatio(0), - mAACProfile(AOT_AAC_LC), - mNumBytesPerInputFrame(0u), - mOutBufferSize(0u), - mSentCodecSpecificData(false), - mInputSize(0), - mInputTimeUs(-1ll), - mSignalledError(false), - mOutIndex(0u) { -} - -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", - mIntf->getSampleRate(), mIntf->getChannelCount(), mIntf->getBitrate(), 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, mIntf->getSampleRate())) { - ALOGE("Failed to set AAC encoder parameters"); - return UNKNOWN_ERROR; - } - if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mIntf->getBitrate())) { - ALOGE("Failed to set AAC encoder parameters"); - return UNKNOWN_ERROR; - } - if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE, - getChannelMode(mIntf->getChannelCount()))) { - 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError) { - return; - } - bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; - - uint32_t sampleRate = mIntf->getSampleRate(); - uint32_t channelCount = mIntf->getChannelCount(); - - if (!mSentCodecSpecificData) { - // The very first thing we want to output is the codec specific - // data. - - if (AACENC_OK != aacEncEncode(mAACEncoder, nullptr, nullptr, nullptr, nullptr)) { - ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - uint32_t bitrate = mIntf->getBitrate(); - uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE); - if (bitrate != actualBitRate) { - ALOGW("Requested bitrate %u unsupported, using %u", bitrate, actualBitRate); - } - - AACENC_InfoStruct encInfo; - if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) { - ALOGE("Failed to get AAC encoder info"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - std::unique_ptr<C2StreamCsdInfo::output> csd = - C2StreamCsdInfo::output::AllocUnique(encInfo.confSize, 0u); - if (!csd) { - ALOGE("CSD allocation failed"); - mSignalledError = true; - work->result = C2_NO_MEMORY; - return; - } - 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 * channelCount * sizeof(int16_t); - mInputTimeUs = work->input.ordinal.timestamp; - - mSentCodecSpecificData = true; - } - - uint8_t temp[1]; - C2ReadView view = mDummyReadView; - const uint8_t *data = temp; - size_t capacity = 0u; - if (!work->input.buffers.empty()) { - view = work->input.buffers[0]->data().linearBlocks().front().map().get(); - data = view.data(); - capacity = view.capacity(); - } - - size_t numFrames = (capacity + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0)) - / mNumBytesPerInputFrame; - ALOGV("capacity = %zu; mInputSize = %zu; numFrames = %zu mNumBytesPerInputFrame = %u", - capacity, mInputSize, numFrames, mNumBytesPerInputFrame); - - std::shared_ptr<C2LinearBlock> block; - std::shared_ptr<C2Buffer> buffer; - std::unique_ptr<C2WriteView> wView; - uint8_t *outPtr = temp; - size_t outAvailable = 0u; - uint64_t inputIndex = work->input.ordinal.frameIndex.peeku(); - - AACENC_InArgs inargs; - AACENC_OutArgs outargs; - memset(&inargs, 0, sizeof(inargs)); - memset(&outargs, 0, sizeof(outargs)); - inargs.numInSamples = capacity / sizeof(int16_t); - - void* inBuffer[] = { (unsigned char *)data }; - INT inBufferIds[] = { IN_AUDIO_DATA }; - INT inBufferSize[] = { (INT)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; - - AACENC_ERROR encoderErr = AACENC_OK; - - class FillWork { - public: - FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal, - const std::shared_ptr<C2Buffer> &buffer) - : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) { - } - ~FillWork() = default; - - void operator()(const std::unique_ptr<C2Work> &work) { - work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags; - work->worklets.front()->output.buffers.clear(); - work->worklets.front()->output.ordinal = mOrdinal; - work->workletsProcessed = 1u; - work->result = C2_OK; - if (mBuffer) { - work->worklets.front()->output.buffers.push_back(mBuffer); - } - ALOGV("timestamp = %lld, index = %lld, w/%s buffer", - mOrdinal.timestamp.peekll(), - mOrdinal.frameIndex.peekll(), - mBuffer ? "" : "o"); - } - - private: - const uint32_t mFlags; - const C2WorkOrdinalStruct mOrdinal; - const std::shared_ptr<C2Buffer> mBuffer; - }; - - C2WorkOrdinalStruct outOrdinal = work->input.ordinal; - - while (encoderErr == AACENC_OK && inargs.numInSamples > 0) { - if (numFrames && !block) { - 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("fetchLinearBlock failed : err = %d", err); - work->result = C2_NO_MEMORY; - return; - } - - wView.reset(new C2WriteView(block->map().get())); - outPtr = wView->data(); - outAvailable = wView->size(); - --numFrames; - } - - memset(&outargs, 0, sizeof(outargs)); - - outBuffer[0] = outPtr; - outBufferSize[0] = outAvailable; - - encoderErr = aacEncEncode(mAACEncoder, - &inBufDesc, - &outBufDesc, - &inargs, - &outargs); - - if (encoderErr == AACENC_OK) { - if (buffer) { - outOrdinal.frameIndex = mOutIndex++; - outOrdinal.timestamp = mInputTimeUs; - cloneAndSend( - inputIndex, - work, - FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer)); - buffer.reset(); - } - - if (outargs.numOutBytes > 0) { - mInputSize = 0; - int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples - + outargs.numInSamples; - mInputTimeUs = work->input.ordinal.timestamp - + (consumed * 1000000ll / channelCount / sampleRate); - buffer = createLinearBuffer(block, 0, outargs.numOutBytes); -#if defined(LOG_NDEBUG) && !LOG_NDEBUG - hexdump(outPtr, std::min(outargs.numOutBytes, 256)); -#endif - outPtr = temp; - outAvailable = 0; - block.reset(); - } else { - mInputSize += outargs.numInSamples * sizeof(int16_t); - } - - if (outargs.numInSamples > 0) { - inBuffer[0] = (int16_t *)inBuffer[0] + outargs.numInSamples; - inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t); - inargs.numInSamples -= outargs.numInSamples; - } - } - ALOGV("encoderErr = %d mInputSize = %zu inargs.numInSamples = %d, mInputTimeUs = %lld", - encoderErr, mInputSize, inargs.numInSamples, mInputTimeUs.peekll()); - } - - if (eos && inBufferSize[0] > 0) { - if (numFrames && !block) { - 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("fetchLinearBlock failed : err = %d", err); - work->result = C2_NO_MEMORY; - return; - } - - wView.reset(new C2WriteView(block->map().get())); - outPtr = wView->data(); - outAvailable = wView->size(); - --numFrames; - } - - memset(&outargs, 0, sizeof(outargs)); - - outBuffer[0] = outPtr; - outBufferSize[0] = outAvailable; - - // Flush - inargs.numInSamples = -1; - - (void)aacEncEncode(mAACEncoder, - &inBufDesc, - &outBufDesc, - &inargs, - &outargs); - } - - outOrdinal.frameIndex = mOutIndex++; - outOrdinal.timestamp = mInputTimeUs; - FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0), - outOrdinal, buffer)(work); -} - -c2_status_t C2SoftAacEnc::drain( - uint32_t drainMode, - const std::shared_ptr<C2BlockPool> &pool) { - switch (drainMode) { - case DRAIN_COMPONENT_NO_EOS: - [[fallthrough]]; - 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: - C2SoftAacEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftAacEnc::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftAacEncFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/aac/C2SoftAacEnc.h b/media/codecs/aac/C2SoftAacEnc.h deleted file mode 100644 index 82fb438..0000000 --- a/media/codecs/aac/C2SoftAacEnc.h +++ /dev/null @@ -1,75 +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 ANDROID_C2_SOFT_AAC_ENC_H_ -#define ANDROID_C2_SOFT_AAC_ENC_H_ - -#include <atomic> - -#include <SimpleC2Component.h> - -#include "aacenc_lib.h" - -namespace android { - -class C2SoftAacEnc : public SimpleC2Component { -public: - class IntfImpl; - - C2SoftAacEnc(const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl); - 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: - std::shared_ptr<IntfImpl> mIntf; - - HANDLE_AACENCODER mAACEncoder; - - 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; - std::atomic_uint64_t mOutIndex; - - status_t initEncoder(); - - status_t setAudioParams(); - - C2_DO_NOT_COPY(C2SoftAacEnc); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_AAC_ENC_H_ diff --git a/media/codecs/aac/DrcPresModeWrap.cpp b/media/codecs/aac/DrcPresModeWrap.cpp deleted file mode 100644 index 5b9aebc..0000000 --- a/media/codecs/aac/DrcPresModeWrap.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (C) 2014 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 "DrcPresModeWrap.h" - -#include <assert.h> - -#define LOG_TAG "C2SoftAacDrcWrapper" -//#define LOG_NDEBUG 0 -#include <utils/Log.h> - -//#define DRC_PRES_MODE_WRAP_DEBUG - -#define GPM_ENCODER_TARGET_LEVEL 64 -#define MAX_TARGET_LEVEL 40 - -CDrcPresModeWrapper::CDrcPresModeWrapper() -{ - mDataUpdate = true; - - /* Data from streamInfo. */ - /* Initialized to the same values as in the aac decoder */ - mStreamPRL = -1; - mStreamDRCPresMode = -1; - mStreamNrAACChan = 0; - mStreamNrOutChan = 0; - - /* Desired values (set by user). */ - /* Initialized to the same values as in the aac decoder */ - mDesTarget = -1; - mDesAttFactor = 0; - mDesBoostFactor = 0; - mDesHeavy = 0; - - mEncoderTarget = -1; - - /* Values from last time. */ - /* Initialized to the same values as the desired values */ - mLastTarget = -1; - mLastAttFactor = 0; - mLastBoostFactor = 0; - mLastHeavy = 0; -} - -CDrcPresModeWrapper::~CDrcPresModeWrapper() -{ -} - -void -CDrcPresModeWrapper::setDecoderHandle(const HANDLE_AACDECODER handle) -{ - mHandleDecoder = handle; -} - -void -CDrcPresModeWrapper::submitStreamData(CStreamInfo* pStreamInfo) -{ - assert(pStreamInfo); - - if (mStreamPRL != pStreamInfo->drcProgRefLev) { - mStreamPRL = pStreamInfo->drcProgRefLev; - mDataUpdate = true; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - ALOGV("DRC presentation mode wrapper: drcProgRefLev is %d\n", mStreamPRL); -#endif - } - - if (mStreamDRCPresMode != pStreamInfo->drcPresMode) { - mStreamDRCPresMode = pStreamInfo->drcPresMode; - mDataUpdate = true; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - ALOGV("DRC presentation mode wrapper: drcPresMode is %d\n", mStreamDRCPresMode); -#endif - } - - if (mStreamNrAACChan != pStreamInfo->aacNumChannels) { - mStreamNrAACChan = pStreamInfo->aacNumChannels; - mDataUpdate = true; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - ALOGV("DRC presentation mode wrapper: aacNumChannels is %d\n", mStreamNrAACChan); -#endif - } - - if (mStreamNrOutChan != pStreamInfo->numChannels) { - mStreamNrOutChan = pStreamInfo->numChannels; - mDataUpdate = true; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - ALOGV("DRC presentation mode wrapper: numChannels is %d\n", mStreamNrOutChan); -#endif - } - - - - if (mStreamNrOutChan<mStreamNrAACChan) { - mIsDownmix = true; - } else { - mIsDownmix = false; - } - - if (mIsDownmix && (mStreamNrOutChan == 1)) { - mIsMonoDownmix = true; - } else { - mIsMonoDownmix = false; - } - - if (mIsDownmix && mStreamNrOutChan == 2){ - mIsStereoDownmix = true; - } else { - mIsStereoDownmix = false; - } - -} - -void -CDrcPresModeWrapper::setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value) -{ - switch (param) { - case DRC_PRES_MODE_WRAP_DESIRED_TARGET: - mDesTarget = value; - break; - case DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR: - mDesAttFactor = value; - break; - case DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR: - mDesBoostFactor = value; - break; - case DRC_PRES_MODE_WRAP_DESIRED_HEAVY: - mDesHeavy = value; - break; - case DRC_PRES_MODE_WRAP_ENCODER_TARGET: - mEncoderTarget = value; - break; - default: - break; - } - mDataUpdate = true; -} - -void -CDrcPresModeWrapper::update() -{ - // Get Data from Decoder - int progRefLevel = mStreamPRL; - int drcPresMode = mStreamDRCPresMode; - - // by default, do as desired - int newTarget = mDesTarget; - int newAttFactor = mDesAttFactor; - int newBoostFactor = mDesBoostFactor; - int newHeavy = mDesHeavy; - - if (mDataUpdate) { - // sanity check - if (mDesTarget < MAX_TARGET_LEVEL){ - mDesTarget = MAX_TARGET_LEVEL; // limit target level to -10 dB or below - newTarget = MAX_TARGET_LEVEL; - } - - if (mEncoderTarget != -1) { - if (mDesTarget<124) { // if target level > -31 dB - if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) { - // no stereo or mono downmixing, calculated scaling of light DRC - /* use as little compression as possible */ - newAttFactor = 0; - newBoostFactor = 0; - if (mDesTarget<progRefLevel) { // if target level > PRL - if (mEncoderTarget < mDesTarget) { // if mEncoderTarget > target level - // mEncoderTarget > target level > PRL - int calcFactor; - float calcFactor_norm; - // 0.0f < calcFactor_norm < 1.0f - calcFactor_norm = (float)(mDesTarget - progRefLevel) / - (float)(mEncoderTarget - progRefLevel); - calcFactor = (int)(calcFactor_norm*127.0f); // 0 <= calcFactor < 127 - // calcFactor is the lower limit - newAttFactor = (calcFactor>newAttFactor) ? calcFactor : newAttFactor; - // new AttFactor will be always = calcFactor, as it is set to 0 before. - newBoostFactor = newAttFactor; - } else { - /* target level > mEncoderTarget > PRL */ - // newTDLimiterEnable = 1; - // the time domain limiter must always be active in this case. - // It is assumed that the framework activates it by default - newAttFactor = 127; - newBoostFactor = 127; - } - } else { // target level <= PRL - // no restrictions required - // newAttFactor = newAttFactor; - } - } else { // downmixing - // if target level > -23 dB or mono downmix - if ( (mDesTarget<92) || mIsMonoDownmix ) { - newHeavy = 1; - } else { - // we perform a downmix, so, we need at least full light DRC - newAttFactor = 127; - } - } - } else { // target level <= -31 dB - // playback -31 dB: light DRC only needed if we perform downmixing - if (mIsDownmix) { // we do downmixing - newAttFactor = 127; - } - } - } - else { // handle other used encoder target levels - - // Sanity check: DRC presentation mode is only specified for max. 5.1 channels - if (mStreamNrAACChan > 6) { - drcPresMode = 0; - } - - switch (drcPresMode) { - case 0: - default: // presentation mode not indicated - { - - if (mDesTarget<124) { // if target level > -31 dB - // no stereo or mono downmixing - if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) { - if (mDesTarget<progRefLevel) { // if target level > PRL - // newTDLimiterEnable = 1; - // the time domain limiter must always be active in this case. - // It is assumed that the framework activates it by default - newAttFactor = 127; // at least, use light compression - } else { // target level <= PRL - // no restrictions required - // newAttFactor = newAttFactor; - } - } else { // downmixing - // newTDLimiterEnable = 1; - // the time domain limiter must always be active in this case. - // It is assumed that the framework activates it by default - - // if target level > -23 dB or mono downmix - if ( (mDesTarget < 92) || mIsMonoDownmix ) { - newHeavy = 1; - } else{ - // we perform a downmix, so, we need at least full light DRC - newAttFactor = 127; - } - } - } else { // target level <= -31 dB - if (mIsDownmix) { // we do downmixing. - // newTDLimiterEnable = 1; - // the time domain limiter must always be active in this case. - // It is assumed that the framework activates it by default - newAttFactor = 127; - } - } - } - break; - - // Presentation mode 1 and 2 according to ETSI TS 101 154: - // Digital Video Broadcasting (DVB); Specification for the use of Video and Audio Coding - // in Broadcasting Applications based on the MPEG-2 Transport Stream, - // section C.5.4., "Decoding", and Table C.33 - // ISO DRC -> newHeavy = 0 (Use light compression, MPEG-style) - // Compression_value -> newHeavy = 1 (Use heavy compression, DVB-style) - // scaling restricted -> newAttFactor = 127 - - case 1: // presentation mode 1, Light:-31/Heavy:-23 - { - if (mDesTarget < 124) { // if target level > -31 dB - // playback up to -23 dB - newHeavy = 1; - } else { // target level <= -31 dB - // playback -31 dB - if (mIsDownmix) { // we do downmixing. - newAttFactor = 127; - } - } - } - break; - - case 2: // presentation mode 2, Light:-23/Heavy:-23 - { - if (mDesTarget < 124) { // if target level > -31 dB - // playback up to -23 dB - if (mIsMonoDownmix) { // if mono downmix - newHeavy = 1; - } else { - newHeavy = 0; - newAttFactor = 127; - } - } else { // target level <= -31 dB - // playback -31 dB - newHeavy = 0; - if (mIsDownmix) { // we do downmixing. - newAttFactor = 127; - } - } - } - break; - - } // switch() - } // if (mEncoderTarget == GPM_ENCODER_TARGET_LEVEL) - - // sanity again - if (newHeavy == 1) { - newBoostFactor=127; // not really needed as the same would be done by the decoder anyway - newAttFactor = 127; - } - - // update the decoder - if (newTarget != mLastTarget) { - aacDecoder_SetParam(mHandleDecoder, AAC_DRC_REFERENCE_LEVEL, newTarget); - mLastTarget = newTarget; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - if (newTarget != mDesTarget) - ALOGV("DRC presentation mode wrapper: forced target level to %d (from %d)\n", newTarget, mDesTarget); - else - ALOGV("DRC presentation mode wrapper: set target level to %d\n", newTarget); -#endif - } - - if (newAttFactor != mLastAttFactor) { - aacDecoder_SetParam(mHandleDecoder, AAC_DRC_ATTENUATION_FACTOR, newAttFactor); - mLastAttFactor = newAttFactor; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - if (newAttFactor != mDesAttFactor) - ALOGV("DRC presentation mode wrapper: forced attenuation factor to %d (from %d)\n", newAttFactor, mDesAttFactor); - else - ALOGV("DRC presentation mode wrapper: set attenuation factor to %d\n", newAttFactor); -#endif - } - - if (newBoostFactor != mLastBoostFactor) { - aacDecoder_SetParam(mHandleDecoder, AAC_DRC_BOOST_FACTOR, newBoostFactor); - mLastBoostFactor = newBoostFactor; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - if (newBoostFactor != mDesBoostFactor) - ALOGV("DRC presentation mode wrapper: forced boost factor to %d (from %d)\n", - newBoostFactor, mDesBoostFactor); - else - ALOGV("DRC presentation mode wrapper: set boost factor to %d\n", newBoostFactor); -#endif - } - - if (newHeavy != mLastHeavy) { - aacDecoder_SetParam(mHandleDecoder, AAC_DRC_HEAVY_COMPRESSION, newHeavy); - mLastHeavy = newHeavy; -#ifdef DRC_PRES_MODE_WRAP_DEBUG - if (newHeavy != mDesHeavy) - ALOGV("DRC presentation mode wrapper: forced heavy compression to %d (from %d)\n", - newHeavy, mDesHeavy); - else - ALOGV("DRC presentation mode wrapper: set heavy compression to %d\n", newHeavy); -#endif - } - -#ifdef DRC_PRES_MODE_WRAP_DEBUG - ALOGV("DRC config: tgt_lev: %3d, cut: %3d, boost: %3d, heavy: %d\n", newTarget, - newAttFactor, newBoostFactor, newHeavy); -#endif - mDataUpdate = false; - - } // if (mDataUpdate) -} diff --git a/media/codecs/aac/DrcPresModeWrap.h b/media/codecs/aac/DrcPresModeWrap.h deleted file mode 100644 index f0b6cf2..0000000 --- a/media/codecs/aac/DrcPresModeWrap.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2014 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. - */ -#pragma once -#include "aacdecoder_lib.h" - -typedef enum -{ - DRC_PRES_MODE_WRAP_DESIRED_TARGET = 0x0000, - DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR = 0x0001, - DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR = 0x0002, - DRC_PRES_MODE_WRAP_DESIRED_HEAVY = 0x0003, - DRC_PRES_MODE_WRAP_ENCODER_TARGET = 0x0004 -} DRC_PRES_MODE_WRAP_PARAM; - - -class CDrcPresModeWrapper { -public: - CDrcPresModeWrapper(); - ~CDrcPresModeWrapper(); - void setDecoderHandle(const HANDLE_AACDECODER handle); - void setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value); - void submitStreamData(CStreamInfo*); - void update(); - -protected: - HANDLE_AACDECODER mHandleDecoder; - int mDesTarget; - int mDesAttFactor; - int mDesBoostFactor; - int mDesHeavy; - - int mEncoderTarget; - - int mLastTarget; - int mLastAttFactor; - int mLastBoostFactor; - int mLastHeavy; - - SCHAR mStreamPRL; - SCHAR mStreamDRCPresMode; - INT mStreamNrAACChan; - INT mStreamNrOutChan; - - bool mIsDownmix; - bool mIsMonoDownmix; - bool mIsStereoDownmix; - - bool mDataUpdate; -}; diff --git a/media/codecs/aac/MODULE_LICENSE_APACHE2 b/media/codecs/aac/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/aac/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/aac/NOTICE b/media/codecs/aac/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/aac/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/aac/patent_disclaimer.txt b/media/codecs/aac/patent_disclaimer.txt deleted file mode 100644 index b4bf11d..0000000 --- a/media/codecs/aac/patent_disclaimer.txt +++ /dev/null @@ -1,9 +0,0 @@ - -THIS IS NOT A GRANT OF PATENT RIGHTS. - -Google makes no representation or warranty that the codecs for which -source code is made available hereunder are unencumbered by -third-party patents. Those intending to use this source code in -hardware or software products are advised that implementations of -these codecs, including in open source software or shareware, may -require patent licenses from the relevant patent holders. diff --git a/media/codecs/amr_nb_wb/Android.bp b/media/codecs/amr_nb_wb/Android.bp deleted file mode 100644 index 764b3db..0000000 --- a/media/codecs/amr_nb_wb/Android.bp +++ /dev/null @@ -1,77 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2amrnbdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftAmrDec.cpp"], - - cflags: [ - "-DAMRNB", - ], - - static_libs: [ - "libstagefright_amrnbdec", - "libstagefright_amrwbdec", - ], - - shared_libs: [ - "libstagefright_amrnb_common", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2amrwbdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftAmrDec.cpp"], - - static_libs: [ - "libstagefright_amrnbdec", - "libstagefright_amrwbdec", - ], - - shared_libs: [ - "libstagefright_amrnb_common", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2amrnbenc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftAmrNbEnc.cpp"], - - static_libs: [ - "libstagefright_amrnbenc", - ], - - shared_libs: [ - "libstagefright_amrnb_common", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2amrwbenc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftAmrWbEnc.cpp"], - - static_libs: [ - "libstagefright_amrwbenc", - ], - - shared_libs: [ - "libstagefright_enc_common", - ], -} diff --git a/media/codecs/amr_nb_wb/C2SoftAmrDec.cpp b/media/codecs/amr_nb_wb/C2SoftAmrDec.cpp deleted file mode 100644 index c591e21..0000000 --- a/media/codecs/amr_nb_wb/C2SoftAmrDec.cpp +++ /dev/null @@ -1,438 +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 -#ifdef AMRNB -#define LOG_TAG "C2SoftAmrNbDec" -#else -#define LOG_TAG "C2SoftAmrWbDec" -#endif -#include <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftAmrDec.h" -#include "gsmamr_dec.h" -#include "pvamrwbdecoder.h" - -namespace android { - -#ifdef AMRNB - constexpr char COMPONENT_NAME[] = "c2.android.amrnb.decoder"; -#else - constexpr char COMPONENT_NAME[] = "c2.android.amrwb.decoder"; -#endif - -class C2SoftAmrDec::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( -#ifdef AMRNB - MEDIA_MIMETYPE_AUDIO_AMR_NB -#else - MEDIA_MIMETYPE_AUDIO_AMR_WB -#endif - )).build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) -#ifdef AMRNB - .withDefault(new C2StreamSampleRateInfo::output(0u, 8000)) - .withFields({C2F(mSampleRate, value).equalTo(8000)}) -#else - .withDefault(new C2StreamSampleRateInfo::output(0u, 16000)) - .withFields({C2F(mSampleRate, value).equalTo(16000)}) -#endif - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).equalTo(1)}) - .withSetter((Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) -#ifdef AMRNB - .withDefault(new C2BitrateTuning::input(0u, 4750)) - .withFields({C2F(mBitrate, value).inRange(4750, 12200)}) -#else - .withDefault(new C2BitrateTuning::input(0u, 6600)) - .withFields({C2F(mBitrate, value).inRange(6600, 23850)}) -#endif - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .build()); - } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftAmrDec::C2SoftAmrDec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mAmrHandle(nullptr), - mDecoderBuf(nullptr), - mDecoderCookie(nullptr) { -#ifdef AMRNB - mIsWide = false; -#else - mIsWide = true; -#endif -} - -C2SoftAmrDec::~C2SoftAmrDec() { - (void)onRelease(); -} - -c2_status_t C2SoftAmrDec::onInit() { - status_t err = initDecoder(); - return err == OK ? C2_OK : C2_NO_MEMORY; -} - -c2_status_t C2SoftAmrDec::onStop() { - if (!mIsWide) { - Speech_Decode_Frame_reset(mAmrHandle); - } else { - pvDecoder_AmrWb_Reset(mAmrHandle, 0 /* reset_all */); - } - mSignalledError = false; - mSignalledOutputEos = false; - - return C2_OK; -} - -void C2SoftAmrDec::onReset() { - (void)onStop(); -} - -void C2SoftAmrDec::onRelease() { - if (!mIsWide) { - if (mAmrHandle) { - GSMDecodeFrameExit(&mAmrHandle); - } - mAmrHandle = nullptr; - } else { - if (mDecoderBuf) { - free(mDecoderBuf); - } - mDecoderBuf = nullptr; - mAmrHandle = nullptr; - mDecoderCookie = nullptr; - } -} - -c2_status_t C2SoftAmrDec::onFlush_sm() { - return onStop(); -} - -status_t C2SoftAmrDec::initDecoder() { - 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 C2SoftAmrDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - C2ReadView rView = mDummyReadView; - size_t inOffset = 0u; - size_t inSize = 0u; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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; - 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; - 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; - if (eos) { - mSignalledOutputEos = true; - ALOGV("signalled EOS"); - } -} - -c2_status_t C2SoftAmrDec::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: - C2SoftAMRDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftAmrDec(COMPONENT_NAME, id, - std::make_shared<C2SoftAmrDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftAmrDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftAmrDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftAMRDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/amr_nb_wb/C2SoftAmrDec.h b/media/codecs/amr_nb_wb/C2SoftAmrDec.h deleted file mode 100644 index 6384450..0000000 --- a/media/codecs/amr_nb_wb/C2SoftAmrDec.h +++ /dev/null @@ -1,68 +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 ANDROID_C2_SOFT_AMR_DEC_H_ -#define ANDROID_C2_SOFT_AMR_DEC_H_ - -#include <SimpleC2Component.h> - - -namespace android { - -struct C2SoftAmrDec : public SimpleC2Component { - class IntfImpl; - - C2SoftAmrDec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl); - virtual ~C2SoftAmrDec(); - - // 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 { - kNumSamplesPerFrameNB = 160, - kNumSamplesPerFrameWB = 320, - }; - - std::shared_ptr<IntfImpl> mIntf; - void *mAmrHandle; - void *mDecoderBuf; - int16_t *mDecoderCookie; - - int16_t mInputSampleBuffer[477]; - - bool mIsWide; - bool mSignalledError; - bool mSignalledOutputEos; - - status_t initDecoder(); - - C2_DO_NOT_COPY(C2SoftAmrDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_AMR_DEC_H_ diff --git a/media/codecs/amr_nb_wb/C2SoftAmrNbEnc.cpp b/media/codecs/amr_nb_wb/C2SoftAmrNbEnc.cpp deleted file mode 100644 index ca21480..0000000 --- a/media/codecs/amr_nb_wb/C2SoftAmrNbEnc.cpp +++ /dev/null @@ -1,355 +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 <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftAmrNbEnc.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.amrnb.encoder"; - -class C2SoftAmrNbEnc::IntfImpl : public C2InterfaceHelper { - public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper) - : C2InterfaceHelper(helper) { - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::input(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::output(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_AMR_NB)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::input(0u, 1)) - .withFields({C2F(mChannelCount, value).equalTo(1)}) - .withSetter((Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::input(0u, 8000)) - .withFields({C2F(mSampleRate, value).equalTo(8000)}) - .withSetter( - (Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::output(0u, 4750)) - .withFields({C2F(mBitrate, value).inRange(4750, 12200)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .build()); - } - - uint32_t getSampleRate() const { return mSampleRate->value; } - uint32_t getChannelCount() const { return mChannelCount->value; } - uint32_t getBitrate() const { return mBitrate->value; } - - private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount; - std::shared_ptr<C2BitrateTuning::output> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftAmrNbEnc::C2SoftAmrNbEnc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : SimpleC2Component( - std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - 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; - // TODO: get mode directly from config - switch(mIntf->getBitrate()) { - case 4750: mMode = MR475; - break; - case 5150: mMode = MR515; - break; - case 5900: mMode = MR59; - break; - case 6700: mMode = MR67; - break; - case 7400: mMode = MR74; - break; - case 7950: mMode = MR795; - break; - case 10200: mMode = MR102; - break; - case 12200: mMode = MR122; - break; - default: 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - size_t inOffset = 0u; - size_t inSize = 0u; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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 / mIntf->getSampleRate(); - size_t inPos = 0; - size_t outPos = 0; - while (inPos < inSize) { - const uint8_t *inPtr = rView.data() + inOffset; - 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: - C2SoftAmrNbEncFactory() - : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) {} - - 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( - COMPONENT_NAME, id, - std::make_shared<C2SoftAmrNbEnc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftAmrNbEnc::IntfImpl>( - COMPONENT_NAME, id, - std::make_shared<C2SoftAmrNbEnc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftAmrNbEncFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/amr_nb_wb/C2SoftAmrNbEnc.h b/media/codecs/amr_nb_wb/C2SoftAmrNbEnc.h deleted file mode 100644 index 6ab14db..0000000 --- a/media/codecs/amr_nb_wb/C2SoftAmrNbEnc.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 ANDROID_C2_SOFT_AMR_NB_ENC_H_ -#define ANDROID_C2_SOFT_AMR_NB_ENC_H_ - -#include <SimpleC2Component.h> - -#include "gsmamr_enc.h" - -namespace android { - -class C2SoftAmrNbEnc : public SimpleC2Component { - public: - class IntfImpl; - C2SoftAmrNbEnc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - 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: - std::shared_ptr<IntfImpl> mIntf; - static const int32_t kNumSamplesPerFrame = L_FRAME; - static const int32_t kNumBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t); - - 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]; - - C2_DO_NOT_COPY(C2SoftAmrNbEnc); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_AMR_NB_ENC_H_ diff --git a/media/codecs/amr_nb_wb/C2SoftAmrWbEnc.cpp b/media/codecs/amr_nb_wb/C2SoftAmrWbEnc.cpp deleted file mode 100644 index be3892f..0000000 --- a/media/codecs/amr_nb_wb/C2SoftAmrWbEnc.cpp +++ /dev/null @@ -1,430 +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 <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftAmrWbEnc.h" -#include "cmnMemory.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.amrwb.encoder"; - -class C2SoftAmrWbEnc::IntfImpl : public C2InterfaceHelper { - public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper) - : C2InterfaceHelper(helper) { - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::input(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::output(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_AMR_WB)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::input(0u, 1)) - .withFields({C2F(mChannelCount, value).equalTo(1)}) - .withSetter((Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::input(0u, 16000)) - .withFields({C2F(mSampleRate, value).equalTo(16000)}) - .withSetter( - (Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::output(0u, 6600)) - .withFields({C2F(mBitrate, value).inRange(6600, 23850)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .build()); - } - - uint32_t getSampleRate() const { return mSampleRate->value; } - uint32_t getChannelCount() const { return mChannelCount->value; } - uint32_t getBitrate() const { return mBitrate->value; } - - private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount; - std::shared_ptr<C2BitrateTuning::output> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftAmrWbEnc::C2SoftAmrWbEnc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : SimpleC2Component( - std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mEncoderHandle(nullptr), - mApiHandle(nullptr), - mMemOperator(nullptr) { -} - -C2SoftAmrWbEnc::~C2SoftAmrWbEnc() { - onRelease(); -} - -c2_status_t C2SoftAmrWbEnc::onInit() { - // TODO: get mode directly from config - switch(mIntf->getBitrate()) { - case 6600: mMode = VOAMRWB_MD66; - break; - case 8850: mMode = VOAMRWB_MD885; - break; - case 12650: mMode = VOAMRWB_MD1265; - break; - case 14250: mMode = VOAMRWB_MD1425; - break; - case 15850: mMode = VOAMRWB_MD1585; - break; - case 18250: mMode = VOAMRWB_MD1825; - break; - case 19850: mMode = VOAMRWB_MD1985; - break; - case 23050: mMode = VOAMRWB_MD2305; - break; - case 23850: mMode = VOAMRWB_MD2385; - break; - default: mMode = VOAMRWB_MD2305; - } - status_t err = initEncoder(); - 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - size_t inOffset = 0u; - size_t inSize = 0u; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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; - - 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 / mIntf->getSampleRate(); - size_t inPos = 0; - size_t outPos = 0; - while (inPos < inSize) { - const uint8_t *inPtr = rView.data() + inOffset; - 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: - C2SoftAmrWbEncFactory() - : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) {} - - 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( - COMPONENT_NAME, id, - std::make_shared<C2SoftAmrWbEnc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftAmrWbEnc::IntfImpl>( - COMPONENT_NAME, id, - std::make_shared<C2SoftAmrWbEnc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftAmrWbEncFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/amr_nb_wb/C2SoftAmrWbEnc.h b/media/codecs/amr_nb_wb/C2SoftAmrWbEnc.h deleted file mode 100644 index 0cc9e9f..0000000 --- a/media/codecs/amr_nb_wb/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 ANDROID_C2_SOFT_AMR_WB_ENC_H_ -#define ANDROID_C2_SOFT_AMR_WB_ENC_H_ - -#include <SimpleC2Component.h> - -#include "voAMRWB.h" - -namespace android { - -class C2SoftAmrWbEnc : public SimpleC2Component { -public: - class IntfImpl; - C2SoftAmrWbEnc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - 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: - std::shared_ptr<IntfImpl> mIntf; - static const int32_t kNumSamplesPerFrame = 320; - static const int32_t kNumBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t); - - 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); - - C2_DO_NOT_COPY(C2SoftAmrWbEnc); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_AMR_WB_ENC_H_ diff --git a/media/codecs/amr_nb_wb/MODULE_LICENSE_APACHE2 b/media/codecs/amr_nb_wb/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/amr_nb_wb/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/amr_nb_wb/NOTICE b/media/codecs/amr_nb_wb/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/amr_nb_wb/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/amr_nb_wb/patent_disclaimer.txt b/media/codecs/amr_nb_wb/patent_disclaimer.txt deleted file mode 100644 index b4bf11d..0000000 --- a/media/codecs/amr_nb_wb/patent_disclaimer.txt +++ /dev/null @@ -1,9 +0,0 @@ - -THIS IS NOT A GRANT OF PATENT RIGHTS. - -Google makes no representation or warranty that the codecs for which -source code is made available hereunder are unencumbered by -third-party patents. Those intending to use this source code in -hardware or software products are advised that implementations of -these codecs, including in open source software or shareware, may -require patent licenses from the relevant patent holders. diff --git a/media/codecs/avc/Android.bp b/media/codecs/avc/Android.bp deleted file mode 100644 index d883951..0000000 --- a/media/codecs/avc/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2avcdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - static_libs: ["libavcdec"], - - srcs: ["C2SoftAvcDec.cpp"], - - include_dirs: [ - "external/libavc/decoder", - "external/libavc/common", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2avcenc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - static_libs: ["libavcenc"], - - srcs: ["C2SoftAvcEnc.cpp"], - - include_dirs: [ - "external/libavc/encoder", - "external/libavc/common", - ], - - cflags: [ - "-Wno-unused-variable", - ], -} diff --git a/media/codecs/avc/C2SoftAvcDec.cpp b/media/codecs/avc/C2SoftAvcDec.cpp deleted file mode 100644 index 3e62744..0000000 --- a/media/codecs/avc/C2SoftAvcDec.cpp +++ /dev/null @@ -1,978 +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 <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <Codec2Mapper.h> -#include <SimpleC2Interface.h> - -#include "C2SoftAvcDec.h" -#include "ih264d.h" - -namespace android { - -namespace { - -constexpr char COMPONENT_NAME[] = "c2.android.avc.decoder"; - -} // namespace - -class C2SoftAvcDec::IntfImpl : public SimpleInterface<void>::BaseParams { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : SimpleInterface<void>::BaseParams( - helper, - COMPONENT_NAME, - C2Component::KIND_DECODER, - C2Component::DOMAIN_VIDEO, - MEDIA_MIMETYPE_VIDEO_AVC) { - noPrivateBuffers(); // TODO: account for our buffers here - noInputReferences(); - noOutputReferences(); - noInputLatency(); - noTimeStretch(); - - // TODO: output latency and reordering - - addParameter( - DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES) - .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL)) - .build()); - - // coded and output picture size is the same for this codec - addParameter( - DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE) - .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 4080, 2), - C2F(mSize, height).inRange(2, 4080, 2), - }) - .withSetter(SizeSetter) - .build()); - - addParameter( - DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE) - .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 4080, 2), - C2F(mSize, height).inRange(2, 4080, 2), - }) - .withSetter(MaxPictureSizeSetter, mSize) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_AVC_CONSTRAINED_BASELINE, C2Config::LEVEL_AVC_5_2)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_AVC_CONSTRAINED_BASELINE, - C2Config::PROFILE_AVC_BASELINE, - C2Config::PROFILE_AVC_MAIN, - C2Config::PROFILE_AVC_CONSTRAINED_HIGH, - C2Config::PROFILE_AVC_PROGRESSIVE_HIGH, - C2Config::PROFILE_AVC_HIGH}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_AVC_1, C2Config::LEVEL_AVC_1B, C2Config::LEVEL_AVC_1_1, - C2Config::LEVEL_AVC_1_2, C2Config::LEVEL_AVC_1_3, - C2Config::LEVEL_AVC_2, C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2, - C2Config::LEVEL_AVC_3, C2Config::LEVEL_AVC_3_1, C2Config::LEVEL_AVC_3_2, - C2Config::LEVEL_AVC_4, C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2, - C2Config::LEVEL_AVC_5, C2Config::LEVEL_AVC_5_1, C2Config::LEVEL_AVC_5_2 - }) - }) - .withSetter(ProfileLevelSetter, mSize) - .build()); - - addParameter( - DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4)) - .withFields({ - C2F(mMaxInputSize, value).any(), - }) - .calculatedAs(MaxInputSizeSetter, mMaxSize) - .build()); - - C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() }; - std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - 1u, 0u, 8u /* bitDepth */, C2Color::YUV_420); - memcpy(defaultColorInfo->m.locations, locations, sizeof(locations)); - - defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - { C2ChromaOffsetStruct::ITU_YUV_420_0() }, - 0u, 8u /* bitDepth */, C2Color::YUV_420); - helper->addStructDescriptors<C2ChromaOffsetStruct>(); - - addParameter( - DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO) - .withConstValue(defaultColorInfo) - .build()); - - addParameter( - DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsTuning::output( - 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mDefaultColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mDefaultColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mDefaultColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mDefaultColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(DefaultColorAspectsSetter) - .build()); - - addParameter( - DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsInfo::input( - 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mCodedColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mCodedColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mCodedColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mCodedColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(CodedColorAspectsSetter) - .build()); - - addParameter( - DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsInfo::output( - 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects) - .build()); - - // TODO: support more formats? - addParameter( - DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT) - .withConstValue(new C2StreamPixelFormatInfo::output( - 0u, HAL_PIXEL_FORMAT_YCBCR_420_888)) - .build()); - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe, - C2P<C2VideoSizeStreamInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - // TODO: get max width/height from the size's field helpers vs. hardcoding - me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4080u); - me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4080u); - return C2R::Ok(); - } - - static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me, - const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) { - (void)mayBlock; - // assume compression ratio of 2 - me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 192); - return C2R::Ok(); - } - - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - (void)size; - (void)me; // TODO: validate - return C2R::Ok(); - } - - static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) { - (void)mayBlock; - if (me.v.range > C2Color::RANGE_OTHER) { - me.set().range = C2Color::RANGE_OTHER; - } - if (me.v.primaries > C2Color::PRIMARIES_OTHER) { - me.set().primaries = C2Color::PRIMARIES_OTHER; - } - if (me.v.transfer > C2Color::TRANSFER_OTHER) { - me.set().transfer = C2Color::TRANSFER_OTHER; - } - if (me.v.matrix > C2Color::MATRIX_OTHER) { - me.set().matrix = C2Color::MATRIX_OTHER; - } - return C2R::Ok(); - } - - static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) { - (void)mayBlock; - if (me.v.range > C2Color::RANGE_OTHER) { - me.set().range = C2Color::RANGE_OTHER; - } - if (me.v.primaries > C2Color::PRIMARIES_OTHER) { - me.set().primaries = C2Color::PRIMARIES_OTHER; - } - if (me.v.transfer > C2Color::TRANSFER_OTHER) { - me.set().transfer = C2Color::TRANSFER_OTHER; - } - if (me.v.matrix > C2Color::MATRIX_OTHER) { - me.set().matrix = C2Color::MATRIX_OTHER; - } - return C2R::Ok(); - } - - static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me, - const C2P<C2StreamColorAspectsTuning::output> &def, - const C2P<C2StreamColorAspectsInfo::input> &coded) { - (void)mayBlock; - // take default values for all unspecified fields, and coded values for specified ones - me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range; - me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED - ? def.v.primaries : coded.v.primaries; - me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED - ? def.v.transfer : coded.v.transfer; - me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix; - return C2R::Ok(); - } - - std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() { - return mColorAspects; - } - -private: - std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; - std::shared_ptr<C2StreamPictureSizeInfo::output> mSize; - std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize; - std::shared_ptr<C2StreamColorInfo::output> mColorInfo; - std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects; - std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects; - std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects; - std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat; -}; - -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); -} - -C2SoftAvcDec::C2SoftAvcDec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mDecHandle(nullptr), - mOutBufferFlush(nullptr), - mIvColorFormat(IV_YUV_420P), - mWidth(320), - mHeight(240), - mHeaderDecoded(false) { - GENERATE_FILE_NAMES(); - CREATE_DUMP_FILE(mInFile); -} - -C2SoftAvcDec::~C2SoftAvcDec() { - onRelease(); -} - -c2_status_t C2SoftAvcDec::onInit() { - status_t err = initDecoder(); - return err == OK ? C2_OK : C2_CORRUPTED; -} - -c2_status_t C2SoftAvcDec::onStop() { - if (OK != resetDecoder()) return C2_CORRUPTED; - resetPlugin(); - return C2_OK; -} - -void C2SoftAvcDec::onReset() { - (void) onStop(); -} - -void C2SoftAvcDec::onRelease() { - (void) deleteDecoder(); - if (mOutBufferFlush) { - ivd_aligned_free(nullptr, mOutBufferFlush); - mOutBufferFlush = nullptr; - } - if (mOutBlock) { - mOutBlock.reset(); - } -} - -c2_status_t C2SoftAvcDec::onFlush_sm() { - if (OK != setFlushMode()) return C2_CORRUPTED; - - uint32_t bufferSize = mStride * mHeight * 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; - } - } - - if (mOutBufferFlush) { - ivd_aligned_free(nullptr, mOutBufferFlush); - mOutBufferFlush = nullptr; - } - - return C2_OK; -} - -status_t C2SoftAvcDec::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(nullptr, - &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 C2SoftAvcDec::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 C2SoftAvcDec::setParams(size_t stride, IVD_VIDEO_DECODE_MODE_T dec_mode) { - 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 = dec_mode; - 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; -} - -void C2SoftAvcDec::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); - } -} - -status_t C2SoftAvcDec::initDecoder() { - if (OK != createDecoder()) return UNKNOWN_ERROR; - mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES); - mStride = ALIGN64(mWidth); - mSignalledError = false; - resetPlugin(); - (void) setNumCores(); - if (OK != setParams(mStride, IVD_DECODE_FRAME)) return UNKNOWN_ERROR; - (void) getVersion(); - - return OK; -} - -bool C2SoftAvcDec::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); - - return true; -} - -bool C2SoftAvcDec::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) IH264D_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; - } - - VuiColorAspects vuiColorAspects; - vuiColorAspects.primaries = s_get_vui_params_op.u1_colour_primaries; - vuiColorAspects.transfer = s_get_vui_params_op.u1_tfr_chars; - vuiColorAspects.coeffs = s_get_vui_params_op.u1_matrix_coeffs; - vuiColorAspects.fullRange = s_get_vui_params_op.u1_video_full_range_flag; - - // convert vui aspects to C2 values if changed - if (!(vuiColorAspects == mBitstreamColorAspects)) { - mBitstreamColorAspects = vuiColorAspects; - ColorAspects sfAspects; - C2StreamColorAspectsInfo::input codedAspects = { 0u }; - ColorUtils::convertIsoColorAspectsToCodecAspects( - vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs, - vuiColorAspects.fullRange, sfAspects); - if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) { - codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) { - codedAspects.range = C2Color::RANGE_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) { - codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) { - codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED; - } - std::vector<std::unique_ptr<C2SettingResult>> failures; - (void)mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures); - } - return true; -} - -status_t C2SoftAvcDec::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 C2SoftAvcDec::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; - mHeaderDecoded = false; - - return OK; -} - -void C2SoftAvcDec::resetPlugin() { - mSignalledOutputEos = false; - gettimeofday(&mTimeStart, nullptr); - gettimeofday(&mTimeEnd, nullptr); -} - -status_t C2SoftAvcDec::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; -} - -static 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 C2SoftAvcDec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) { - std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mOutBlock), - C2Rect(mWidth, mHeight)); - mOutBlock = nullptr; - { - IntfImpl::Lock lock = mIntf->lock(); - buffer->setInfo(mIntf->getColorAspects_l()); - } - - auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) { - work->worklets.front()->output.flags = (C2FrameData::flags_t)0; - 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 C2SoftAvcDec::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, IVD_DECODE_FRAME)) 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 C2SoftAvcDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 0u; - work->worklets.front()->output.flags = work->input.flags; - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - size_t inOffset = 0u; - size_t inSize = 0u; - uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } - - ivd_video_decode_ip_t s_decode_ip; - ivd_video_decode_op_t s_decode_op; - { - C2GraphicView wView = mOutBlock->map().get(); - if (wView.error()) { - ALOGE("graphic view map failed %d", wView.error()); - work->result = wView.error(); - return; - } - if (!setDecodeArgs(&s_decode_ip, &s_decode_op, &rView, &wView, - inOffset + inPos, inSize - inPos, workIndex)) { - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } - - if (false == mHeaderDecoded) { - /* Decode header and get dimensions */ - setParams(mStride, IVD_DECODE_HEADER); - } - - WORD32 delay; - GETTIME(&mTimeStart, nullptr); - 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"); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & 0xFF)) { - ALOGE("unsupported resolution : %dx%d", mWidth, mHeight); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - 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(); - work->workletsProcessed = 0u; - - /* Decode header and get new dimensions */ - setParams(mStride, IVD_DECODE_HEADER); - (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op); - } - if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) { - if (mHeaderDecoded == false) { - mHeaderDecoded = true; - setParams(ALIGN64(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME); - } - 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); - - C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(size)); - } else { - ALOGE("Cannot set width and height"); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } - continue; - } - } - (void)getVuiParams(); - hasPicture |= (1 == s_decode_op.u4_frame_decoded_flag); - if (s_decode_op.u4_output_present) { - finishWork(s_decode_op.u4_ts, work); - } - if (0 == s_decode_op.u4_num_bytes_consumed) { - ALOGD("Bytes consumed is zero. Ignoring remaining bytes"); - break; - } - 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 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; - } - - if (OK != setFlushMode()) return C2_CORRUPTED; - while (true) { - if (C2_OK != ensureDecoderState(pool)) { - mSignalledError = true; - work->workletsProcessed = 1u; - 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; - work->workletsProcessed = 1u; - 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 { - fillEmptyWork(work); - break; - } - } - - return C2_OK; -} - -c2_status_t C2SoftAvcDec::drain( - uint32_t drainMode, - const std::shared_ptr<C2BlockPool> &pool) { - return drainInternal(drainMode, pool, nullptr); -} - -class C2SoftAvcDecFactory : public C2ComponentFactory { -public: - C2SoftAvcDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftAvcDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftAvcDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftAvcDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftAvcDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/avc/C2SoftAvcDec.h b/media/codecs/avc/C2SoftAvcDec.h deleted file mode 100644 index 2127a93..0000000 --- a/media/codecs/avc/C2SoftAvcDec.h +++ /dev/null @@ -1,196 +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 ANDROID_C2_SOFT_AVC_DEC_H_ -#define ANDROID_C2_SOFT_AVC_DEC_H_ - -#include <sys/time.h> - -#include <media/stagefright/foundation/ColorUtils.h> - -#include <SimpleC2Component.h> - -#include "ih264_typedefs.h" -#include "iv.h" -#include "ivd.h" - -namespace android { - -#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_ctl_get_vui_params_ip_t ih264d_ctl_get_vui_params_ip_t -#define ivdext_ctl_get_vui_params_op_t ih264d_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)IH264D_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/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 */ - - -class C2SoftAvcDec : public SimpleC2Component { -public: - class IntfImpl; - C2SoftAvcDec(const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl); - 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: - status_t createDecoder(); - status_t setNumCores(); - status_t setParams(size_t stride, IVD_VIDEO_DECODE_MODE_T dec_mode); - void 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(); - 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(); - - std::shared_ptr<IntfImpl> mIntf; - - // 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; - bool mHeaderDecoded; - // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid - // converting them to C2 values for each frame - struct VuiColorAspects { - uint8_t primaries; - uint8_t transfer; - uint8_t coeffs; - uint8_t fullRange; - - // default color aspects - VuiColorAspects() - : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - - bool operator==(const VuiColorAspects &o) { - return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs - && fullRange == o.fullRange; - } - } mBitstreamColorAspects; - - // profile - struct timeval mTimeStart; - struct timeval mTimeEnd; -#ifdef FILE_DUMP_ENABLE - char mInFile[200]; -#endif /* FILE_DUMP_ENABLE */ - - C2_DO_NOT_COPY(C2SoftAvcDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_AVC_DEC_H_ diff --git a/media/codecs/avc/C2SoftAvcEnc.cpp b/media/codecs/avc/C2SoftAvcEnc.cpp deleted file mode 100644 index bfe745c..0000000 --- a/media/codecs/avc/C2SoftAvcEnc.cpp +++ /dev/null @@ -1,1559 +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 <log/log.h> -#include <utils/misc.h> - -#include <media/hardware/VideoAPI.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/foundation/AUtils.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <Codec2BufferUtils.h> -#include <SimpleC2Interface.h> -#include <util/C2InterfaceHelper.h> - -#include "C2SoftAvcEnc.h" -#include "ih264e.h" -#include "ih264e_error.h" - -namespace android { - -class C2SoftAvcEnc::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatVideo)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_VIDEO_RAW)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_VIDEO_AVC)) - .build()); - - addParameter( - DefineParam(mUsage, C2_NAME_INPUT_STREAM_USAGE_SETTING) - .withConstValue(new C2StreamUsageTuning::input( - 0u, (uint64_t)C2MemoryUsage::CPU_READ)) - .build()); - - addParameter( - DefineParam(mSize, C2_NAME_STREAM_VIDEO_SIZE_SETTING) - .withDefault(new C2VideoSizeStreamTuning::input(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 2560, 2), - C2F(mSize, height).inRange(2, 2560, 2), - }) - .withSetter(SizeSetter) - .build()); - - addParameter( - DefineParam(mFrameRate, C2_NAME_STREAM_FRAME_RATE_SETTING) - .withDefault(new C2StreamFrameRateInfo::output(0u, 30.)) - // TODO: More restriction? - .withFields({C2F(mFrameRate, value).greaterThan(0.)}) - .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::output(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(4096, 12000000)}) - .withSetter(BitrateSetter) - .build()); - - addParameter( - DefineParam(mIntraRefresh, C2_PARAMKEY_INTRA_REFRESH) - .withDefault(new C2StreamIntraRefreshTuning::output( - 0u, C2Config::INTRA_REFRESH_DISABLED, 0.)) - .withFields({ - C2F(mIntraRefresh, mode).oneOf({ - C2Config::INTRA_REFRESH_DISABLED, C2Config::INTRA_REFRESH_ARBITRARY }), - C2F(mIntraRefresh, period).any() - }) - .withSetter(IntraRefreshSetter) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::output( - 0u, PROFILE_AVC_CONSTRAINED_BASELINE, LEVEL_AVC_4_1)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - PROFILE_AVC_BASELINE, - PROFILE_AVC_CONSTRAINED_BASELINE, - PROFILE_AVC_MAIN, - }), - C2F(mProfileLevel, level).oneOf({ - LEVEL_AVC_1, - LEVEL_AVC_1B, - LEVEL_AVC_1_1, - LEVEL_AVC_1_2, - LEVEL_AVC_1_3, - LEVEL_AVC_2, - LEVEL_AVC_2_1, - LEVEL_AVC_2_2, - LEVEL_AVC_3, - LEVEL_AVC_3_1, - LEVEL_AVC_3_2, - LEVEL_AVC_4, - LEVEL_AVC_4_1, - LEVEL_AVC_4_2, - LEVEL_AVC_5, - }), - }) - .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate) - .build()); - - addParameter( - DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME) - .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE)) - .withFields({C2F(mRequestSync, value).oneOf({ C2_FALSE, C2_TRUE }) }) - .withSetter(Setter<decltype(*mRequestSync)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mSyncFramePeriod, C2_PARAMKEY_SYNC_FRAME_INTERVAL) - .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000)) - .withFields({C2F(mSyncFramePeriod, value).any()}) - .withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps) - .build()); - } - - static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (me.v.value <= 4096) { - me.set().value = 4096; - } - return res; - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe, - C2P<C2StreamPictureSizeInfo::input> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R ProfileLevelSetter( - bool mayBlock, - C2P<C2StreamProfileLevelInfo::output> &me, - const C2P<C2VideoSizeStreamTuning::input> &size, - const C2P<C2StreamFrameRateInfo::output> &frameRate, - const C2P<C2BitrateTuning::output> &bitrate) { - (void)mayBlock; - if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) { - me.set().profile = PROFILE_AVC_CONSTRAINED_BASELINE; - } - - struct LevelLimits { - C2Config::level_t level; - float mbsPerSec; - uint64_t mbs; - uint32_t bitrate; - }; - constexpr LevelLimits kLimits[] = { - { LEVEL_AVC_1, 1485, 99, 64000 }, - // Decoder does not properly handle level 1b. - // { LEVEL_AVC_1B, 1485, 99, 128000 }, - { LEVEL_AVC_1_1, 3000, 396, 192000 }, - { LEVEL_AVC_1_2, 6000, 396, 384000 }, - { LEVEL_AVC_1_3, 11880, 396, 768000 }, - { LEVEL_AVC_2, 11880, 396, 2000000 }, - { LEVEL_AVC_2_1, 19800, 792, 4000000 }, - { LEVEL_AVC_2_2, 20250, 1620, 4000000 }, - { LEVEL_AVC_3, 40500, 1620, 10000000 }, - { LEVEL_AVC_3_1, 108000, 3600, 14000000 }, - { LEVEL_AVC_3_2, 216000, 5120, 20000000 }, - { LEVEL_AVC_4, 245760, 8192, 20000000 }, - { LEVEL_AVC_4_1, 245760, 8192, 50000000 }, - { LEVEL_AVC_4_2, 522240, 8704, 50000000 }, - { LEVEL_AVC_5, 589824, 22080, 135000000 }, - }; - - uint64_t mbs = uint64_t((size.v.width + 15) / 16) * ((size.v.height + 15) / 16); - float mbsPerSec = float(mbs) * frameRate.v.value; - - // Check if the supplied level meets the MB / bitrate requirements. If - // not, update the level with the lowest level meeting the requirements. - - bool found = false; - // By default needsUpdate = false in case the supplied level does meet - // the requirements. For Level 1b, we want to update the level anyway, - // so we set it to true in that case. - bool needsUpdate = (me.v.level == LEVEL_AVC_1B); - for (const LevelLimits &limit : kLimits) { - if (mbs <= limit.mbs && mbsPerSec <= limit.mbsPerSec && - bitrate.v.value <= limit.bitrate) { - // This is the lowest level that meets the requirements, and if - // we haven't seen the supplied level yet, that means we don't - // need the update. - if (needsUpdate) { - ALOGD("Given level %x does not cover current configuration: " - "adjusting to %x", me.v.level, limit.level); - me.set().level = limit.level; - } - found = true; - break; - } - if (me.v.level == limit.level) { - // We break out of the loop when the lowest feasible level is - // found. The fact that we're here means that our level doesn't - // meet the requirement and needs to be updated. - needsUpdate = true; - } - } - if (!found) { - // We set to the highest supported level. - me.set().level = LEVEL_AVC_5; - } - - return C2R::Ok(); - } - - static C2R IntraRefreshSetter(bool mayBlock, C2P<C2StreamIntraRefreshTuning::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (me.v.period < 1) { - me.set().mode = C2Config::INTRA_REFRESH_DISABLED; - me.set().period = 0; - } else { - // only support arbitrary mode (cyclic in our case) - me.set().mode = C2Config::INTRA_REFRESH_ARBITRARY; - } - return res; - } - - IV_PROFILE_T getProfile_l() const { - switch (mProfileLevel->profile) { - case PROFILE_AVC_CONSTRAINED_BASELINE: [[fallthrough]]; - case PROFILE_AVC_BASELINE: return IV_PROFILE_BASE; - case PROFILE_AVC_MAIN: return IV_PROFILE_MAIN; - default: - ALOGD("Unrecognized profile: %x", mProfileLevel->profile); - return IV_PROFILE_DEFAULT; - } - } - - UWORD32 getLevel_l() const { - struct Level { - C2Config::level_t c2Level; - UWORD32 avcLevel; - }; - constexpr Level levels[] = { - { LEVEL_AVC_1, 10 }, - { LEVEL_AVC_1B, 9 }, - { LEVEL_AVC_1_1, 11 }, - { LEVEL_AVC_1_2, 12 }, - { LEVEL_AVC_1_3, 13 }, - { LEVEL_AVC_2, 20 }, - { LEVEL_AVC_2_1, 21 }, - { LEVEL_AVC_2_2, 22 }, - { LEVEL_AVC_3, 30 }, - { LEVEL_AVC_3_1, 31 }, - { LEVEL_AVC_3_2, 32 }, - { LEVEL_AVC_4, 40 }, - { LEVEL_AVC_4_1, 41 }, - { LEVEL_AVC_4_2, 42 }, - { LEVEL_AVC_5, 50 }, - }; - for (const Level &level : levels) { - if (mProfileLevel->level == level.c2Level) { - return level.avcLevel; - } - } - ALOGD("Unrecognized level: %x", mProfileLevel->level); - return 41; - } - uint32_t getSyncFramePeriod_l() const { - if (mSyncFramePeriod->value < 0 || mSyncFramePeriod->value == INT64_MAX) { - return 0; - } - double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value; - return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.); - } - - // unsafe getters - std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const { return mSize; } - std::shared_ptr<C2StreamIntraRefreshTuning::output> getIntraRefresh_l() const { return mIntraRefresh; } - std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; } - std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; } - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamUsageTuning::input> mUsage; - std::shared_ptr<C2VideoSizeStreamTuning::input> mSize; - std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync; - std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh; - std::shared_ptr<C2BitrateTuning::output> mBitrate; - std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel; - std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod; -}; - -#define ive_api_function ih264e_api_function - -constexpr char COMPONENT_NAME[] = "c2.android.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; -} - -} // namespace - -C2SoftAvcEnc::C2SoftAvcEnc( - const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mIvVideoColorFormat(IV_YUV_420P), - mAVCEncProfile(IV_PROFILE_BASE), - mAVCEncLevel(41), - mStarted(false), - mSawInputEOS(false), - mSawOutputEOS(false), - mSignalledError(false), - mCodecCtx(nullptr), - // 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 = nullptr; - mMemRecords = nullptr; - 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; - mPSNREnable = DEFAULT_PSNR_ENABLE; - mReconEnable = DEFAULT_RECON_ENABLE; - mEntropyMode = DEFAULT_ENTROPY_MODE; - mBframes = DEFAULT_B_FRAMES; - - gettimeofday(&mTimeStart, nullptr); - gettimeofday(&mTimeEnd, nullptr); -} - -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 = mSize->height; - s_dimensions_ip.u4_wd = mSize->width; - - 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->value + 0.5; - s_frame_rate_ip.u4_tgt_frame_rate = mFrameRate->value + 0.5; - - 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->value; - - 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 = - (mIntraRefresh->mode == C2Config::INTRA_REFRESH_DISABLED || mIntraRefresh->period < 1) - ? IVE_AIR_MODE_NONE : IVE_AIR_MODE_CYCLIC; - s_air_ip.u4_air_refresh_period = mIntraRefresh->period; - - 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() { - IntfImpl::Lock lock = mIntf->lock(); - - 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 = mIntf->getProfile_l(); - 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); - lock.unlock(); - - 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; - - CHECK(!mStarted); - - c2_status_t errType = C2_OK; - - { - IntfImpl::Lock lock = mIntf->lock(); - mSize = mIntf->getSize_l(); - mBitrate = mIntf->getBitrate_l(); - mFrameRate = mIntf->getFrameRate_l(); - mIntraRefresh = mIntf->getIntraRefresh_l(); - mAVCEncLevel = mIntf->getLevel_l(); - mIInterval = mIntf->getSyncFramePeriod_l(); - mIDRInterval = mIntf->getSyncFramePeriod_l(); - } - uint32_t width = mSize->width; - uint32_t height = mSize->height; - - mStride = width; - - // TODO - mIvVideoColorFormat = IV_YUV_420P; - - ALOGD("Params width %d height %d level %d colorFormat %d", width, - height, 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(nullptr, &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 (nullptr == 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 = nullptr; - 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 = width; - s_fill_mem_rec_ip.u4_max_ht = height; - 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(nullptr, &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 == nullptr) { - 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 = width; - s_init_ip.u4_max_ht = height; - 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++) { - if (ps_mem_rec) ive_aligned_free(ps_mem_rec->pv_base); - else { - ALOGE("memory record is null."); - return C2_CORRUPTED; - } - ps_mem_rec++; - } - - if (mMemRecords) free(mMemRecords); - - // clear other pointers into the space being free()d - mCodecCtx = nullptr; - - 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 = nullptr; - ps_encode_ip->pv_mb_info = nullptr; - ps_encode_ip->pv_pic_info = nullptr; - 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 = nullptr; - - /* 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; - } - - if (input->width() < mSize->width || - input->height() < mSize->height) { - /* Expect width height to be configured */ - ALOGW("unexpected Capacity Aspect %d(%d) x %d(%d)", input->width(), - mSize->width, input->height(), mSize->height); - return C2_BAD_VALUE; - } - ALOGV("width = %d, height = %d", input->width(), input->height()); - 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; - - uint32_t width = mSize->width; - uint32_t height = mSize->height; - // width and height are always even (as block size is 16x16) - CHECK_EQ((width & 1u), 0u); - CHECK_EQ((height & 1u), 0u); - size_t yPlaneSize = width * height; - - switch (layout.type) { - case C2PlanarLayout::TYPE_RGB: - [[fallthrough]]; - case C2PlanarLayout::TYPE_RGBA: { - ALOGV("yPlaneSize = %zu", yPlaneSize); - MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2); - mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer); - yPlane = conversionBuffer.data(); - uPlane = yPlane + yPlaneSize; - vPlane = uPlane + yPlaneSize / 4; - yStride = width; - uStride = vStride = yStride / 2; - ConvertRGBToPlanarYUV(yPlane, yStride, height, conversionBuffer.size(), *input); - break; - } - case C2PlanarLayout::TYPE_YUV: { - if (!IsYUV420(*input)) { - ALOGE("input is not YUV420"); - return C2_BAD_VALUE; - } - - if (layout.planes[layout.PLANE_Y].colInc == 1 - && layout.planes[layout.PLANE_U].colInc == 1 - && layout.planes[layout.PLANE_V].colInc == 1 - && uStride == vStride - && yStride == 2 * vStride) { - // I420 compatible - already set up above - break; - } - - // copy to I420 - yStride = width; - uStride = vStride = yStride / 2; - MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2); - mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer); - MediaImage2 img = CreateYUV420PlanarMediaImage2(width, height, yStride, height); - status_t err = ImageCopy(conversionBuffer.data(), &img, *input); - if (err != OK) { - ALOGE("Buffer conversion failed: %d", err); - return C2_BAD_VALUE; - } - yPlane = conversionBuffer.data(); - uPlane = yPlane + yPlaneSize; - vPlane = uPlane + yPlaneSize / 4; - break; - - } - - case C2PlanarLayout::TYPE_YUVA: - ALOGE("YUVA plane type is not supported"); - return C2_BAD_VALUE; - - 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - IV_STATUS_T status; - WORD32 timeDelay, timeTaken; - uint64_t timestamp = work->input.ordinal.timestamp.peekull(); - - // Initialize encoder if not already initialized - if (mCodecCtx == nullptr) { - if (C2_OK != initEncoder()) { - ALOGE("Failed to initialize encoder"); - mSignalledError = true; - 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, nullptr, header, kHeaderLength, timestamp); - if (error != C2_OK) { - ALOGE("setEncodeArgs failed: %d", error); - mSignalledError = true; - 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); - if (!csd) { - ALOGE("CSD allocation failed"); - mSignalledError = true; - work->result = C2_NO_MEMORY; - return; - } - 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()); - } - - // handle dynamic config parameters - { - IntfImpl::Lock lock = mIntf->lock(); - std::shared_ptr<C2StreamIntraRefreshTuning::output> intraRefresh = mIntf->getIntraRefresh_l(); - std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l(); - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> requestSync = mIntf->getRequestSync_l(); - lock.unlock(); - - if (bitrate != mBitrate) { - mBitrate = bitrate; - setBitRate(); - } - - if (intraRefresh != mIntraRefresh) { - mIntraRefresh = intraRefresh; - setAirParams(); - } - - if (requestSync != mRequestSync) { - // we can handle IDR immediately - if (requestSync->value) { - // unset request - C2StreamRequestSyncFrameTuning::output clearSync(0u, C2_FALSE); - std::vector<std::unique_ptr<C2SettingResult>> failures; - mIntf->config({ &clearSync }, C2_MAY_BLOCK, &failures); - ALOGV("Got sync request"); - setFrameType(IV_IDR_FRAME); - } - mRequestSync = requestSync; - } - } - - 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; - // } - // } - // } - std::shared_ptr<const C2GraphicView> view; - std::shared_ptr<C2Buffer> inputBuffer; - if (!work->input.buffers.empty()) { - inputBuffer = work->input.buffers[0]; - view = std::make_shared<const C2GraphicView>( - inputBuffer->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->result = err; - return; - } - C2WriteView wView = block->map().get(); - if (wView.error() != C2_OK) { - ALOGE("write view map err = %d", wView.error()); - work->result = wView.error(); - return; - } - - error = setEncodeArgs( - &s_encode_ip, &s_encode_op, view.get(), wView.base(), wView.capacity(), timestamp); - if (error != C2_OK) { - ALOGE("setEncodeArgs failed : %d", error); - mSignalledError = true; - work->result = error; - return; - } - - // DUMP_TO_FILE( - // mInFile, s_encode_ip.s_inp_buf.apv_bufs[0], - // (mHeight * mStride * 3 / 2)); - - GETTIME(&mTimeStart, nullptr); - /* 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->result = C2_CORRUPTED; - return; - } - } while (IV_SUCCESS != status); - - // Hold input buffer reference - if (inputBuffer) { - mBuffers[s_encode_ip.s_inp_buf.apv_bufs[0]] = inputBuffer; - } - - GETTIME(&mTimeEnd, nullptr); - /* 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 != nullptr) { - if (mBuffers.count(freed) == 0u) { - ALOGD("buffer not tracked"); - } else { - // Release input buffer reference - mBuffers.erase(freed); - mConversionBuffersInUse.erase(freed); - } - } - - 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(); - - if (s_encode_op.s_out_buf.u4_bytes) { - std::shared_ptr<C2Buffer> buffer = - createLinearBuffer(block, 0, s_encode_op.s_out_buf.u4_bytes); - if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) { - ALOGV("IDR frame produced"); - buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>( - 0u /* stream id */, C2PictureTypeKeyFrame)); - } - work->worklets.front()->output.buffers.push_back(buffer); - } - - 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: - C2SoftAvcEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftAvcEnc::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftAvcEncFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/avc/C2SoftAvcEnc.h b/media/codecs/avc/C2SoftAvcEnc.h deleted file mode 100644 index aa3ca61..0000000 --- a/media/codecs/avc/C2SoftAvcEnc.h +++ /dev/null @@ -1,296 +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 ANDROID_C2_SOFT_AVC_ENC_H__ -#define ANDROID_C2_SOFT_AVC_ENC_H__ - -#include <map> - -#include <utils/Vector.h> - -#include <SimpleC2Component.h> - -#include "ih264_typedefs.h" -#include "iv2.h" -#include "ive2.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 { - class IntfImpl; - - C2SoftAvcEnc(const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl); - - // 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: - // OMX input buffer's timestamp and flags - typedef struct { - int64_t mTimeUs; - int32_t mFlags; - } InputBufferInfo; - - std::shared_ptr<IntfImpl> mIntf; - - int32_t mStride; - - struct timeval mTimeStart; // Time at the start of decode() - struct timeval mTimeEnd; // Time at the end of decode() - -#ifdef FILE_DUMP_ENABLE - char mInFile[200]; - char mOutFile[200]; -#endif /* FILE_DUMP_ENABLE */ - - IV_COLOR_FORMAT_T mIvVideoColorFormat; - - IV_PROFILE_T mAVCEncProfile __unused; - 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 - - // configurations used by component in process - // (TODO: keep this in intf but make them internal only) - std::shared_ptr<C2StreamPictureSizeInfo::input> mSize; - std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh; - std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; - std::shared_ptr<C2StreamBitrateInfo::output> mBitrate; - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync; - - 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; - std::map<const void *, std::shared_ptr<C2Buffer>> mBuffers; - MemoryBlockPool mConversionBuffers; - std::map<const void *, MemoryBlock> 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); - - C2_DO_NOT_COPY(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 // ANDROID_C2_SOFT_AVC_ENC_H__ diff --git a/media/codecs/base/Android.bp b/media/codecs/base/Android.bp deleted file mode 100644 index 473cb4d..0000000 --- a/media/codecs/base/Android.bp +++ /dev/null @@ -1,129 +0,0 @@ -// DO NOT DEPEND ON THIS DIRECTLY -// use libstagefright_soft_c2-defaults instead -cc_library_shared { - name: "libstagefright_soft_c2common", - defaults: ["libstagefright_codec2-impl-defaults"], - vendor_available: true, - - srcs: [ - "SimpleC2Component.cpp", - "SimpleC2Interface.cpp", - ], - - export_include_dirs: [ - "include", - ], - - export_shared_lib_headers: [ - "libstagefright_ccodec_utils", - ], - - shared_libs: [ - "libcutils", // for properties - "liblog", // for ALOG - "libstagefright_ccodec_utils", // for ImageCopy - "libstagefright_foundation", // for Mutexed - ], - - sanitize: { - misc_undefined: [ - "unsigned-integer-overflow", - "signed-integer-overflow", - ], - cfi: true, - }, - - ldflags: ["-Wl,-Bsymbolic"], -} - -// public dependency for software codec implementation -// to be used by code under media/codecs/* only as its stability is not guaranteed -cc_defaults { - name: "libstagefright_soft_c2-defaults", - defaults: ["libstagefright_codec2-impl-defaults"], - vendor_available: true, - - export_shared_lib_headers: [ - "libstagefright_ccodec_utils", - ], - - shared_libs: [ - "libcutils", // for properties - "liblog", // for ALOG - "libstagefright_foundation", // for ColorUtils and MIME - "libstagefright_ccodec_utils", // for ImageCopy - "libstagefright_soft_c2common", - ], - - cflags: [ - "-Wall", - "-Werror", - ], - - ldflags: ["-Wl,-Bsymbolic"], -} - -// public dependency for software codec implementation -// to be used by code under media/codecs/* only -cc_defaults { - name: "libstagefright_soft_c2_sanitize_all-defaults", - - sanitize: { - misc_undefined: [ - "unsigned-integer-overflow", - "signed-integer-overflow", - ], - cfi: true, - }, -} - -// public dependency for software codec implementation -// to be used by code under media/codecs/* only -cc_defaults { - name: "libstagefright_soft_c2_sanitize_signed-defaults", - - sanitize: { - misc_undefined: [ - "signed-integer-overflow", - ], - cfi: true, - }, -} - -// TEMP: used by cheets2 project - remove when no longer used -cc_library_shared { - name: "libstagefright_simple_c2component", - vendor_available: true, - - srcs: [ - "SimpleC2Interface.cpp", - ], - - local_include_dirs: [ - "include", - ], - - export_include_dirs: [ - "include", - ], - - shared_libs: [ - "libcutils", - "liblog", - "libstagefright_codec2", - "libstagefright_codec2_vndk", - "libstagefright_foundation", - "libutils", - ], - - sanitize: { - misc_undefined: [ - "unsigned-integer-overflow", - "signed-integer-overflow", - ], - cfi: true, - }, - - ldflags: ["-Wl,-Bsymbolic"], -} - diff --git a/media/codecs/base/SimpleC2Component.cpp b/media/codecs/base/SimpleC2Component.cpp deleted file mode 100644 index 50b4d20..0000000 --- a/media/codecs/base/SimpleC2Component.cpp +++ /dev/null @@ -1,569 +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 "SimpleC2Component" -#include <log/log.h> - -#include <cutils/properties.h> -#include <media/stagefright/foundation/AMessage.h> - -#include <inttypes.h> - -#include <C2Config.h> -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <SimpleC2Component.h> - -namespace android { - -std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() { - std::unique_ptr<C2Work> work = std::move(mQueue.front().work); - mQueue.pop_front(); - return work; -} - -void SimpleC2Component::WorkQueue::push_back(std::unique_ptr<C2Work> work) { - mQueue.push_back({ std::move(work), NO_DRAIN }); -} - -bool SimpleC2Component::WorkQueue::empty() const { - return mQueue.empty(); -} - -void SimpleC2Component::WorkQueue::clear() { - mQueue.clear(); -} - -uint32_t SimpleC2Component::WorkQueue::drainMode() const { - return mQueue.front().drainMode; -} - -void SimpleC2Component::WorkQueue::markDrain(uint32_t drainMode) { - mQueue.push_back({ nullptr, drainMode }); -} - -//////////////////////////////////////////////////////////////////////////////// - -SimpleC2Component::WorkHandler::WorkHandler() : mRunning(false) {} - -void SimpleC2Component::WorkHandler::setComponent( - const std::shared_ptr<SimpleC2Component> &thiz) { - mThiz = thiz; -} - -static void Reply(const sp<AMessage> &msg, int32_t *err = nullptr) { - sp<AReplyToken> replyId; - CHECK(msg->senderAwaitsResponse(&replyId)); - sp<AMessage> reply = new AMessage; - if (err) { - reply->setInt32("err", *err); - } - reply->postReply(replyId); -} - -void SimpleC2Component::WorkHandler::onMessageReceived(const sp<AMessage> &msg) { - std::shared_ptr<SimpleC2Component> thiz = mThiz.lock(); - if (!thiz) { - ALOGD("component not yet set; msg = %s", msg->debugString().c_str()); - sp<AReplyToken> replyId; - if (msg->senderAwaitsResponse(&replyId)) { - sp<AMessage> reply = new AMessage; - reply->setInt32("err", C2_CORRUPTED); - reply->postReply(replyId); - } - return; - } - - switch (msg->what()) { - case kWhatProcess: { - if (mRunning) { - if (thiz->processQueue()) { - (new AMessage(kWhatProcess, this))->post(); - } - } else { - ALOGV("Ignore process message as we're not running"); - } - break; - } - case kWhatInit: { - int32_t err = thiz->onInit(); - Reply(msg, &err); - [[fallthrough]]; - } - case kWhatStart: { - mRunning = true; - break; - } - case kWhatStop: { - int32_t err = thiz->onStop(); - Reply(msg, &err); - break; - } - case kWhatReset: { - thiz->onReset(); - mRunning = false; - Reply(msg); - break; - } - case kWhatRelease: { - thiz->onRelease(); - mRunning = false; - Reply(msg); - break; - } - default: { - ALOGD("Unrecognized msg: %d", msg->what()); - break; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// - -namespace { - -struct DummyReadView : public C2ReadView { - DummyReadView() : C2ReadView(C2_NO_INIT) {} -}; - -} // namespace - -SimpleC2Component::SimpleC2Component( - const std::shared_ptr<C2ComponentInterface> &intf) - : mDummyReadView(DummyReadView()), - mIntf(intf), - mLooper(new ALooper), - mHandler(new WorkHandler) { - mLooper->setName(intf->getName().c_str()); - (void)mLooper->registerHandler(mHandler); - mLooper->start(false, false, ANDROID_PRIORITY_VIDEO); -} - -SimpleC2Component::~SimpleC2Component() { - mLooper->unregisterHandler(mHandler->id()); - (void)mLooper->stop(); -} - -c2_status_t SimpleC2Component::setListener_vb( - const std::shared_ptr<C2Component::Listener> &listener, c2_blocking_t mayBlock) { - mHandler->setComponent(shared_from_this()); - - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState == RUNNING) { - if (listener) { - return C2_BAD_STATE; - } else if (!mayBlock) { - return C2_BLOCKING; - } - } - state->mListener = listener; - // TODO: wait for listener change to have taken place before returning - // (e.g. if there is an ongoing listener callback) - return C2_OK; -} - -c2_status_t SimpleC2Component::queue_nb(std::list<std::unique_ptr<C2Work>> * const items) { - { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState != RUNNING) { - return C2_BAD_STATE; - } - } - bool queueWasEmpty = false; - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queueWasEmpty = queue->empty(); - while (!items->empty()) { - queue->push_back(std::move(items->front())); - items->pop_front(); - } - } - if (queueWasEmpty) { - (new AMessage(WorkHandler::kWhatProcess, mHandler))->post(); - } - return C2_OK; -} - -c2_status_t SimpleC2Component::announce_nb(const std::vector<C2WorkOutline> &items) { - (void)items; - return C2_OMITTED; -} - -c2_status_t SimpleC2Component::flush_sm( - flush_mode_t flushMode, std::list<std::unique_ptr<C2Work>>* const flushedWork) { - (void)flushMode; - { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState != RUNNING) { - return C2_BAD_STATE; - } - } - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queue->incGeneration(); - // TODO: queue->splicedBy(flushedWork, flushedWork->end()); - while (!queue->empty()) { - std::unique_ptr<C2Work> work = queue->pop_front(); - if (work) { - flushedWork->push_back(std::move(work)); - } - } - } - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - while (!pending->empty()) { - flushedWork->push_back(std::move(pending->begin()->second)); - pending->erase(pending->begin()); - } - } - - return C2_OK; -} - -c2_status_t SimpleC2Component::drain_nb(drain_mode_t drainMode) { - if (drainMode == DRAIN_CHAIN) { - return C2_OMITTED; - } - { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState != RUNNING) { - return C2_BAD_STATE; - } - } - bool queueWasEmpty = false; - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queueWasEmpty = queue->empty(); - queue->markDrain(drainMode); - } - if (queueWasEmpty) { - (new AMessage(WorkHandler::kWhatProcess, mHandler))->post(); - } - - return C2_OK; -} - -c2_status_t SimpleC2Component::start() { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState == RUNNING) { - return C2_BAD_STATE; - } - bool needsInit = (state->mState == UNINITIALIZED); - state.unlock(); - if (needsInit) { - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatInit, mHandler))->postAndAwaitResponse(&reply); - int32_t err; - CHECK(reply->findInt32("err", &err)); - if (err != C2_OK) { - return (c2_status_t)err; - } - } else { - (new AMessage(WorkHandler::kWhatStart, mHandler))->post(); - } - state.lock(); - state->mState = RUNNING; - return C2_OK; -} - -c2_status_t SimpleC2Component::stop() { - ALOGV("stop"); - { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState != RUNNING) { - return C2_BAD_STATE; - } - state->mState = STOPPED; - } - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queue->clear(); - } - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - pending->clear(); - } - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatStop, mHandler))->postAndAwaitResponse(&reply); - int32_t err; - CHECK(reply->findInt32("err", &err)); - if (err != C2_OK) { - return (c2_status_t)err; - } - return C2_OK; -} - -c2_status_t SimpleC2Component::reset() { - ALOGV("reset"); - { - Mutexed<ExecState>::Locked state(mExecState); - state->mState = UNINITIALIZED; - } - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queue->clear(); - } - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - pending->clear(); - } - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatReset, mHandler))->postAndAwaitResponse(&reply); - return C2_OK; -} - -c2_status_t SimpleC2Component::release() { - ALOGV("release"); - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatRelease, mHandler))->postAndAwaitResponse(&reply); - return C2_OK; -} - -std::shared_ptr<C2ComponentInterface> SimpleC2Component::intf() { - return mIntf; -} - -namespace { - -std::list<std::unique_ptr<C2Work>> vec(std::unique_ptr<C2Work> &work) { - std::list<std::unique_ptr<C2Work>> ret; - ret.push_back(std::move(work)); - return ret; -} - -} // namespace - -void SimpleC2Component::finish( - uint64_t frameIndex, std::function<void(const std::unique_ptr<C2Work> &)> fillWork) { - std::unique_ptr<C2Work> work; - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - if (pending->count(frameIndex) == 0) { - ALOGW("unknown frame index: %" PRIu64, frameIndex); - return; - } - work = std::move(pending->at(frameIndex)); - pending->erase(frameIndex); - } - if (work) { - fillWork(work); - std::shared_ptr<C2Component::Listener> listener = mExecState.lock()->mListener; - listener->onWorkDone_nb(shared_from_this(), vec(work)); - ALOGV("returning pending work"); - } -} - -void SimpleC2Component::cloneAndSend( - uint64_t frameIndex, - const std::unique_ptr<C2Work> ¤tWork, - std::function<void(const std::unique_ptr<C2Work> &)> fillWork) { - std::unique_ptr<C2Work> work(new C2Work); - if (currentWork->input.ordinal.frameIndex == frameIndex) { - work->input.flags = currentWork->input.flags; - work->input.ordinal = currentWork->input.ordinal; - } else { - Mutexed<PendingWork>::Locked pending(mPendingWork); - if (pending->count(frameIndex) == 0) { - ALOGW("unknown frame index: %" PRIu64, frameIndex); - return; - } - work->input.flags = pending->at(frameIndex)->input.flags; - work->input.ordinal = pending->at(frameIndex)->input.ordinal; - } - work->worklets.emplace_back(new C2Worklet); - if (work) { - fillWork(work); - std::shared_ptr<C2Component::Listener> listener = mExecState.lock()->mListener; - listener->onWorkDone_nb(shared_from_this(), vec(work)); - ALOGV("cloned and sending work"); - } -} - -bool SimpleC2Component::processQueue() { - std::unique_ptr<C2Work> work; - uint64_t generation; - int32_t drainMode; - bool isFlushPending = false; - bool hasQueuedWork = false; - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - if (queue->empty()) { - return false; - } - - generation = queue->generation(); - drainMode = queue->drainMode(); - isFlushPending = queue->popPendingFlush(); - work = queue->pop_front(); - hasQueuedWork = !queue->empty(); - } - if (isFlushPending) { - ALOGV("processing pending flush"); - c2_status_t err = onFlush_sm(); - if (err != C2_OK) { - ALOGD("flush err: %d", err); - // TODO: error - } - } - - if (!mOutputBlockPool) { - c2_status_t err = [this] { - // TODO: don't use query_vb - C2StreamFormatConfig::output outputFormat(0u); - std::vector<std::unique_ptr<C2Param>> params; - c2_status_t err = intf()->query_vb( - { &outputFormat }, - { C2PortBlockPoolsTuning::output::PARAM_TYPE }, - C2_DONT_BLOCK, - ¶ms); - if (err != C2_OK && err != C2_BAD_INDEX) { - ALOGD("query err = %d", err); - return err; - } - C2BlockPool::local_id_t poolId = - outputFormat.value == C2FormatVideo - ? C2BlockPool::BASIC_GRAPHIC - : C2BlockPool::BASIC_LINEAR; - if (params.size()) { - C2PortBlockPoolsTuning::output *outputPools = - C2PortBlockPoolsTuning::output::From(params[0].get()); - if (outputPools && outputPools->flexCount() >= 1) { - poolId = outputPools->m.values[0]; - } - } - - err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool); - ALOGD("Using output block pool with poolID %llu => got %llu - %d", - (unsigned long long)poolId, - (unsigned long long)( - mOutputBlockPool ? mOutputBlockPool->getLocalId() : 111000111), - err); - return err; - }(); - if (err != C2_OK) { - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onError_nb(shared_from_this(), err); - return hasQueuedWork; - } - } - - if (!work) { - c2_status_t err = drain(drainMode, mOutputBlockPool); - if (err != C2_OK) { - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onError_nb(shared_from_this(), err); - } - return hasQueuedWork; - } - - { - std::vector<C2Param *> updates; - for (const std::unique_ptr<C2Param> ¶m: work->input.configUpdate) { - if (param) { - updates.emplace_back(param.get()); - } - } - if (!updates.empty()) { - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = intf()->config_vb(updates, C2_MAY_BLOCK, &failures); - ALOGD("applied %zu configUpdates => %s (%d)", updates.size(), asString(err), err); - } - } - - ALOGV("start processing frame #%" PRIu64, work->input.ordinal.frameIndex.peeku()); - // If input buffer list is not empty, it means we have some input to process on. - // However, input could be a null buffer. In such case, clear the buffer list - // before making call to process(). - if (!work->input.buffers.empty() && !work->input.buffers[0]) { - ALOGD("Encountered null input buffer. Clearing the input buffer"); - work->input.buffers.clear(); - } - process(work, mOutputBlockPool); - ALOGV("processed frame #%" PRIu64, work->input.ordinal.frameIndex.peeku()); - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - if (queue->generation() != generation) { - ALOGD("work form old generation: was %" PRIu64 " now %" PRIu64, - queue->generation(), generation); - work->result = C2_NOT_FOUND; - queue.unlock(); - { - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onWorkDone_nb(shared_from_this(), vec(work)); - } - queue.lock(); - return hasQueuedWork; - } - } - if (work->workletsProcessed != 0u) { - Mutexed<ExecState>::Locked state(mExecState); - ALOGV("returning this work"); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onWorkDone_nb(shared_from_this(), vec(work)); - } else { - ALOGV("queue pending work"); - work->input.buffers.clear(); - std::unique_ptr<C2Work> unexpected; - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - uint64_t frameIndex = work->input.ordinal.frameIndex.peeku(); - if (pending->count(frameIndex) != 0) { - unexpected = std::move(pending->at(frameIndex)); - pending->erase(frameIndex); - } - (void)pending->insert({ frameIndex, std::move(work) }); - } - if (unexpected) { - ALOGD("unexpected pending work"); - unexpected->result = C2_CORRUPTED; - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onWorkDone_nb(shared_from_this(), vec(unexpected)); - } - } - return hasQueuedWork; -} - -std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer( - const std::shared_ptr<C2LinearBlock> &block) { - return createLinearBuffer(block, block->offset(), block->size()); -} - -std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer( - const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size) { - return C2Buffer::CreateLinearBuffer(block->share(offset, size, ::C2Fence())); -} - -std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer( - const std::shared_ptr<C2GraphicBlock> &block) { - return createGraphicBuffer(block, C2Rect(block->width(), block->height())); -} - -std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer( - const std::shared_ptr<C2GraphicBlock> &block, const C2Rect &crop) { - return C2Buffer::CreateGraphicBuffer(block->share(crop, ::C2Fence())); -} - -} // namespace android diff --git a/media/codecs/base/SimpleC2Interface.cpp b/media/codecs/base/SimpleC2Interface.cpp deleted file mode 100644 index c849a4e..0000000 --- a/media/codecs/base/SimpleC2Interface.cpp +++ /dev/null @@ -1,315 +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 "SimpleC2Interface" -#include <utils/Log.h> - -// use MediaDefs here vs. MediaCodecConstants as this is not MediaCodec specific/dependent -#include <media/stagefright/foundation/MediaDefs.h> - -#include <SimpleC2Interface.h> - -namespace android { - -/* SimpleInterface */ - -SimpleInterface<void>::BaseParams::BaseParams( - const std::shared_ptr<C2ReflectorHelper> &reflector, - C2String name, - C2Component::kind_t kind, - C2Component::domain_t domain, - C2String mediaType, - std::vector<C2String> aliases) - : C2InterfaceHelper(reflector) { - setDerivedInstance(this); - - addParameter( - DefineParam(mName, C2_PARAMKEY_COMPONENT_NAME) - .withConstValue(AllocSharedString<C2ComponentNameSetting>(name.c_str())) - .build()); - - if (aliases.size()) { - C2String joined; - for (const C2String &alias : aliases) { - if (joined.length()) { - joined += ","; - } - joined += alias; - } - addParameter( - DefineParam(mAliases, C2_PARAMKEY_COMPONENT_ALIASES) - .withConstValue(AllocSharedString<C2ComponentAliasesSetting>(joined.c_str())) - .build()); - } - - addParameter( - DefineParam(mKind, C2_PARAMKEY_COMPONENT_KIND) - .withConstValue(new C2ComponentKindSetting(kind)) - .build()); - - addParameter( - DefineParam(mDomain, C2_PARAMKEY_COMPONENT_DOMAIN) - .withConstValue(new C2ComponentDomainSetting(domain)) - .build()); - - // simple interfaces have single streams - addParameter( - DefineParam(mInputStreamCount, C2_PARAMKEY_INPUT_STREAM_COUNT) - .withConstValue(new C2PortStreamCountTuning::input(1)) - .build()); - - addParameter( - DefineParam(mOutputStreamCount, C2_PARAMKEY_OUTPUT_STREAM_COUNT) - .withConstValue(new C2PortStreamCountTuning::output(1)) - .build()); - - // set up buffer formats and allocators - - // default to linear buffers and no media type - C2BufferData::type_t rawBufferType = C2BufferData::LINEAR; - C2String rawMediaType; - C2Allocator::id_t rawAllocator = C2AllocatorStore::DEFAULT_LINEAR; - C2BlockPool::local_id_t rawPoolId = C2BlockPool::BASIC_LINEAR; - C2BufferData::type_t codedBufferType = C2BufferData::LINEAR; - C2Allocator::id_t codedAllocator = C2AllocatorStore::DEFAULT_LINEAR; - C2BlockPool::local_id_t codedPoolId = C2BlockPool::BASIC_LINEAR; - - switch (domain) { - case C2Component::DOMAIN_IMAGE: - case C2Component::DOMAIN_VIDEO: - // TODO: should we define raw image? The only difference is timestamp handling - rawBufferType = C2BufferData::GRAPHIC; - rawMediaType = MEDIA_MIMETYPE_VIDEO_RAW; - rawAllocator = C2AllocatorStore::DEFAULT_GRAPHIC; - rawPoolId = C2BlockPool::BASIC_GRAPHIC; - break; - case C2Component::DOMAIN_AUDIO: - rawBufferType = C2BufferData::LINEAR; - rawMediaType = MEDIA_MIMETYPE_AUDIO_RAW; - rawAllocator = C2AllocatorStore::DEFAULT_LINEAR; - rawPoolId = C2BlockPool::BASIC_LINEAR; - break; - default: - break; - } - bool isEncoder = kind == C2Component::KIND_ENCODER; - - // handle raw decoders - if (mediaType == rawMediaType) { - codedBufferType = rawBufferType; - codedAllocator = rawAllocator; - codedPoolId = rawPoolId; - } - - addParameter( - DefineParam(mInputFormat, C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE) - .withConstValue(new C2StreamBufferTypeSetting::input( - 0u, isEncoder ? rawBufferType : codedBufferType)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE) - .withConstValue(AllocSharedString<C2PortMediaTypeSetting::input>( - isEncoder ? rawMediaType : mediaType)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_PARAMKEY_OUTPUT_STREAM_BUFFER_TYPE) - .withConstValue(new C2StreamBufferTypeSetting::output( - 0u, isEncoder ? codedBufferType : rawBufferType)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE) - .withConstValue(AllocSharedString<C2PortMediaTypeSetting::output>( - isEncoder ? mediaType : rawMediaType)) - .build()); - - C2Allocator::id_t inputAllocators[1] = { isEncoder ? rawAllocator : codedAllocator }; - C2Allocator::id_t outputAllocators[1] = { isEncoder ? codedAllocator : rawAllocator }; - C2BlockPool::local_id_t outputPoolIds[1] = { isEncoder ? codedPoolId : rawPoolId }; - - addParameter( - DefineParam(mInputAllocators, C2_PARAMKEY_INPUT_ALLOCATORS) - .withDefault(C2PortAllocatorsTuning::input::AllocShared(inputAllocators)) - .withFields({ C2F(mInputAllocators, m.values[0]).any(), - C2F(mInputAllocators, m.values).inRange(0, 1) }) - .withSetter(Setter<C2PortAllocatorsTuning::input>::NonStrictValuesWithNoDeps) - .build()); - - addParameter( - DefineParam(mOutputAllocators, C2_PARAMKEY_OUTPUT_ALLOCATORS) - .withDefault(C2PortAllocatorsTuning::output::AllocShared(outputAllocators)) - .withFields({ C2F(mOutputAllocators, m.values[0]).any(), - C2F(mOutputAllocators, m.values).inRange(0, 1) }) - .withSetter(Setter<C2PortAllocatorsTuning::output>::NonStrictValuesWithNoDeps) - .build()); - - addParameter( - DefineParam(mOutputPoolIds, C2_PARAMKEY_OUTPUT_BLOCK_POOLS) - .withDefault(C2PortBlockPoolsTuning::output::AllocShared(outputPoolIds)) - .withFields({ C2F(mOutputPoolIds, m.values[0]).any(), - C2F(mOutputPoolIds, m.values).inRange(0, 1) }) - .withSetter(Setter<C2PortBlockPoolsTuning::output>::NonStrictValuesWithNoDeps) - .build()); - - // add stateless params - addParameter( - DefineParam(mSubscribedParamIndices, C2_PARAMKEY_SUBSCRIBED_PARAM_INDICES) - .withDefault(C2SubscribedParamIndicesTuning::AllocShared(0u)) - .withFields({ C2F(mSubscribedParamIndices, m.values[0]).any(), - C2F(mSubscribedParamIndices, m.values).any() }) - .withSetter(Setter<C2SubscribedParamIndicesTuning>::NonStrictValuesWithNoDeps) - .build()); - - /* TODO - - addParameter( - DefineParam(mCurrentWorkOrdinal, C2_PARAMKEY_CURRENT_WORK) - .withDefault(new C2CurrentWorkTuning()) - .withFields({ C2F(mCurrentWorkOrdinal, m.timeStamp).any(), - C2F(mCurrentWorkOrdinal, m.frameIndex).any(), - C2F(mCurrentWorkOrdinal, m.customOrdinal).any() }) - .withSetter(Setter<C2CurrentWorkTuning>::NonStrictValuesWithNoDeps) - .build()); - - addParameter( - DefineParam(mLastInputQueuedWorkOrdinal, C2_PARAMKEY_LAST_INPUT_QUEUED) - .withDefault(new C2LastWorkQueuedTuning::input()) - .withFields({ C2F(mLastInputQueuedWorkOrdinal, m.timeStamp).any(), - C2F(mLastInputQueuedWorkOrdinal, m.frameIndex).any(), - C2F(mLastInputQueuedWorkOrdinal, m.customOrdinal).any() }) - .withSetter(Setter<C2LastWorkQueuedTuning::input>::NonStrictValuesWithNoDeps) - .build()); - - addParameter( - DefineParam(mLastOutputQueuedWorkOrdinal, C2_PARAMKEY_LAST_OUTPUT_QUEUED) - .withDefault(new C2LastWorkQueuedTuning::output()) - .withFields({ C2F(mLastOutputQueuedWorkOrdinal, m.timeStamp).any(), - C2F(mLastOutputQueuedWorkOrdinal, m.frameIndex).any(), - C2F(mLastOutputQueuedWorkOrdinal, m.customOrdinal).any() }) - .withSetter(Setter<C2LastWorkQueuedTuning::output>::NonStrictValuesWithNoDeps) - .build()); - - std::shared_ptr<C2OutOfMemoryTuning> mOutOfMemory; - - std::shared_ptr<C2PortConfigCounterTuning::input> mInputConfigCounter; - std::shared_ptr<C2PortConfigCounterTuning::output> mOutputConfigCounter; - std::shared_ptr<C2ConfigCounterTuning> mDirectConfigCounter; - - */ -} - -void SimpleInterface<void>::BaseParams::noInputLatency() { - addParameter( - DefineParam(mRequestedInputDelay, C2_PARAMKEY_INPUT_DELAY_REQUEST) - .withConstValue(new C2PortRequestedDelayTuning::input(0u)) - .build()); - - addParameter( - DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY) - .withConstValue(new C2PortActualDelayTuning::input(0u)) - .build()); -} - -void SimpleInterface<void>::BaseParams::noOutputLatency() { - addParameter( - DefineParam(mRequestedOutputDelay, C2_PARAMKEY_OUTPUT_DELAY_REQUEST) - .withConstValue(new C2PortRequestedDelayTuning::output(0u)) - .build()); - - addParameter( - DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY) - .withConstValue(new C2PortActualDelayTuning::output(0u)) - .build()); -} - -void SimpleInterface<void>::BaseParams::noPipelineLatency() { - addParameter( - DefineParam(mRequestedPipelineDelay, C2_PARAMKEY_PIPELINE_DELAY_REQUEST) - .withConstValue(new C2RequestedPipelineDelayTuning(0u)) - .build()); - - addParameter( - DefineParam(mActualPipelineDelay, C2_PARAMKEY_PIPELINE_DELAY) - .withConstValue(new C2ActualPipelineDelayTuning(0u)) - .build()); -} - -void SimpleInterface<void>::BaseParams::noPrivateBuffers() { - addParameter( - DefineParam(mPrivateAllocators, C2_PARAMKEY_PRIVATE_ALLOCATORS) - .withConstValue(C2PrivateAllocatorsTuning::AllocShared(0u)) - .build()); - - addParameter( - DefineParam(mMaxPrivateBufferCount, C2_PARAMKEY_MAX_PRIVATE_BUFFER_COUNT) - .withConstValue(C2MaxPrivateBufferCountTuning::AllocShared(0u)) - .build()); - - addParameter( - DefineParam(mPrivatePoolIds, C2_PARAMKEY_PRIVATE_BLOCK_POOLS) - .withConstValue(C2PrivateBlockPoolsTuning::AllocShared(0u)) - .build()); -} - -void SimpleInterface<void>::BaseParams::noInputReferences() { - addParameter( - DefineParam(mMaxInputReferenceAge, C2_PARAMKEY_INPUT_MAX_REFERENCE_AGE) - .withConstValue(new C2StreamMaxReferenceAgeTuning::input(0u)) - .build()); - - addParameter( - DefineParam(mMaxInputReferenceCount, C2_PARAMKEY_INPUT_MAX_REFERENCE_COUNT) - .withConstValue(new C2StreamMaxReferenceCountTuning::input(0u)) - .build()); -} - -void SimpleInterface<void>::BaseParams::noOutputReferences() { - addParameter( - DefineParam(mMaxOutputReferenceAge, C2_PARAMKEY_OUTPUT_MAX_REFERENCE_AGE) - .withConstValue(new C2StreamMaxReferenceAgeTuning::output(0u)) - .build()); - - addParameter( - DefineParam(mMaxOutputReferenceCount, C2_PARAMKEY_OUTPUT_MAX_REFERENCE_COUNT) - .withConstValue(new C2StreamMaxReferenceCountTuning::output(0u)) - .build()); -} - -void SimpleInterface<void>::BaseParams::noTimeStretch() { - addParameter( - DefineParam(mTimeStretch, C2_PARAMKEY_TIME_STRETCH) - .withConstValue(new C2ComponentTimeStretchTuning(1.f)) - .build()); -} - -/* - Clients need to handle the following base params due to custom dependency. - - std::shared_ptr<C2ApiLevelSetting> mApiLevel; - std::shared_ptr<C2ApiFeaturesSetting> mApiFeatures; - std::shared_ptr<C2ComponentAttributesSetting> mAttrib; - - std::shared_ptr<C2PortSuggestedBufferCountTuning::input> mSuggestedInputBufferCount; - std::shared_ptr<C2PortSuggestedBufferCountTuning::output> mSuggestedOutputBufferCount; - - std::shared_ptr<C2TrippedTuning> mTripped; - -*/ - -} // namespace android diff --git a/media/codecs/base/include/SimpleC2Component.h b/media/codecs/base/include/SimpleC2Component.h deleted file mode 100644 index b3a98f4..0000000 --- a/media/codecs/base/include/SimpleC2Component.h +++ /dev/null @@ -1,244 +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 SIMPLE_C2_COMPONENT_H_ -#define SIMPLE_C2_COMPONENT_H_ - -#include <list> -#include <unordered_map> - -#include <C2Component.h> - -#include <media/stagefright/foundation/AHandler.h> -#include <media/stagefright/foundation/ALooper.h> -#include <media/stagefright/foundation/Mutexed.h> - -namespace android { - -class SimpleC2Component - : public C2Component, public std::enable_shared_from_this<SimpleC2Component> { -public: - explicit SimpleC2Component( - const std::shared_ptr<C2ComponentInterface> &intf); - virtual ~SimpleC2Component(); - - // C2Component - // From C2Component - virtual c2_status_t setListener_vb( - const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) override; - virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override; - virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) override; - virtual c2_status_t flush_sm( - flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) override; - virtual c2_status_t drain_nb(drain_mode_t mode) override; - virtual c2_status_t start() override; - virtual c2_status_t stop() override; - virtual c2_status_t reset() override; - virtual c2_status_t release() override; - virtual std::shared_ptr<C2ComponentInterface> intf() override; - - // for handler - bool processQueue(); - -protected: - /** - * Initialize internal states of the component according to the config set - * in the interface. - * - * This method is called during start(), but only at the first invocation or - * after reset(). - */ - virtual c2_status_t onInit() = 0; - - /** - * Stop the component. - */ - virtual c2_status_t onStop() = 0; - - /** - * Reset the component. - */ - virtual void onReset() = 0; - - /** - * Release the component. - */ - virtual void onRelease() = 0; - - /** - * Flush the component. - */ - virtual c2_status_t onFlush_sm() = 0; - - /** - * Process the given work and finish pending work using finish(). - * - * \param[in,out] work the work to process - * \param[in] pool the pool to use for allocating output blocks. - */ - virtual void process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) = 0; - - /** - * Drain the component and finish pending work using finish(). - * - * \param[in] drainMode mode of drain. - * \param[in] pool the pool to use for allocating output blocks. - * - * \retval C2_OK The component has drained all pending output - * work. - * \retval C2_OMITTED Unsupported mode (e.g. DRAIN_CHAIN) - */ - virtual c2_status_t drain( - uint32_t drainMode, - const std::shared_ptr<C2BlockPool> &pool) = 0; - - // for derived classes - /** - * Finish pending work. - * - * This method will retrieve the pending work according to |frameIndex| and - * feed the work into |fillWork| function. |fillWork| must be - * "non-blocking". Once |fillWork| returns the filled work will be returned - * to the client. - * - * \param[in] frameIndex the index of the pending work - * \param[in] fillWork the function to fill the retrieved work. - */ - void finish(uint64_t frameIndex, std::function<void(const std::unique_ptr<C2Work> &)> fillWork); - - /** - * Clone pending or current work and send the work back to client. - * - * This method will retrieve and clone the pending or current work according - * to |frameIndex| and feed the work into |fillWork| function. |fillWork| - * must be "non-blocking". Once |fillWork| returns the filled work will be - * returned to the client. - * - * \param[in] frameIndex the index of the work - * \param[in] currentWork the current work under processing - * \param[in] fillWork the function to fill the retrieved work. - */ - void cloneAndSend( - uint64_t frameIndex, - const std::unique_ptr<C2Work> ¤tWork, - std::function<void(const std::unique_ptr<C2Work> &)> fillWork); - - - std::shared_ptr<C2Buffer> createLinearBuffer( - const std::shared_ptr<C2LinearBlock> &block); - - std::shared_ptr<C2Buffer> createLinearBuffer( - const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size); - - std::shared_ptr<C2Buffer> createGraphicBuffer( - const std::shared_ptr<C2GraphicBlock> &block); - - std::shared_ptr<C2Buffer> createGraphicBuffer( - const std::shared_ptr<C2GraphicBlock> &block, - const C2Rect &crop); - - static constexpr uint32_t NO_DRAIN = ~0u; - - C2ReadView mDummyReadView; - -private: - const std::shared_ptr<C2ComponentInterface> mIntf; - - class WorkHandler : public AHandler { - public: - enum { - kWhatProcess, - kWhatInit, - kWhatStart, - kWhatStop, - kWhatReset, - kWhatRelease, - }; - - WorkHandler(); - ~WorkHandler() override = default; - - void setComponent(const std::shared_ptr<SimpleC2Component> &thiz); - - protected: - void onMessageReceived(const sp<AMessage> &msg) override; - - private: - std::weak_ptr<SimpleC2Component> mThiz; - bool mRunning; - }; - - enum { - UNINITIALIZED, - STOPPED, - RUNNING, - }; - - struct ExecState { - ExecState() : mState(UNINITIALIZED) {} - - int mState; - std::shared_ptr<C2Component::Listener> mListener; - }; - Mutexed<ExecState> mExecState; - - sp<ALooper> mLooper; - sp<WorkHandler> mHandler; - - class WorkQueue { - public: - inline WorkQueue() : mFlush(false), mGeneration(0ul) {} - - inline uint64_t generation() const { return mGeneration; } - inline void incGeneration() { ++mGeneration; mFlush = true; } - - std::unique_ptr<C2Work> pop_front(); - void push_back(std::unique_ptr<C2Work> work); - bool empty() const; - uint32_t drainMode() const; - void markDrain(uint32_t drainMode); - inline bool popPendingFlush() { - bool flush = mFlush; - mFlush = false; - return flush; - } - void clear(); - - private: - struct Entry { - std::unique_ptr<C2Work> work; - uint32_t drainMode; - }; - - bool mFlush; - uint64_t mGeneration; - std::list<Entry> mQueue; - }; - Mutexed<WorkQueue> mWorkQueue; - - typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork; - Mutexed<PendingWork> mPendingWork; - - std::shared_ptr<C2BlockPool> mOutputBlockPool; - - SimpleC2Component() = delete; -}; - -} // namespace android - -#endif // SIMPLE_C2_COMPONENT_H_ diff --git a/media/codecs/base/include/SimpleC2Interface.h b/media/codecs/base/include/SimpleC2Interface.h deleted file mode 100644 index 2051d3d..0000000 --- a/media/codecs/base/include/SimpleC2Interface.h +++ /dev/null @@ -1,236 +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 ANDROID_SIMPLE_C2_INTERFACE_H_ -#define ANDROID_SIMPLE_C2_INTERFACE_H_ - -#include <C2Component.h> -#include <C2Config.h> -#include <util/C2InterfaceHelper.h> - -namespace android { - -/** - * Wrap a common interface object (such as Codec2Client::Interface, or C2InterfaceHelper into - * a C2ComponentInterface. - * - * \param T common interface type - */ -template <typename T> -class SimpleC2Interface : public C2ComponentInterface { -public: - SimpleC2Interface(const char *name, c2_node_id_t id, const std::shared_ptr<T> &impl) - : mName(name), - mId(id), - mImpl(impl) { - } - - ~SimpleC2Interface() override = default; - - // From C2ComponentInterface - C2String getName() const override { return mName; } - c2_node_id_t getId() const override { return mId; } - 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 { - return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams); - } - c2_status_t config_vb( - const std::vector<C2Param*> ¶ms, - c2_blocking_t mayBlock, - std::vector<std::unique_ptr<C2SettingResult>>* const failures) override { - return mImpl->config(params, mayBlock, failures); - } - c2_status_t createTunnel_sm(c2_node_id_t) override { return C2_OMITTED; } - c2_status_t releaseTunnel_sm(c2_node_id_t) override { return C2_OMITTED; } - c2_status_t querySupportedParams_nb( - std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override { - return mImpl->querySupportedParams(params); - } - c2_status_t querySupportedValues_vb( - std::vector<C2FieldSupportedValuesQuery> &fields, - c2_blocking_t mayBlock) const override { - return mImpl->querySupportedValues(fields, mayBlock); - } - -private: - C2String mName; - const c2_node_id_t mId; - const std::shared_ptr<T> mImpl; -}; - -/** - * Utility classes for common interfaces. - */ -template<> -class SimpleC2Interface<void> { -public: - /** - * Base Codec 2.0 parameters required for all components. - */ - struct BaseParams : C2InterfaceHelper { - explicit BaseParams( - const std::shared_ptr<C2ReflectorHelper> &helper, - C2String name, - C2Component::kind_t kind, - C2Component::domain_t domain, - C2String mediaType, - std::vector<C2String> aliases = std::vector<C2String>()); - - /// Marks that this component has no input latency. Otherwise, component must - /// add support for C2PortRequestedDelayTuning::input and C2PortActualDelayTuning::input. - void noInputLatency(); - - /// Marks that this component has no output latency. Otherwise, component must - /// add support for C2PortRequestedDelayTuning::output and C2PortActualDelayTuning::output. - void noOutputLatency(); - - /// Marks that this component has no pipeline latency. Otherwise, component must - /// add support for C2RequestedPipelineDelayTuning and C2ActualPipelineDelayTuning. - void noPipelineLatency(); - - /// Marks that this component has no need for private buffers. Otherwise, component must - /// add support for C2MaxPrivateBufferCountTuning, C2PrivateAllocatorsTuning and - /// C2PrivateBlockPoolsTuning. - void noPrivateBuffers(); - - /// Marks that this component holds no references to input buffers. Otherwise, component - /// must add support for C2StreamMaxReferenceAgeTuning::input and - /// C2StreamMaxReferenceCountTuning::input. - void noInputReferences(); - - /// Marks that this component holds no references to output buffers. Otherwise, component - /// must add support for C2StreamMaxReferenceAgeTuning::output and - /// C2StreamMaxReferenceCountTuning::output. - void noOutputReferences(); - - /// Marks that this component does not stretch time. Otherwise, component - /// must add support for C2ComponentTimeStretchTuning. - void noTimeStretch(); - - std::shared_ptr<C2ApiLevelSetting> mApiLevel; - std::shared_ptr<C2ApiFeaturesSetting> mApiFeatures; - - std::shared_ptr<C2PlatformLevelSetting> mPlatformLevel; - std::shared_ptr<C2PlatformFeaturesSetting> mPlatformFeatures; - - std::shared_ptr<C2ComponentNameSetting> mName; - std::shared_ptr<C2ComponentAliasesSetting> mAliases; - std::shared_ptr<C2ComponentKindSetting> mKind; - std::shared_ptr<C2ComponentDomainSetting> mDomain; - std::shared_ptr<C2ComponentAttributesSetting> mAttrib; - std::shared_ptr<C2ComponentTimeStretchTuning> mTimeStretch; - - std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType; - std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType; - std::shared_ptr<C2StreamBufferTypeSetting::input> mInputFormat; - std::shared_ptr<C2StreamBufferTypeSetting::output> mOutputFormat; - - std::shared_ptr<C2PortRequestedDelayTuning::input> mRequestedInputDelay; - std::shared_ptr<C2PortRequestedDelayTuning::output> mRequestedOutputDelay; - std::shared_ptr<C2RequestedPipelineDelayTuning> mRequestedPipelineDelay; - - std::shared_ptr<C2PortActualDelayTuning::input> mActualInputDelay; - std::shared_ptr<C2PortActualDelayTuning::output> mActualOutputDelay; - std::shared_ptr<C2ActualPipelineDelayTuning> mActualPipelineDelay; - - std::shared_ptr<C2StreamMaxReferenceAgeTuning::input> mMaxInputReferenceAge; - std::shared_ptr<C2StreamMaxReferenceCountTuning::input> mMaxInputReferenceCount; - std::shared_ptr<C2StreamMaxReferenceAgeTuning::output> mMaxOutputReferenceAge; - std::shared_ptr<C2StreamMaxReferenceCountTuning::output> mMaxOutputReferenceCount; - std::shared_ptr<C2MaxPrivateBufferCountTuning> mMaxPrivateBufferCount; - - std::shared_ptr<C2PortStreamCountTuning::input> mInputStreamCount; - std::shared_ptr<C2PortStreamCountTuning::output> mOutputStreamCount; - - std::shared_ptr<C2SubscribedParamIndicesTuning> mSubscribedParamIndices; - std::shared_ptr<C2PortSuggestedBufferCountTuning::input> mSuggestedInputBufferCount; - std::shared_ptr<C2PortSuggestedBufferCountTuning::output> mSuggestedOutputBufferCount; - - std::shared_ptr<C2CurrentWorkTuning> mCurrentWorkOrdinal; - std::shared_ptr<C2LastWorkQueuedTuning::input> mLastInputQueuedWorkOrdinal; - std::shared_ptr<C2LastWorkQueuedTuning::output> mLastOutputQueuedWorkOrdinal; - - std::shared_ptr<C2PortAllocatorsTuning::input> mInputAllocators; - std::shared_ptr<C2PortAllocatorsTuning::output> mOutputAllocators; - std::shared_ptr<C2PrivateAllocatorsTuning> mPrivateAllocators; - std::shared_ptr<C2PortBlockPoolsTuning::output> mOutputPoolIds; - std::shared_ptr<C2PrivateBlockPoolsTuning> mPrivatePoolIds; - - std::shared_ptr<C2TrippedTuning> mTripped; - std::shared_ptr<C2OutOfMemoryTuning> mOutOfMemory; - - std::shared_ptr<C2PortConfigCounterTuning::input> mInputConfigCounter; - std::shared_ptr<C2PortConfigCounterTuning::output> mOutputConfigCounter; - std::shared_ptr<C2ConfigCounterTuning> mDirectConfigCounter; - }; -}; - -template<typename T> -using SimpleInterface = SimpleC2Interface<T>; - -template<typename T, typename ...Args> -std::shared_ptr<T> AllocSharedString(const Args(&... args), const char *str) { - size_t len = strlen(str) + 1; - std::shared_ptr<T> ret = T::AllocShared(len, args...); - strcpy(ret->m.value, str); - return ret; -} - -template<typename T, typename ...Args> -std::shared_ptr<T> AllocSharedString(const Args(&... args), const std::string &str) { - std::shared_ptr<T> ret = T::AllocShared(str.length() + 1, args...); - strcpy(ret->m.value, str.c_str()); - return ret; -} - -template <typename T> -struct Setter { - typedef typename std::remove_reference<T>::type type; - - static C2R NonStrictValueWithNoDeps( - bool mayBlock, C2InterfaceHelper::C2P<type> &me) { - (void)mayBlock; - return me.F(me.v.value).validatePossible(me.v.value); - } - - static C2R NonStrictValuesWithNoDeps( - bool mayBlock, C2InterfaceHelper::C2P<type> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - for (size_t ix = 0; ix < me.v.flexCount(); ++ix) { - res.plus(me.F(me.v.m.values[ix]).validatePossible(me.v.m.values[ix])); - } - return res; - } - - static C2R StrictValueWithNoDeps( - bool mayBlock, - const C2InterfaceHelper::C2P<type> &old, - C2InterfaceHelper::C2P<type> &me) { - (void)mayBlock; - if (!me.F(me.v.value).supportsNow(me.v.value)) { - me.set().value = old.v.value; - } - return me.F(me.v.value).validatePossible(me.v.value); - } -}; - -} // namespace android - -#endif // ANDROID_SIMPLE_C2_INTERFACE_H_ diff --git a/media/codecs/cmds/Android.bp b/media/codecs/cmds/Android.bp deleted file mode 100644 index 69142e8..0000000 --- a/media/codecs/cmds/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -cc_binary { - name: "codec2", - defaults: ["libstagefright_codec2-impl-defaults"], - - srcs: [ - "codec2.cpp", - ], - - include_dirs: [ - ], - - shared_libs: [ - "libbase", - "libbinder", - "libcutils", - "libdatasource", - "libgui", - "liblog", - "libstagefright", - "libstagefright_foundation", - "libui", - "libutils", - ], - - cflags: [ - "-Werror", - "-Wall", - ], - - sanitize: { - cfi: true, - misc_undefined: [ - "unsigned-integer-overflow", - "signed-integer-overflow", - ], - }, -} diff --git a/media/codecs/cmds/codec2.cpp b/media/codecs/cmds/codec2.cpp deleted file mode 100644 index 2cbbcd8..0000000 --- a/media/codecs/cmds/codec2.cpp +++ /dev/null @@ -1,482 +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 <log/log.h> - -#include <binder/IServiceManager.h> -#include <binder/ProcessState.h> -#include <datasource/DataSourceFactory.h> -#include <media/DataSource.h> -#include <media/IMediaHTTPService.h> -#include <media/stagefright/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/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 <C2AllocatorGralloc.h> -#include <C2Buffer.h> -#include <C2BufferPriv.h> -#include <C2Component.h> -#include <C2Config.h> -#include <C2Debug.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 != nullptr); - CHECK(mControl->isValid()); - - SurfaceComposerClient::Transaction{} - .setLayer(mControl, INT_MAX) - .show(mControl) - .apply(); - - mSurface = mControl->getSurface(); - CHECK(mSurface != nullptr); - 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.android.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 == nullptr); - - 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 = nullptr; - } - - ++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::getInstance()->CreateFromURI(nullptr /* httpService */, filename); - - if (strncasecmp(filename, "sine:", 5) && dataSource == nullptr) { - 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 == nullptr) { - fprintf(stderr, "could not create extractor.\n"); - return -1; - } - - sp<MetaData> meta = extractor->getMetaData(); - - if (meta != nullptr) { - 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, 0); - - if (meta == nullptr) { - break; - } - const char *mime; - meta->findCString(kKeyMIMEType, &mime); - - // TODO: allowing AVC only for the time being - if (!strncasecmp(mime, "video/avc", 9)) { - break; - } - - meta = nullptr; - } - - if (meta == nullptr) { - 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/codecs/flac/Android.bp b/media/codecs/flac/Android.bp deleted file mode 100644 index 32c3b36..0000000 --- a/media/codecs/flac/Android.bp +++ /dev/null @@ -1,27 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2flacdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - header_libs: ["libFLAC-headers"], - - srcs: ["C2SoftFlacDec.cpp"], - - shared_libs: [ - "libstagefright_flacdec", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2flacenc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftFlacEnc.cpp"], - - static_libs: ["libFLAC"], -} diff --git a/media/codecs/flac/C2SoftFlacDec.cpp b/media/codecs/flac/C2SoftFlacDec.cpp deleted file mode 100644 index f1e2f51..0000000 --- a/media/codecs/flac/C2SoftFlacDec.cpp +++ /dev/null @@ -1,372 +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 "C2SoftFlacDec" -#include <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftFlacDec.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.flac.decoder"; - -class C2SoftFlacDec::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_FLAC)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 44100)) - .withFields({C2F(mSampleRate, value).inRange(1, 655350)}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).inRange(1, 8)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 768000)) - .withFields({C2F(mBitrate, value).inRange(1, 21000000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 32768)) - .build()); - } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftFlacDec::C2SoftFlacDec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mFLACDecoder(nullptr) { -} - -C2SoftFlacDec::~C2SoftFlacDec() { - onRelease(); -} - -c2_status_t C2SoftFlacDec::onInit() { - status_t err = initDecoder(); - return err == OK ? C2_OK : C2_NO_MEMORY; -} - -c2_status_t C2SoftFlacDec::onStop() { - if (mFLACDecoder) mFLACDecoder->flush(); - memset(&mStreamInfo, 0, sizeof(mStreamInfo)); - mHasStreamInfo = false; - mSignalledError = false; - mSignalledOutputEos = false; - return C2_OK; -} - -void C2SoftFlacDec::onReset() { - mInputBufferCount = 0; - (void)onStop(); -} - -void C2SoftFlacDec::onRelease() { - mInputBufferCount = 0; - if (mFLACDecoder) delete mFLACDecoder; - mFLACDecoder = nullptr; -} - -c2_status_t C2SoftFlacDec::onFlush_sm() { - return onStop(); -} - -status_t C2SoftFlacDec::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 C2SoftFlacDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - C2ReadView rView = mDummyReadView; - size_t inOffset = 0u; - size_t inSize = 0u; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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.sample_rate && mStreamInfo.max_blocksize && - mStreamInfo.channels) { - mHasStreamInfo = true; - C2StreamSampleRateInfo::output sampleRateInfo( - 0u, mStreamInfo.sample_rate); - C2StreamChannelCountInfo::output channelCountInfo( - 0u, mStreamInfo.channels); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = - mIntf->config({&sampleRateInfo, &channelCountInfo}, - C2_MAY_BLOCK, &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(sampleRateInfo)); - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(channelCountInfo)); - } else { - ALOGE("Config Update failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - 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; - if (eos) { - mSignalledOutputEos = true; - ALOGV("signalled EOS"); - } -} - -c2_status_t C2SoftFlacDec::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: - C2SoftFlacDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftFlacDec(COMPONENT_NAME, - id, - std::make_shared<C2SoftFlacDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftFlacDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftFlacDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftFlacDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/flac/C2SoftFlacDec.h b/media/codecs/flac/C2SoftFlacDec.h deleted file mode 100644 index b491bfd..0000000 --- a/media/codecs/flac/C2SoftFlacDec.h +++ /dev/null @@ -1,66 +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 ANDROID_C2_SOFT_FLAC_DEC_H_ -#define ANDROID_C2_SOFT_FLAC_DEC_H_ - -#include <SimpleC2Component.h> - -#include "FLACDecoder.h" - -namespace android { - -struct C2SoftFlacDec : public SimpleC2Component { - class IntfImpl; - - C2SoftFlacDec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl); - virtual ~C2SoftFlacDec(); - - // 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 - }; - - std::shared_ptr<IntfImpl> mIntf; - FLACDecoder *mFLACDecoder; - FLAC__StreamMetadata_StreamInfo mStreamInfo; - bool mSignalledError; - bool mSignalledOutputEos; - bool mHasStreamInfo; - size_t mInputBufferCount; - - status_t initDecoder(); - - C2_DO_NOT_COPY(C2SoftFlacDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_FLAC_DEC_H_ diff --git a/media/codecs/flac/C2SoftFlacEnc.cpp b/media/codecs/flac/C2SoftFlacEnc.cpp deleted file mode 100644 index e4192c7..0000000 --- a/media/codecs/flac/C2SoftFlacEnc.cpp +++ /dev/null @@ -1,460 +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 <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftFlacEnc.h" - -namespace android { - -class C2SoftFlacEnc::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - setDerivedInstance(this); - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatAudio)) - .build()); - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatCompressed)) - .build()); - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_FLAC)) - .build()); - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::input(0u, 44100)) - .withFields({C2F(mSampleRate, value).inRange(1, 655350)}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::input(0u, 1)) - .withFields({C2F(mChannelCount, value).inRange(1, 2)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::output(0u, 768000)) - .withFields({C2F(mBitrate, value).inRange(1, 21000000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 4608)) - .build()); - } - - uint32_t getSampleRate() const { return mSampleRate->value; } - uint32_t getChannelCount() const { return mChannelCount->value; } - uint32_t getBitrate() const { return mBitrate->value; } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount; - std::shared_ptr<C2BitrateTuning::output> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; -constexpr char COMPONENT_NAME[] = "c2.android.flac.encoder"; - -C2SoftFlacEnc::C2SoftFlacEnc( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - 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; - mCompressionLevel = FLAC_COMPRESSION_LEVEL_DEFAULT; - mIsFirstFrame = true; - mAnchorTimeStamp = 0ull; - mProcessedSamples = 0u; - mEncoderWriteData = false; - mEncoderReturnedNbBytes = 0; - mHeaderOffset = 0; - mWroteHeader = false; - - 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() { - 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; - mHeaderOffset = 0; - mWroteHeader = false; - - 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; -} - -void C2SoftFlacEnc::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - C2ReadView rView = mDummyReadView; - size_t inOffset = 0u; - size_t inSize = 0u; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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; - } - - if (!mWroteHeader) { - std::unique_ptr<C2StreamCsdInfo::output> csd = - C2StreamCsdInfo::output::AllocUnique(mHeaderOffset, 0u); - if (!csd) { - ALOGE("CSD allocation failed"); - mSignalledError = true; - work->result = C2_NO_MEMORY; - return; - } - memcpy(csd->m.value, mHeader, mHeaderOffset); - ALOGV("put csd, %d bytes", mHeaderOffset); - - work->worklets.front()->output.configUpdate.push_back(std::move(csd)); - mWroteHeader = true; - } - - uint32_t sampleRate = mIntf->getSampleRate(); - uint32_t channelCount = mIntf->getChannelCount(); - uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate; - - size_t outCapacity = inSize; - outCapacity += mBlockSize * channelCount * sizeof(int16_t); - - 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; - while (inPos < inSize) { - const uint8_t *inPtr = rView.data() + inOffset; - size_t processSize = MIN(kInBlockSize * channelCount * sizeof(int16_t), (inSize - inPos)); - const unsigned nbInputFrames = processSize / (channelCount * 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 && (C2_OK != 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); - - 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; - } - - 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(); - 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__, mIntf->getChannelCount(), mIntf->getSampleRate()); - - 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, mIntf->getChannelCount()); - ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mIntf->getSampleRate()); - 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: - C2SoftFlacEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftFlacEnc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftFlacEnc::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftFlacEnc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftFlacEncFactory() override = default; -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/flac/C2SoftFlacEnc.h b/media/codecs/flac/C2SoftFlacEnc.h deleted file mode 100644 index cdf305e..0000000 --- a/media/codecs/flac/C2SoftFlacEnc.h +++ /dev/null @@ -1,89 +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 ANDROID_C2_SOFT_FLAC_ENC_H_ -#define ANDROID_C2_SOFT_FLAC_ENC_H_ - -#include <SimpleC2Component.h> - -#include "FLAC/stream_encoder.h" - -#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: - class IntfImpl; - - C2SoftFlacEnc(const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl); - 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); - - std::shared_ptr<IntfImpl> mIntf; - 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 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; - unsigned mHeaderOffset; - bool mWroteHeader; - char mHeader[FLAC_HEADER_SIZE]; - - C2_DO_NOT_COPY(C2SoftFlacEnc); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_FLAC_ENC_H_ diff --git a/media/codecs/flac/MODULE_LICENSE_APACHE2 b/media/codecs/flac/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/flac/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/flac/NOTICE b/media/codecs/flac/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/flac/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/g711/Android.bp b/media/codecs/g711/Android.bp deleted file mode 100644 index 56cbc20..0000000 --- a/media/codecs/g711/Android.bp +++ /dev/null @@ -1,23 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2g711alawdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftG711Dec.cpp"], - - cflags: [ - "-DALAW", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2g711mlawdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftG711Dec.cpp"], -} diff --git a/media/codecs/g711/C2SoftG711Dec.cpp b/media/codecs/g711/C2SoftG711Dec.cpp deleted file mode 100644 index 1c71d45..0000000 --- a/media/codecs/g711/C2SoftG711Dec.cpp +++ /dev/null @@ -1,323 +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 "C2SoftG711Dec" -#include <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftG711Dec.h" - -namespace android { - -#ifdef ALAW -constexpr char COMPONENT_NAME[] = "c2.android.g711.alaw.decoder"; -#else -constexpr char COMPONENT_NAME[] = "c2.android.g711.mlaw.decoder"; -#endif - -class C2SoftG711Dec::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( -#ifdef ALAW - MEDIA_MIMETYPE_AUDIO_G711_ALAW -#else - MEDIA_MIMETYPE_AUDIO_G711_MLAW -#endif - )).build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 8000)) - .withFields({C2F(mSampleRate, value).inRange(8000, 48000)}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).equalTo(1)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 64000)) - .withFields({C2F(mBitrate, value).equalTo(64000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .build()); - } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftG711Dec::C2SoftG711Dec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl) { -} - -C2SoftG711Dec::~C2SoftG711Dec() { - onRelease(); -} - -c2_status_t C2SoftG711Dec::onInit() { - mSignalledOutputEos = false; - return C2_OK; -} - -c2_status_t C2SoftG711Dec::onStop() { - mSignalledOutputEos = false; - return C2_OK; -} - -void C2SoftG711Dec::onReset() { - (void)onStop(); -} - -void C2SoftG711Dec::onRelease() { -} - -c2_status_t C2SoftG711Dec::onFlush_sm() { - return onStop(); -} - -void C2SoftG711Dec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - C2ReadView rView = mDummyReadView; - size_t inOffset = 0u; - size_t inSize = 0u; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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; - int outSize = inSize * sizeof(int16_t); - - 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; - 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; - - if (eos) { - mSignalledOutputEos = true; - ALOGV("signalled EOS"); - } -} - -c2_status_t C2SoftG711Dec::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 C2SoftG711Dec::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 C2SoftG711Dec::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: - C2SoftG711DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftG711Dec(COMPONENT_NAME, id, - std::make_shared<C2SoftG711Dec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftG711Dec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftG711Dec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftG711DecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/g711/C2SoftG711Dec.h b/media/codecs/g711/C2SoftG711Dec.h deleted file mode 100644 index 23e8ffc..0000000 --- a/media/codecs/g711/C2SoftG711Dec.h +++ /dev/null @@ -1,59 +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 ANDROID_C2_SOFT_G711_DEC_H_ -#define ANDROID_C2_SOFT_G711_DEC_H_ - -#include <SimpleC2Component.h> - - -namespace android { - -struct C2SoftG711Dec : public SimpleC2Component { - class IntfImpl; - - C2SoftG711Dec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl); - virtual ~C2SoftG711Dec(); - - // 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: - std::shared_ptr<IntfImpl> mIntf; - 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 - - C2_DO_NOT_COPY(C2SoftG711Dec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_G711_DEC_H_ diff --git a/media/codecs/g711/MODULE_LICENSE_APACHE2 b/media/codecs/g711/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/g711/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/g711/NOTICE b/media/codecs/g711/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/g711/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/gsm/Android.bp b/media/codecs/gsm/Android.bp deleted file mode 100644 index 8075747..0000000 --- a/media/codecs/gsm/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2gsmdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftGsmDec.cpp"], - - static_libs: ["libgsm"], -} diff --git a/media/codecs/gsm/C2SoftGsmDec.cpp b/media/codecs/gsm/C2SoftGsmDec.cpp deleted file mode 100644 index 7101c79..0000000 --- a/media/codecs/gsm/C2SoftGsmDec.cpp +++ /dev/null @@ -1,311 +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 "C2SoftGsmDec" -#include <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftGsmDec.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.gsm.decoder"; - -class C2SoftGsmDec::IntfImpl : public C2InterfaceHelper { - public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper) - : C2InterfaceHelper(helper) { - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_MSGSM)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 8000)) - .withFields({C2F(mSampleRate, value).equalTo(8000)}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).equalTo(1)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 13200)) - .withFields({C2F(mBitrate, value).equalTo(13200)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 1024 / MSGSM_IN_FRM_SZ * MSGSM_IN_FRM_SZ)) - .build()); - } - - private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftGsmDec::C2SoftGsmDec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : SimpleC2Component( - std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mGsm(nullptr) { -} - -C2SoftGsmDec::~C2SoftGsmDec() { - onRelease(); -} - -c2_status_t C2SoftGsmDec::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 C2SoftGsmDec::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 C2SoftGsmDec::onReset() { - (void)onStop(); -} - -void C2SoftGsmDec::onRelease() { - if (mGsm) { - gsm_destroy(mGsm); - mGsm = nullptr; - } -} - -c2_status_t C2SoftGsmDec::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 C2SoftGsmDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledEos) { - work->result = C2_BAD_VALUE; - return; - } - - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - C2ReadView rView = mDummyReadView; - size_t inOffset = 0u; - size_t inSize = 0u; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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; - 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; - if (eos) { - mSignalledEos = true; - ALOGV("signalled EOS"); - } -} - -c2_status_t C2SoftGsmDec::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: - C2SoftGSMDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftGsmDec(COMPONENT_NAME, - id, - std::make_shared<C2SoftGsmDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftGsmDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftGsmDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftGSMDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/gsm/C2SoftGsmDec.h b/media/codecs/gsm/C2SoftGsmDec.h deleted file mode 100644 index 2b209fe..0000000 --- a/media/codecs/gsm/C2SoftGsmDec.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 ANDROID_C2_SOFT_GSM_DEC_H_ -#define ANDROID_C2_SOFT_GSM_DEC_H_ - -#include <SimpleC2Component.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 C2SoftGsmDec : public SimpleC2Component { - class IntfImpl; - - C2SoftGsmDec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl); - virtual ~C2SoftGsmDec(); - - // 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: - std::shared_ptr<IntfImpl> mIntf; - gsm mGsm; - bool mSignalledError; - bool mSignalledEos; - - C2_DO_NOT_COPY(C2SoftGsmDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_GSM_DEC_H_ diff --git a/media/codecs/gsm/MODULE_LICENSE_APACHE2 b/media/codecs/gsm/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/gsm/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/gsm/NOTICE b/media/codecs/gsm/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/gsm/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/hevc/Android.bp b/media/codecs/hevc/Android.bp deleted file mode 100644 index 519de68..0000000 --- a/media/codecs/hevc/Android.bp +++ /dev/null @@ -1,16 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2hevcdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - srcs: ["C2SoftHevcDec.cpp"], - - static_libs: ["libhevcdec"], - - include_dirs: [ - "external/libhevc/decoder", - "external/libhevc/common", - ], -} diff --git a/media/codecs/hevc/C2SoftHevcDec.cpp b/media/codecs/hevc/C2SoftHevcDec.cpp deleted file mode 100644 index 99892ce..0000000 --- a/media/codecs/hevc/C2SoftHevcDec.cpp +++ /dev/null @@ -1,976 +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 <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <Codec2Mapper.h> -#include <SimpleC2Interface.h> - -#include "C2SoftHevcDec.h" -#include "ihevcd_cxa.h" - -namespace android { - -namespace { - -constexpr char COMPONENT_NAME[] = "c2.android.hevc.decoder"; - -} // namespace - -class C2SoftHevcDec::IntfImpl : public SimpleInterface<void>::BaseParams { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : SimpleInterface<void>::BaseParams( - helper, - COMPONENT_NAME, - C2Component::KIND_DECODER, - C2Component::DOMAIN_VIDEO, - MEDIA_MIMETYPE_VIDEO_HEVC) { - noPrivateBuffers(); // TODO: account for our buffers here - noInputReferences(); - noOutputReferences(); - noInputLatency(); - noTimeStretch(); - - // TODO: output latency and reordering - - addParameter( - DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES) - .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL)) - .build()); - - addParameter( - DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE) - .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 4096, 2), - C2F(mSize, height).inRange(2, 4096, 2), - }) - .withSetter(SizeSetter) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_HEVC_MAIN, C2Config::LEVEL_HEVC_MAIN_5_1)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_HEVC_MAIN, - C2Config::PROFILE_HEVC_MAIN_STILL}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_HEVC_MAIN_1, - C2Config::LEVEL_HEVC_MAIN_2, C2Config::LEVEL_HEVC_MAIN_2_1, - C2Config::LEVEL_HEVC_MAIN_3, C2Config::LEVEL_HEVC_MAIN_3_1, - C2Config::LEVEL_HEVC_MAIN_4, C2Config::LEVEL_HEVC_MAIN_4_1, - C2Config::LEVEL_HEVC_MAIN_5, C2Config::LEVEL_HEVC_MAIN_5_1, - C2Config::LEVEL_HEVC_MAIN_5_2, C2Config::LEVEL_HEVC_HIGH_4, - C2Config::LEVEL_HEVC_HIGH_4_1, C2Config::LEVEL_HEVC_HIGH_5, - C2Config::LEVEL_HEVC_HIGH_5_1, C2Config::LEVEL_HEVC_HIGH_5_2 - }) - }) - .withSetter(ProfileLevelSetter, mSize) - .build()); - - addParameter( - DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE) - .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 4096, 2), - C2F(mSize, height).inRange(2, 4096, 2), - }) - .withSetter(MaxPictureSizeSetter, mSize) - .build()); - - addParameter( - DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4)) - .withFields({ - C2F(mMaxInputSize, value).any(), - }) - .calculatedAs(MaxInputSizeSetter, mMaxSize) - .build()); - - C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() }; - std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - 1u, 0u, 8u /* bitDepth */, C2Color::YUV_420); - memcpy(defaultColorInfo->m.locations, locations, sizeof(locations)); - - defaultColorInfo = C2StreamColorInfo::output::AllocShared( - {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */, - C2Color::YUV_420); - helper->addStructDescriptors<C2ChromaOffsetStruct>(); - - addParameter( - DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO) - .withConstValue(defaultColorInfo) - .build()); - - addParameter( - DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsTuning::output( - 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mDefaultColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mDefaultColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mDefaultColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mDefaultColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(DefaultColorAspectsSetter) - .build()); - - addParameter( - DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsInfo::input( - 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mCodedColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mCodedColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mCodedColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mCodedColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(CodedColorAspectsSetter) - .build()); - - addParameter( - DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsInfo::output( - 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects) - .build()); - - // TODO: support more formats? - addParameter( - DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT) - .withConstValue(new C2StreamPixelFormatInfo::output( - 0u, HAL_PIXEL_FORMAT_YCBCR_420_888)) - .build()); - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe, - C2P<C2VideoSizeStreamInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - // TODO: get max width/height from the size's field helpers vs. hardcoding - me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u); - me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u); - return C2R::Ok(); - } - - static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me, - const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) { - (void)mayBlock; - // assume compression ratio of 2 - me.set().value = (((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072); - return C2R::Ok(); - } - - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - (void)size; - (void)me; // TODO: validate - return C2R::Ok(); - } - - static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) { - (void)mayBlock; - if (me.v.range > C2Color::RANGE_OTHER) { - me.set().range = C2Color::RANGE_OTHER; - } - if (me.v.primaries > C2Color::PRIMARIES_OTHER) { - me.set().primaries = C2Color::PRIMARIES_OTHER; - } - if (me.v.transfer > C2Color::TRANSFER_OTHER) { - me.set().transfer = C2Color::TRANSFER_OTHER; - } - if (me.v.matrix > C2Color::MATRIX_OTHER) { - me.set().matrix = C2Color::MATRIX_OTHER; - } - return C2R::Ok(); - } - - static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) { - (void)mayBlock; - if (me.v.range > C2Color::RANGE_OTHER) { - me.set().range = C2Color::RANGE_OTHER; - } - if (me.v.primaries > C2Color::PRIMARIES_OTHER) { - me.set().primaries = C2Color::PRIMARIES_OTHER; - } - if (me.v.transfer > C2Color::TRANSFER_OTHER) { - me.set().transfer = C2Color::TRANSFER_OTHER; - } - if (me.v.matrix > C2Color::MATRIX_OTHER) { - me.set().matrix = C2Color::MATRIX_OTHER; - } - return C2R::Ok(); - } - - static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me, - const C2P<C2StreamColorAspectsTuning::output> &def, - const C2P<C2StreamColorAspectsInfo::input> &coded) { - (void)mayBlock; - // take default values for all unspecified fields, and coded values for specified ones - me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range; - me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED - ? def.v.primaries : coded.v.primaries; - me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED - ? def.v.transfer : coded.v.transfer; - me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix; - return C2R::Ok(); - } - - std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() { - return mColorAspects; - } - -private: - std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; - std::shared_ptr<C2StreamPictureSizeInfo::output> mSize; - std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize; - std::shared_ptr<C2StreamColorInfo::output> mColorInfo; - std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects; - std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects; - std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects; - std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat; -}; - -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, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mDecHandle(nullptr), - mOutBufferFlush(nullptr), - mIvColorformat(IV_YUV_420P), - mWidth(320), - mHeight(240), - mHeaderDecoded(false) { -} - -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; - } - } - - if (mOutBufferFlush) { - 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_VIDEO_DECODE_MODE_T dec_mode) { - 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 = dec_mode; - 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; - resetPlugin(); - (void) setNumCores(); - if (OK != setParams(mStride, IVD_DECODE_FRAME)) 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::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; - } - - VuiColorAspects vuiColorAspects; - vuiColorAspects.primaries = s_get_vui_params_op.u1_colour_primaries; - vuiColorAspects.transfer = s_get_vui_params_op.u1_transfer_characteristics; - vuiColorAspects.coeffs = s_get_vui_params_op.u1_matrix_coefficients; - vuiColorAspects.fullRange = s_get_vui_params_op.u1_video_full_range_flag; - - // convert vui aspects to C2 values if changed - if (!(vuiColorAspects == mBitstreamColorAspects)) { - mBitstreamColorAspects = vuiColorAspects; - ColorAspects sfAspects; - C2StreamColorAspectsInfo::input codedAspects = { 0u }; - ColorUtils::convertIsoColorAspectsToCodecAspects( - vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs, - vuiColorAspects.fullRange, sfAspects); - if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) { - codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) { - codedAspects.range = C2Color::RANGE_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) { - codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) { - codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED; - } - std::vector<std::unique_ptr<C2SettingResult>> failures; - (void)mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures); - } - 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; - mHeaderDecoded = 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; - { - IntfImpl::Lock lock = mIntf->lock(); - buffer->setInfo(mIntf->getColorAspects_l()); - } - - auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) { - work->worklets.front()->output.flags = (C2FrameData::flags_t)0; - 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, IVD_DECODE_FRAME)) 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 0u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - size_t inOffset = 0u; - size_t inSize = 0u; - uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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->workletsProcessed = 1u; - 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->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } - - if (false == mHeaderDecoded) { - /* Decode header and get dimensions */ - setParams(mStride, IVD_DECODE_HEADER); - } - WORD32 delay; - GETTIME(&mTimeStart, nullptr); - 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"); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & 0xFF)) { - ALOGE("unsupported resolution : %dx%d", mWidth, mHeight); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - 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(); - work->workletsProcessed = 0u; - - /* Decode header and get new dimensions */ - setParams(mStride, IVD_DECODE_HEADER); - (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op); - } - if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) { - if (mHeaderDecoded == false) { - mHeaderDecoded = true; - setParams(ALIGN64(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME); - } - 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); - - C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = - mIntf->config({&size}, C2_MAY_BLOCK, &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(size)); - } else { - ALOGE("Cannot set width and height"); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } - continue; - } - } - (void) getVuiParams(); - hasPicture |= (1 == s_decode_op.u4_frame_decoded_flag); - if (s_decode_op.u4_output_present) { - finishWork(s_decode_op.u4_ts, work); - } - if (0 == s_decode_op.u4_num_bytes_consumed) { - ALOGD("Bytes consumed is zero. Ignoring remaining bytes"); - break; - } - 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->workletsProcessed = 1u; - 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; - work->workletsProcessed = 1u; - 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 { - fillEmptyWork(work); - break; - } - } - - 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: - C2SoftHevcDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftHevcDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftHevcDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftHevcDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftHevcDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/hevc/C2SoftHevcDec.h b/media/codecs/hevc/C2SoftHevcDec.h deleted file mode 100644 index 75111fc..0000000 --- a/media/codecs/hevc/C2SoftHevcDec.h +++ /dev/null @@ -1,152 +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 ANDROID_C2_SOFT_HEVC_DEC_H_ -#define ANDROID_C2_SOFT_HEVC_DEC_H_ - -#include <media/stagefright/foundation/ColorUtils.h> - -#include <SimpleC2Component.h> - -#include "ihevc_typedefs.h" -#include "iv.h" -#include "ivd.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 { - class IntfImpl; - - C2SoftHevcDec(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - 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, IVD_VIDEO_DECODE_MODE_T dec_mode); - 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, - }; - - std::shared_ptr<IntfImpl> mIntf; - 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; - bool mHeaderDecoded; - - // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid - // converting them to C2 values for each frame - struct VuiColorAspects { - uint8_t primaries; - uint8_t transfer; - uint8_t coeffs; - uint8_t fullRange; - - // default color aspects - VuiColorAspects() - : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - - bool operator==(const VuiColorAspects &o) { - return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs - && fullRange == o.fullRange; - } - } mBitstreamColorAspects; - - // profile - struct timeval mTimeStart; - struct timeval mTimeEnd; - - C2_DO_NOT_COPY(C2SoftHevcDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_HEVC_DEC_H_ diff --git a/media/codecs/mp3/Android.bp b/media/codecs/mp3/Android.bp deleted file mode 100644 index 6e013b8..0000000 --- a/media/codecs/mp3/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2mp3dec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftMp3Dec.cpp"], - - static_libs: ["libstagefright_mp3dec"], -} diff --git a/media/codecs/mp3/C2SoftMp3Dec.cpp b/media/codecs/mp3/C2SoftMp3Dec.cpp deleted file mode 100644 index c8b8397..0000000 --- a/media/codecs/mp3/C2SoftMp3Dec.cpp +++ /dev/null @@ -1,558 +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 "C2SoftMp3Dec" -#include <log/log.h> - -#include <numeric> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftMp3Dec.h" -#include "pvmp3decoder_api.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.mp3.decoder"; - -class C2SoftMP3::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_MPEG)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 44100)) - .withFields({C2F(mSampleRate, value).oneOf({8000, 11025, 12000, 16000, - 22050, 24000, 32000, 44100, 48000})}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 2)) - .withFields({C2F(mChannelCount, value).inRange(1, 2)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(8000, 320000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .build()); - } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - 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() { - mGaplessBytes = false; - 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); - - mIsFirst = true; - mGaplessBytes = false; - 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - size_t inSize = 0u; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - if (inSize && rView.error()) { - ALOGE("read view map failed %d", rView.error()); - work->result = rView.error(); - return; - } - } - - if (inSize == 0 && (!mGaplessBytes || !eos)) { - work->worklets.front()->output.flags = work->input.flags; - work->worklets.front()->output.buffers.clear(); - work->worklets.front()->output.ordinal = work->input.ordinal; - return; - } - ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize, - (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku()); - - int32_t numChannels = mConfig->num_channels; - size_t calOutSize; - std::vector<size_t> decodedSizes; - if (inSize && OK != calculateOutSize(const_cast<uint8 *>(rView.data()), - inSize, &decodedSizes)) { - work->result = C2_CORRUPTED; - return; - } - calOutSize = std::accumulate(decodedSizes.begin(), decodedSizes.end(), 0); - if (eos) { - calOutSize += kPVMP3DecoderDelay * numChannels * 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; - } - - int outSize = 0; - int outOffset = 0; - auto it = decodedSizes.begin(); - size_t inPos = 0; - int32_t samplingRate = mConfig->samplingRate; - while (inPos < inSize) { - if (it == decodedSizes.end()) { - ALOGE("unexpected trailing bytes, ignoring them"); - break; - } - - mConfig->pInputBuffer = const_cast<uint8 *>(rView.data() + 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 != samplingRate - || mConfig->num_channels != numChannels) { - ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", - samplingRate, mConfig->samplingRate, - numChannels, mConfig->num_channels); - samplingRate = mConfig->samplingRate; - numChannels = mConfig->num_channels; - - C2StreamSampleRateInfo::output sampleRateInfo(0u, samplingRate); - C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config( - { &sampleRateInfo, &channelCountInfo }, - C2_MAY_BLOCK, - &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(sampleRateInfo)); - work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(channelCountInfo)); - } else { - ALOGE("Config Update failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - 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; - mGaplessBytes = true; - // 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 * numChannels * sizeof(int16_t); - mAnchorTimeStamp = work->input.ordinal.timestamp.peekull(); - } - if (eos) { - if (calOutSize >= - outSize + kPVMP3DecoderDelay * numChannels * sizeof(int16_t)) { - if (!memset(reinterpret_cast<int16_t*>(wView.data() + outSize), 0, - kPVMP3DecoderDelay * numChannels * sizeof(int16_t))) { - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - ALOGV("Adding 529 samples at end"); - mGaplessBytes = false; - outSize += kPVMP3DecoderDelay * numChannels * sizeof(int16_t); - } - } - - uint64_t outTimeStamp = mProcessedSamples * 1000000ll / samplingRate; - mProcessedSamples += ((outSize - outOffset) / (numChannels * 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; - if (eos) { - mSignalledOutputEos = true; - ALOGV("signalled EOS"); - } -} - -class C2SoftMp3DecFactory : public C2ComponentFactory { -public: - C2SoftMp3DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftMP3::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftMP3::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftMP3::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftMp3DecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/mp3/C2SoftMp3Dec.h b/media/codecs/mp3/C2SoftMp3Dec.h deleted file mode 100644 index 402bdc4..0000000 --- a/media/codecs/mp3/C2SoftMp3Dec.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 ANDROID_C2_SOFT_MP3_DEC_H_ -#define ANDROID_C2_SOFT_MP3_DEC_H_ - -#include <SimpleC2Component.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 { - class IntfImpl; - - C2SoftMP3(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl); - 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 - }; - - std::shared_ptr<IntfImpl> mIntf; - tPVMP3DecoderExternal *mConfig; - void *mDecoderBuf; - - bool mIsFirst; - bool mSignalledError; - bool mSignalledOutputEos; - bool mGaplessBytes; - uint64_t mAnchorTimeStamp; - uint64_t mProcessedSamples; - - status_t initDecoder(); - - C2_DO_NOT_COPY(C2SoftMP3); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_MP3_DEC_H_ diff --git a/media/codecs/mp3/MODULE_LICENSE_APACHE2 b/media/codecs/mp3/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/mp3/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/mp3/NOTICE b/media/codecs/mp3/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/mp3/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/mp3/patent_disclaimer.txt b/media/codecs/mp3/patent_disclaimer.txt deleted file mode 100644 index b4bf11d..0000000 --- a/media/codecs/mp3/patent_disclaimer.txt +++ /dev/null @@ -1,9 +0,0 @@ - -THIS IS NOT A GRANT OF PATENT RIGHTS. - -Google makes no representation or warranty that the codecs for which -source code is made available hereunder are unencumbered by -third-party patents. Those intending to use this source code in -hardware or software products are advised that implementations of -these codecs, including in open source software or shareware, may -require patent licenses from the relevant patent holders. diff --git a/media/codecs/mpeg2/Android.bp b/media/codecs/mpeg2/Android.bp deleted file mode 100644 index 85d867e..0000000 --- a/media/codecs/mpeg2/Android.bp +++ /dev/null @@ -1,16 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2mpeg2dec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - srcs: ["C2SoftMpeg2Dec.cpp"], - - static_libs: ["libmpeg2dec"], - - include_dirs: [ - "external/libmpeg2/decoder", - "external/libmpeg2/common", - ], -} diff --git a/media/codecs/mpeg2/C2SoftMpeg2Dec.cpp b/media/codecs/mpeg2/C2SoftMpeg2Dec.cpp deleted file mode 100644 index da32ec0..0000000 --- a/media/codecs/mpeg2/C2SoftMpeg2Dec.cpp +++ /dev/null @@ -1,1069 +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 <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <Codec2Mapper.h> -#include <SimpleC2Interface.h> - -#include "C2SoftMpeg2Dec.h" -#include "impeg2d.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.mpeg2.decoder"; - -class C2SoftMpeg2Dec::IntfImpl : public SimpleInterface<void>::BaseParams { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : SimpleInterface<void>::BaseParams( - helper, - COMPONENT_NAME, - C2Component::KIND_DECODER, - C2Component::DOMAIN_VIDEO, - MEDIA_MIMETYPE_VIDEO_MPEG2) { - noPrivateBuffers(); // TODO: account for our buffers here - noInputReferences(); - noOutputReferences(); - noInputLatency(); - noTimeStretch(); - - // TODO: output latency and reordering - - addParameter( - DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES) - .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL)) - .build()); - - addParameter( - DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE) - .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(16, 1920, 4), - C2F(mSize, height).inRange(16, 1088, 4), - }) - .withSetter(SizeSetter) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_MP2V_SIMPLE, C2Config::LEVEL_MP2V_HIGH)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_MP2V_SIMPLE, - C2Config::PROFILE_MP2V_MAIN}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_MP2V_LOW, - C2Config::LEVEL_MP2V_MAIN, - C2Config::LEVEL_MP2V_HIGH_1440, - C2Config::LEVEL_MP2V_HIGH}) - }) - .withSetter(ProfileLevelSetter, mSize) - .build()); - - addParameter( - DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE) - .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 1920, 2), - C2F(mSize, height).inRange(2, 1088, 2), - }) - .withSetter(MaxPictureSizeSetter, mSize) - .build()); - - addParameter( - DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 2)) - .withFields({ - C2F(mMaxInputSize, value).any(), - }) - .calculatedAs(MaxInputSizeSetter, mMaxSize) - .build()); - - C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() }; - std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - 1u, 0u, 8u /* bitDepth */, C2Color::YUV_420); - memcpy(defaultColorInfo->m.locations, locations, sizeof(locations)); - - defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - { C2ChromaOffsetStruct::ITU_YUV_420_0() }, - 0u, 8u /* bitDepth */, C2Color::YUV_420); - helper->addStructDescriptors<C2ChromaOffsetStruct>(); - - addParameter( - DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO) - .withConstValue(defaultColorInfo) - .build()); - - addParameter( - DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsTuning::output( - 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mDefaultColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mDefaultColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mDefaultColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mDefaultColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(DefaultColorAspectsSetter) - .build()); - - addParameter( - DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsInfo::input( - 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mCodedColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mCodedColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mCodedColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mCodedColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(CodedColorAspectsSetter) - .build()); - - addParameter( - DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS) - .withDefault(new C2StreamColorAspectsInfo::output( - 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED, - C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED)) - .withFields({ - C2F(mColorAspects, range).inRange( - C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER), - C2F(mColorAspects, primaries).inRange( - C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER), - C2F(mColorAspects, transfer).inRange( - C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER), - C2F(mColorAspects, matrix).inRange( - C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER) - }) - .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects) - .build()); - - // TODO: support more formats? - addParameter( - DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT) - .withConstValue(new C2StreamPixelFormatInfo::output( - 0u, HAL_PIXEL_FORMAT_YCBCR_420_888)) - .build()); - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe, - C2P<C2VideoSizeStreamInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - // TODO: get max width/height from the size's field helpers vs. hardcoding - me.set().width = c2_min(c2_max(me.v.width, size.v.width), 1920u); - me.set().height = c2_min(c2_max(me.v.height, size.v.height), 1088u); - return C2R::Ok(); - } - - static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me, - const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) { - (void)mayBlock; - // assume compression ratio of 1 - me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 384); - return C2R::Ok(); - } - - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - (void)size; - (void)me; // TODO: validate - return C2R::Ok(); - } - - static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) { - (void)mayBlock; - if (me.v.range > C2Color::RANGE_OTHER) { - me.set().range = C2Color::RANGE_OTHER; - } - if (me.v.primaries > C2Color::PRIMARIES_OTHER) { - me.set().primaries = C2Color::PRIMARIES_OTHER; - } - if (me.v.transfer > C2Color::TRANSFER_OTHER) { - me.set().transfer = C2Color::TRANSFER_OTHER; - } - if (me.v.matrix > C2Color::MATRIX_OTHER) { - me.set().matrix = C2Color::MATRIX_OTHER; - } - return C2R::Ok(); - } - - static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) { - (void)mayBlock; - if (me.v.range > C2Color::RANGE_OTHER) { - me.set().range = C2Color::RANGE_OTHER; - } - if (me.v.primaries > C2Color::PRIMARIES_OTHER) { - me.set().primaries = C2Color::PRIMARIES_OTHER; - } - if (me.v.transfer > C2Color::TRANSFER_OTHER) { - me.set().transfer = C2Color::TRANSFER_OTHER; - } - if (me.v.matrix > C2Color::MATRIX_OTHER) { - me.set().matrix = C2Color::MATRIX_OTHER; - } - return C2R::Ok(); - } - - static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me, - const C2P<C2StreamColorAspectsTuning::output> &def, - const C2P<C2StreamColorAspectsInfo::input> &coded) { - (void)mayBlock; - // take default values for all unspecified fields, and coded values for specified ones - me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range; - me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED - ? def.v.primaries : coded.v.primaries; - me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED - ? def.v.transfer : coded.v.transfer; - me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix; - return C2R::Ok(); - } - - std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() { - return mColorAspects; - } - -private: - std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; - std::shared_ptr<C2StreamPictureSizeInfo::output> mSize; - std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize; - std::shared_ptr<C2StreamColorInfo::output> mColorInfo; - std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects; - std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects; - std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects; - std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat; -}; - -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, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - 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; - } - } - - if (mOutBufferDrain) { - 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; - 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::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; - } - - VuiColorAspects vuiColorAspects; - vuiColorAspects.primaries = s_ctl_get_seq_info_op.u1_colour_primaries; - vuiColorAspects.transfer = s_ctl_get_seq_info_op.u1_transfer_characteristics; - vuiColorAspects.coeffs = s_ctl_get_seq_info_op.u1_matrix_coefficients; - vuiColorAspects.fullRange = false; // mpeg2 video has limited range. - - // convert vui aspects to C2 values if changed - if (!(vuiColorAspects == mBitstreamColorAspects)) { - mBitstreamColorAspects = vuiColorAspects; - ColorAspects sfAspects; - C2StreamColorAspectsInfo::input codedAspects = { 0u }; - ColorUtils::convertIsoColorAspectsToCodecAspects( - vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs, - vuiColorAspects.fullRange, sfAspects); - if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) { - codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) { - codedAspects.range = C2Color::RANGE_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) { - codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED; - } - if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) { - codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED; - } - std::vector<std::unique_ptr<C2SettingResult>> failures; - (void)mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures); - } - 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; - { - IntfImpl::Lock lock = mIntf->lock(); - buffer->setInfo(mIntf->getColorAspects_l()); - } - - auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) { - work->worklets.front()->output.flags = (C2FrameData::flags_t)0; - 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 0u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - size_t inOffset = 0u; - size_t inSize = 0u; - uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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->workletsProcessed = 1u; - 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->workletsProcessed = 1u; - 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, nullptr); - 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(); - work->workletsProcessed = 0u; - mWidth = s_decode_op.u4_pic_wd; - mHeight = s_decode_op.u4_pic_ht; - - ALOGI("Configuring decoder: mWidth %d , mHeight %d ", - mWidth, mHeight); - C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = - mIntf->config({&size}, C2_MAY_BLOCK, &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(size)); - } else { - ALOGE("Cannot set width and height"); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } - - if (OK != reInitDecoder()) { - ALOGE("Failed to reinitialize decoder"); - mSignalledError = true; - work->workletsProcessed = 1u; - 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(); - work->workletsProcessed = 0u; - 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); - - ALOGI("Configuring decoder out: mWidth %d , mHeight %d ", - mWidth, mHeight); - C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = - mIntf->config({&size}, C2_MAY_BLOCK, &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(size)); - } else { - ALOGE("Cannot set width and height"); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return; - } - } - } - - (void) getSeqInfo(); - 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->workletsProcessed = 1u; - 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; - work->workletsProcessed = 1u; - 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 { - fillEmptyWork(work); - break; - } - } - - 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: - C2SoftMpeg2DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftMpeg2Dec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftMpeg2Dec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftMpeg2Dec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftMpeg2DecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/mpeg2/C2SoftMpeg2Dec.h b/media/codecs/mpeg2/C2SoftMpeg2Dec.h deleted file mode 100644 index 9999872..0000000 --- a/media/codecs/mpeg2/C2SoftMpeg2Dec.h +++ /dev/null @@ -1,195 +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 ANDROID_C2_SOFT_MPEG2_DEC_H_ -#define ANDROID_C2_SOFT_MPEG2_DEC_H_ - -#include <SimpleC2Component.h> - -#include <media/stagefright/foundation/ColorUtils.h> - -#include "iv_datatypedef.h" -#include "iv.h" -#include "ivd.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 { - class IntfImpl; - - C2SoftMpeg2Dec(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - 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(); - 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, - }; - - std::shared_ptr<IntfImpl> mIntf; - 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; - - // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid - // converting them to C2 values for each frame - struct VuiColorAspects { - uint8_t primaries; - uint8_t transfer; - uint8_t coeffs; - uint8_t fullRange; - - // default color aspects - VuiColorAspects() - : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - - bool operator==(const VuiColorAspects &o) { - return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs - && fullRange == o.fullRange; - } - } mBitstreamColorAspects; - - // profile - struct timeval mTimeStart; - struct timeval mTimeEnd; -#ifdef FILE_DUMP_ENABLE - char mInFile[200]; -#endif /* FILE_DUMP_ENABLE */ - - C2_DO_NOT_COPY(C2SoftMpeg2Dec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_MPEG2_DEC_H_ diff --git a/media/codecs/mpeg4_h263/Android.bp b/media/codecs/mpeg4_h263/Android.bp deleted file mode 100644 index 3155bc2..0000000 --- a/media/codecs/mpeg4_h263/Android.bp +++ /dev/null @@ -1,66 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2mpeg4dec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - srcs: ["C2SoftMpeg4Dec.cpp"], - - static_libs: ["libstagefright_m4vh263dec"], - - cflags: [ - "-DOSCL_IMPORT_REF=", - "-DMPEG4", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2h263dec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - srcs: ["C2SoftMpeg4Dec.cpp"], - - static_libs: ["libstagefright_m4vh263dec"], - - cflags: [ - "-DOSCL_IMPORT_REF=", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2mpeg4enc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - - srcs: ["C2SoftMpeg4Enc.cpp"], - - static_libs: ["libstagefright_m4vh263enc"], - - cflags: [ - "-DMPEG4", - "-DOSCL_IMPORT_REF=", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2h263enc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_signed-defaults", - ], - - srcs: ["C2SoftMpeg4Enc.cpp"], - - static_libs: [ "libstagefright_m4vh263enc" ], - - cflags: [ - "-DOSCL_IMPORT_REF=", - ], -} diff --git a/media/codecs/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codecs/mpeg4_h263/C2SoftMpeg4Dec.cpp deleted file mode 100644 index 901f5ed..0000000 --- a/media/codecs/mpeg4_h263/C2SoftMpeg4Dec.cpp +++ /dev/null @@ -1,746 +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 -#ifdef MPEG4 - #define LOG_TAG "C2SoftMpeg4Dec" -#else - #define LOG_TAG "C2SoftH263Dec" -#endif -#include <log/log.h> - -#include <media/stagefright/foundation/AUtils.h> -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftMpeg4Dec.h" -#include "mp4dec_api.h" - -namespace android { - -#ifdef MPEG4 -constexpr char COMPONENT_NAME[] = "c2.android.mpeg4.decoder"; -#else -constexpr char COMPONENT_NAME[] = "c2.android.h263.decoder"; -#endif - -class C2SoftMpeg4Dec::IntfImpl : public SimpleInterface<void>::BaseParams { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : SimpleInterface<void>::BaseParams( - helper, - COMPONENT_NAME, - C2Component::KIND_DECODER, - C2Component::DOMAIN_VIDEO, -#ifdef MPEG4 - MEDIA_MIMETYPE_VIDEO_MPEG4 -#else - MEDIA_MIMETYPE_VIDEO_H263 -#endif - ) { - noPrivateBuffers(); // TODO: account for our buffers here - noInputReferences(); - noOutputReferences(); - noInputLatency(); - noTimeStretch(); - - // TODO: output latency and reordering - - addParameter( - DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES) - .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL)) - .build()); - - addParameter( - DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE) - .withDefault(new C2StreamPictureSizeInfo::output(0u, 176, 144)) - .withFields({ -#ifdef MPEG4 - C2F(mSize, width).inRange(2, 1920, 2), - C2F(mSize, height).inRange(2, 1088, 2), -#else - C2F(mSize, width).inRange(2, 352, 2), - C2F(mSize, height).inRange(2, 288, 2), -#endif - }) - .withSetter(SizeSetter) - .build()); - -#ifdef MPEG4 - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_MP4V_SIMPLE, C2Config::LEVEL_MP4V_3)) - .withFields({ - C2F(mProfileLevel, profile).equalTo( - C2Config::PROFILE_MP4V_SIMPLE), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_MP4V_0, - C2Config::LEVEL_MP4V_0B, - C2Config::LEVEL_MP4V_1, - C2Config::LEVEL_MP4V_2, - C2Config::LEVEL_MP4V_3, - C2Config::LEVEL_MP4V_3B, - C2Config::LEVEL_MP4V_4, - C2Config::LEVEL_MP4V_4A, - C2Config::LEVEL_MP4V_5, - C2Config::LEVEL_MP4V_6}) - }) - .withSetter(ProfileLevelSetter, mSize) - .build()); -#else - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_H263_BASELINE, C2Config::LEVEL_H263_30)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_H263_BASELINE, - C2Config::PROFILE_H263_ISWV2}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_H263_10, - C2Config::LEVEL_H263_20, - C2Config::LEVEL_H263_30, - C2Config::LEVEL_H263_40, - C2Config::LEVEL_H263_45}) - }) - .withSetter(ProfileLevelSetter, mSize) - .build()); -#endif - - addParameter( - DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE) -#ifdef MPEG4 - .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 1920, 1088)) -#else - .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 352, 288)) -#endif - .withFields({ -#ifdef MPEG4 - C2F(mSize, width).inRange(2, 1920, 2), - C2F(mSize, height).inRange(2, 1088, 2), -#else - C2F(mSize, width).inRange(2, 352, 2), - C2F(mSize, height).inRange(2, 288, 2), -#endif - }) - .withSetter(MaxPictureSizeSetter, mSize) - .build()); - - addParameter( - DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) -#ifdef MPEG4 - .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 1920 * 1088 * 3 / 2)) -#else - .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 352 * 288 * 3 / 2)) -#endif - .withFields({ - C2F(mMaxInputSize, value).any(), - }) - .calculatedAs(MaxInputSizeSetter, mMaxSize) - .build()); - - C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() }; - std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - 1u, 0u, 8u /* bitDepth */, C2Color::YUV_420); - memcpy(defaultColorInfo->m.locations, locations, sizeof(locations)); - - defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - { C2ChromaOffsetStruct::ITU_YUV_420_0() }, - 0u, 8u /* bitDepth */, C2Color::YUV_420); - helper->addStructDescriptors<C2ChromaOffsetStruct>(); - - addParameter( - DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO) - .withConstValue(defaultColorInfo) - .build()); - - // TODO: support more formats? - addParameter( - DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT) - .withConstValue(new C2StreamPixelFormatInfo::output( - 0u, HAL_PIXEL_FORMAT_YCBCR_420_888)) - .build()); - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe, - C2P<C2VideoSizeStreamInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - // TODO: get max width/height from the size's field helpers vs. hardcoding -#ifdef MPEG4 - me.set().width = c2_min(c2_max(me.v.width, size.v.width), 1920u); - me.set().height = c2_min(c2_max(me.v.height, size.v.height), 1088u); -#else - me.set().width = c2_min(c2_max(me.v.width, size.v.width), 352u); - me.set().height = c2_min(c2_max(me.v.height, size.v.height), 288u); -#endif - return C2R::Ok(); - } - - static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me, - const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) { - (void)mayBlock; - // assume compression ratio of 1 - me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 384); - return C2R::Ok(); - } - - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - (void)size; - (void)me; // TODO: validate - return C2R::Ok(); - } - - uint32_t getMaxWidth() const { return mMaxSize->width; } - uint32_t getMaxHeight() const { return mMaxSize->height; } - -private: - std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; - std::shared_ptr<C2StreamPictureSizeInfo::output> mSize; - std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize; - std::shared_ptr<C2StreamColorInfo::output> mColorInfo; - std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat; -}; - -C2SoftMpeg4Dec::C2SoftMpeg4Dec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mDecHandle(nullptr), - mOutputBuffer{}, - mInitialized(false) { -} - -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) { - if (mDecHandle) { - 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)onInit(); -} - -void C2SoftMpeg4Dec::onRelease() { - if (mInitialized) { - if (mDecHandle) { - PVCleanUpVideoDecoder(mDecHandle); - delete mDecHandle; - mDecHandle = nullptr; - } - mInitialized = false; - } - if (mOutBlock) { - mOutBlock.reset(); - } - for (int32_t i = 0; i < kNumOutputBuffers; ++i) { - if (mOutputBuffer[i]) { - free(mOutputBuffer[i]); - mOutputBuffer[i] = 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; - } - if (!mDecHandle) { - ALOGE("mDecHandle is null"); - return NO_MEMORY; - } - 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; - } - - mOutputBufferSize = align(mIntf->getMaxWidth(), 16) * align(mIntf->getMaxHeight(), 16) * 3 / 2; - for (int32_t i = 0; i < kNumOutputBuffers; ++i) { - if (!mOutputBuffer[i]) { - mOutputBuffer[i] = (uint8_t *)malloc(mOutputBufferSize); - 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, mIntf->getMaxWidth(), mIntf->getMaxHeight(), H263_MODE)) { - ALOGE("Error in PVInitVideoDecoder H263_MODE while resChanged was set to true"); - mSignalledError = true; - work->result = C2_CORRUPTED; - 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) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - size_t inOffset = 0u; - size_t inSize = 0u; - uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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, - mIntf->getMaxWidth(), mIntf->getMaxHeight(), mode)) { - ALOGE("PVInitVideoDecoder failed. Unsupported content?"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - mInitialized = true; - MP4DecodingMode actualMode = PVGetDecBitstreamMode(mDecHandle); - if (mode != actualMode) { - ALOGE("Decoded mode not same as actual mode of the decoder"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - PVSetPostProcType(mDecHandle, 0); - if (handleResChange(work)) { - ALOGI("Setting width and height"); - C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(size)); - } else { - ALOGE("Config update size failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - 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 yFrameSize = sizeof(uint8) * mDecHandle->size; - if (mOutputBufferSize < yFrameSize * 3 / 2){ - ALOGE("Too small output buffer: %zu bytes", mOutputBufferSize); - mSignalledError = true; - work->result = C2_NO_MEMORY; - 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."); - mSignalledError = true; - work->result = C2_CORRUPTED; - 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) { - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } else if (resChange) { - ALOGI("Setting width and height"); - C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(size)); - } else { - ALOGE("Config update size failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - continue; - } - - if (PVDecodeVopBody(mDecHandle, &tmpInSize) != PV_TRUE) { - ALOGE("failed to decode video frame."); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - if (handleResChange(work)) { - mSignalledError = true; - work->result = C2_CORRUPTED; - 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: - C2SoftMpeg4DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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(COMPONENT_NAME, - id, - std::make_shared<C2SoftMpeg4Dec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftMpeg4Dec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftMpeg4Dec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftMpeg4DecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/mpeg4_h263/C2SoftMpeg4Dec.h b/media/codecs/mpeg4_h263/C2SoftMpeg4Dec.h deleted file mode 100644 index 716a095..0000000 --- a/media/codecs/mpeg4_h263/C2SoftMpeg4Dec.h +++ /dev/null @@ -1,77 +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> - - -struct tagvideoDecControls; - -namespace android { - -struct C2SoftMpeg4Dec : public SimpleC2Component { - class IntfImpl; - - C2SoftMpeg4Dec(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - 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); - - std::shared_ptr<IntfImpl> mIntf; - tagvideoDecControls *mDecHandle; - std::shared_ptr<C2GraphicBlock> mOutBlock; - uint8_t *mOutputBuffer[kNumOutputBuffers]; - size_t mOutputBufferSize; - - uint32_t mWidth; - uint32_t mHeight; - uint32_t mNumSamplesOutput; - - bool mIsMpeg4; - bool mInitialized; - bool mFramesConfigured; - bool mSignalledOutputEos; - bool mSignalledError; - - C2_DO_NOT_COPY(C2SoftMpeg4Dec); -}; - -} // namespace android - -#endif // C2_SOFT_MPEG4_DEC_H_ diff --git a/media/codecs/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codecs/mpeg4_h263/C2SoftMpeg4Enc.cpp deleted file mode 100644 index c8796f3..0000000 --- a/media/codecs/mpeg4_h263/C2SoftMpeg4Enc.cpp +++ /dev/null @@ -1,671 +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 -#ifdef MPEG4 - #define LOG_TAG "C2SoftMpeg4Enc" -#else - #define LOG_TAG "C2SoftH263Enc" -#endif -#include <log/log.h> - -#include <inttypes.h> - -#include <media/hardware/VideoAPI.h> -#include <media/stagefright/foundation/AUtils.h> -#include <media/stagefright/MediaDefs.h> -#include <utils/misc.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> -#include <util/C2InterfaceHelper.h> - -#include "C2SoftMpeg4Enc.h" -#include "mp4enc_api.h" - -namespace android { - -#ifdef MPEG4 -constexpr char COMPONENT_NAME[] = "c2.android.mpeg4.encoder"; -#else -constexpr char COMPONENT_NAME[] = "c2.android.h263.encoder"; -#endif - -class C2SoftMpeg4Enc::IntfImpl : public C2InterfaceHelper { - public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper) - : C2InterfaceHelper(helper) { - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::input(0u, C2FormatVideo)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::output(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_VIDEO_RAW)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( -#ifdef MPEG4 - MEDIA_MIMETYPE_VIDEO_MPEG4 -#else - MEDIA_MIMETYPE_VIDEO_H263 -#endif - )) - .build()); - - addParameter(DefineParam(mUsage, C2_NAME_INPUT_STREAM_USAGE_SETTING) - .withConstValue(new C2StreamUsageTuning::input( - 0u, (uint64_t)C2MemoryUsage::CPU_READ)) - .build()); - - addParameter( - DefineParam(mSize, C2_NAME_STREAM_VIDEO_SIZE_SETTING) - .withDefault(new C2VideoSizeStreamTuning::input(0u, 176, 144)) - .withFields({ -#ifdef MPEG4 - C2F(mSize, width).inRange(16, 176, 16), - C2F(mSize, height).inRange(16, 144, 16), -#else - C2F(mSize, width).oneOf({176, 352}), - C2F(mSize, height).oneOf({144, 288}), -#endif - }) - .withSetter(SizeSetter) - .build()); - - addParameter( - DefineParam(mFrameRate, C2_NAME_STREAM_FRAME_RATE_SETTING) - .withDefault(new C2StreamFrameRateInfo::output(0u, 17.)) - // TODO: More restriction? - .withFields({C2F(mFrameRate, value).greaterThan(0.)}) - .withSetter( - Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::output(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(4096, 12000000)}) - .withSetter(BitrateSetter) - .build()); - - addParameter( - DefineParam(mSyncFramePeriod, C2_PARAMKEY_SYNC_FRAME_INTERVAL) - .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000)) - .withFields({C2F(mSyncFramePeriod, value).any()}) - .withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps) - .build()); - -#ifdef MPEG4 - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::output( - 0u, PROFILE_MP4V_SIMPLE, LEVEL_MP4V_2)) - .withFields({ - C2F(mProfileLevel, profile).equalTo( - PROFILE_MP4V_SIMPLE), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_MP4V_0, - C2Config::LEVEL_MP4V_0B, - C2Config::LEVEL_MP4V_1, - C2Config::LEVEL_MP4V_2}) - }) - .withSetter(ProfileLevelSetter) - .build()); -#else - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::output( - 0u, PROFILE_H263_BASELINE, LEVEL_H263_45)) - .withFields({ - C2F(mProfileLevel, profile).equalTo( - PROFILE_H263_BASELINE), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_H263_10, - C2Config::LEVEL_H263_20, - C2Config::LEVEL_H263_30, - C2Config::LEVEL_H263_40, - C2Config::LEVEL_H263_45}) - }) - .withSetter(ProfileLevelSetter) - .build()); -#endif - } - - static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (me.v.value <= 4096) { - me.set().value = 4096; - } - return res; - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe, - C2P<C2StreamPictureSizeInfo::input> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R ProfileLevelSetter( - bool mayBlock, - C2P<C2StreamProfileLevelInfo::output> &me) { - (void)mayBlock; - if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) { -#ifdef MPEG4 - me.set().profile = PROFILE_MP4V_SIMPLE; -#else - me.set().profile = PROFILE_H263_BASELINE; -#endif - } - if (!me.F(me.v.level).supportsAtAll(me.v.level)) { -#ifdef MPEG4 - me.set().level = LEVEL_MP4V_2; -#else - me.set().level = LEVEL_H263_45; -#endif - } - return C2R::Ok(); - } - - // unsafe getters - std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const { return mSize; } - std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; } - std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; } - uint32_t getSyncFramePeriod() const { - if (mSyncFramePeriod->value < 0 || mSyncFramePeriod->value == INT64_MAX) { - return 0; - } - double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value; - return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.); - } - - private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamUsageTuning::input> mUsage; - std::shared_ptr<C2VideoSizeStreamTuning::input> mSize; - std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; - std::shared_ptr<C2BitrateTuning::output> mBitrate; - std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel; - std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod; -}; - -C2SoftMpeg4Enc::C2SoftMpeg4Enc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : SimpleC2Component( - std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mHandle(nullptr), - mEncParams(nullptr), - mStarted(false), - mOutBufferSize(524288) { -} - -C2SoftMpeg4Enc::~C2SoftMpeg4Enc() { - onRelease(); -} - -c2_status_t C2SoftMpeg4Enc::onInit() { -#ifdef MPEG4 - mEncodeMode = COMBINE_MODE_WITH_ERR_RES; -#else - mEncodeMode = H263_MODE; -#endif - if (!mHandle) { - mHandle = new tagvideoEncControls; - } - - if (!mEncParams) { - mEncParams = new tagvideoEncOptions; - } - - if (!(mEncParams && mHandle)) return C2_NO_MEMORY; - - mSignalledOutputEos = false; - mSignalledError = false; - - return initEncoder(); -} - -c2_status_t C2SoftMpeg4Enc::onStop() { - if (!mStarted) { - return C2_OK; - } - if (mHandle) { - (void)PVCleanUpVideoEncoder(mHandle); - } - mStarted = false; - mSignalledOutputEos = false; - mSignalledError = false; - return C2_OK; -} - -void C2SoftMpeg4Enc::onReset() { - onStop(); - initEncoder(); -} - -void C2SoftMpeg4Enc::onRelease() { - onStop(); - if (mEncParams) { - delete mEncParams; - mEncParams = nullptr; - } - if (mHandle) { - delete mHandle; - mHandle = nullptr; - } -} - -c2_status_t C2SoftMpeg4Enc::onFlush_sm() { - return C2_OK; -} - -static 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; -} - -c2_status_t C2SoftMpeg4Enc::initEncParams() { - if (mHandle) { - memset(mHandle, 0, sizeof(tagvideoEncControls)); - } else return C2_CORRUPTED; - if (mEncParams) { - memset(mEncParams, 0, sizeof(tagvideoEncOptions)); - } else return C2_CORRUPTED; - - if (!PVGetDefaultEncOption(mEncParams, 0)) { - ALOGE("Failed to get default encoding parameters"); - return C2_CORRUPTED; - } - - if (mFrameRate->value == 0) { - ALOGE("Framerate should not be 0"); - return C2_BAD_VALUE; - } - - mEncParams->encMode = mEncodeMode; - mEncParams->encWidth[0] = mSize->width; - mEncParams->encHeight[0] = mSize->height; - mEncParams->encFrameRate[0] = mFrameRate->value + 0.5; - mEncParams->rcType = VBR_1; - mEncParams->vbvDelay = 5.0f; - mEncParams->profile_level = CORE_PROFILE_LEVEL2; - mEncParams->packetSize = 32; - mEncParams->rvlcEnable = PV_OFF; - mEncParams->numLayers = 1; - mEncParams->timeIncRes = 1000; - mEncParams->tickPerSrc = mEncParams->timeIncRes / (mFrameRate->value + 0.5); - mEncParams->bitRate[0] = mBitrate->value; - mEncParams->iQuant[0] = 15; - mEncParams->pQuant[0] = 12; - mEncParams->quantType[0] = 0; - mEncParams->noFrameSkipped = PV_OFF; - - // PV's MPEG4 encoder requires the video dimension of multiple - if (mSize->width % 16 != 0 || mSize->height % 16 != 0) { - ALOGE("Video frame size %dx%d must be a multiple of 16", - mSize->width, mSize->height); - return C2_BAD_VALUE; - } - - // Set IDR frame refresh interval - mEncParams->intraPeriod = mIntf->getSyncFramePeriod(); - mEncParams->numIntraMB = 0; - mEncParams->sceneDetect = PV_ON; - mEncParams->searchRange = 16; - mEncParams->mv8x8Enable = PV_OFF; - mEncParams->gobHeaderInterval = 0; - mEncParams->useACPred = PV_ON; - mEncParams->intraDCVlcTh = 0; - - return C2_OK; -} - -c2_status_t C2SoftMpeg4Enc::initEncoder() { - if (mStarted) { - return C2_OK; - } - { - IntfImpl::Lock lock = mIntf->lock(); - mSize = mIntf->getSize_l(); - mBitrate = mIntf->getBitrate_l(); - mFrameRate = mIntf->getFrameRate_l(); - } - c2_status_t err = initEncParams(); - if (C2_OK != err) { - ALOGE("Failed to initialized encoder params"); - mSignalledError = true; - return err; - } - if (!PVInitVideoEncoder(mHandle, mEncParams)) { - ALOGE("Failed to initialize the encoder"); - mSignalledError = true; - return C2_CORRUPTED; - } - - // 1st buffer for codec specific data - mNumInputFrames = -1; - mStarted = true; - return C2_OK; -} - -void C2SoftMpeg4Enc::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - // Initialize encoder if not already initialized - if (!mStarted && C2_OK != initEncoder()) { - ALOGE("Failed to initialize encoder"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - std::shared_ptr<C2LinearBlock> block; - C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }; - c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, 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; - } - - uint8_t *outPtr = (uint8_t *)wView.data(); - if (mNumInputFrames < 0) { - // The very first thing we want to output is the codec specific data. - int32_t outputSize = mOutBufferSize; - if (!PVGetVolHeader(mHandle, outPtr, &outputSize, 0)) { - ALOGE("Failed to get VOL header"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } else { - ALOGV("Bytes Generated in header %d\n", outputSize); - } - - ++mNumInputFrames; - std::unique_ptr<C2StreamCsdInfo::output> csd = - C2StreamCsdInfo::output::AllocUnique(outputSize, 0u); - if (!csd) { - ALOGE("CSD allocation failed"); - mSignalledError = true; - work->result = C2_NO_MEMORY; - return; - } - memcpy(csd->m.value, outPtr, outputSize); - work->worklets.front()->output.configUpdate.push_back(std::move(csd)); - } - - std::shared_ptr<const C2GraphicView> rView; - std::shared_ptr<C2Buffer> inputBuffer; - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - if (!work->input.buffers.empty()) { - inputBuffer = work->input.buffers[0]; - rView = std::make_shared<const C2GraphicView>( - inputBuffer->data().graphicBlocks().front().map().get()); - if (rView->error() != C2_OK) { - ALOGE("graphic view map err = %d", rView->error()); - work->result = rView->error(); - return; - } - } else { - fillEmptyWork(work); - if (eos) { - mSignalledOutputEos = true; - ALOGV("signalled EOS"); - } - return; - } - - uint64_t inputTimeStamp = work->input.ordinal.timestamp.peekull(); - const C2ConstGraphicBlock inBuffer = inputBuffer->data().graphicBlocks().front(); - if (inBuffer.width() < mSize->width || - inBuffer.height() < mSize->height) { - /* Expect width height to be configured */ - ALOGW("unexpected Capacity Aspect %d(%d) x %d(%d)", inBuffer.width(), - mSize->width, inBuffer.height(), mSize->height); - work->result = C2_BAD_VALUE; - return; - } - - const C2PlanarLayout &layout = rView->layout(); - uint8_t *yPlane = const_cast<uint8_t *>(rView->data()[C2PlanarLayout::PLANE_Y]); - uint8_t *uPlane = const_cast<uint8_t *>(rView->data()[C2PlanarLayout::PLANE_U]); - uint8_t *vPlane = const_cast<uint8_t *>(rView->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; - uint32_t width = mSize->width; - uint32_t height = mSize->height; - // width and height are always even (as block size is 16x16) - CHECK_EQ((width & 1u), 0u); - CHECK_EQ((height & 1u), 0u); - size_t yPlaneSize = width * height; - switch (layout.type) { - case C2PlanarLayout::TYPE_RGB: - [[fallthrough]]; - case C2PlanarLayout::TYPE_RGBA: { - MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2); - mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer); - yPlane = conversionBuffer.data(); - uPlane = yPlane + yPlaneSize; - vPlane = uPlane + yPlaneSize / 4; - yStride = width; - uStride = vStride = width / 2; - ConvertRGBToPlanarYUV(yPlane, yStride, height, conversionBuffer.size(), *rView.get()); - break; - } - case C2PlanarLayout::TYPE_YUV: { - if (!IsYUV420(*rView)) { - ALOGE("input is not YUV420"); - work->result = C2_BAD_VALUE; - break; - } - - if (layout.planes[layout.PLANE_Y].colInc == 1 - && layout.planes[layout.PLANE_U].colInc == 1 - && layout.planes[layout.PLANE_V].colInc == 1 - && uStride == vStride - && yStride == 2 * vStride) { - // I420 compatible - planes are already set up above - break; - } - - // copy to I420 - MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2); - mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer); - MediaImage2 img = CreateYUV420PlanarMediaImage2(width, height, width, height); - status_t err = ImageCopy(conversionBuffer.data(), &img, *rView); - if (err != OK) { - ALOGE("Buffer conversion failed: %d", err); - work->result = C2_BAD_VALUE; - return; - } - yPlane = conversionBuffer.data(); - uPlane = yPlane + yPlaneSize; - vPlane = uPlane + yPlaneSize / 4; - yStride = width; - uStride = vStride = width / 2; - break; - } - - case C2PlanarLayout::TYPE_YUVA: - ALOGE("YUVA plane type is not supported"); - work->result = C2_BAD_VALUE; - return; - - default: - ALOGE("Unrecognized plane type: %d", layout.type); - work->result = C2_BAD_VALUE; - return; - } - - CHECK(NULL != yPlane); - /* Encode frames */ - VideoEncFrameIO vin, vout; - memset(&vin, 0, sizeof(vin)); - memset(&vout, 0, sizeof(vout)); - vin.yChan = yPlane; - vin.uChan = uPlane; - vin.vChan = vPlane; - vin.timestamp = (inputTimeStamp + 500) / 1000; // in ms - vin.height = align(height, 16); - vin.pitch = align(width, 16); - - uint32_t modTimeMs = 0; - int32_t nLayer = 0; - MP4HintTrack hintTrack; - int32_t outputSize = mOutBufferSize; - if (!PVEncodeVideoFrame(mHandle, &vin, &vout, &modTimeMs, outPtr, &outputSize, &nLayer) || - !PVGetHintTrack(mHandle, &hintTrack)) { - ALOGE("Failed to encode frame or get hint track at frame %" PRId64, mNumInputFrames); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - ALOGV("outputSize filled : %d", outputSize); - ++mNumInputFrames; - CHECK(NULL == PVGetOverrunBuffer(mHandle)); - - fillEmptyWork(work); - if (outputSize) { - std::shared_ptr<C2Buffer> buffer = createLinearBuffer(block, 0, outputSize); - work->worklets.front()->output.ordinal.timestamp = inputTimeStamp; - if (hintTrack.CodeType == 0) { - buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>( - 0u /* stream id */, C2PictureTypeKeyFrame)); - } - work->worklets.front()->output.buffers.push_back(buffer); - } - if (eos) { - mSignalledOutputEos = true; - } - - mConversionBuffersInUse.erase(yPlane); -} - -c2_status_t C2SoftMpeg4Enc::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 C2SoftMpeg4EncFactory : public C2ComponentFactory { -public: - C2SoftMpeg4EncFactory() - : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) {} - - 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 C2SoftMpeg4Enc( - COMPONENT_NAME, id, - std::make_shared<C2SoftMpeg4Enc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftMpeg4Enc::IntfImpl>( - COMPONENT_NAME, id, - std::make_shared<C2SoftMpeg4Enc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftMpeg4EncFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // namespace android - -extern "C" ::C2ComponentFactory* CreateCodec2Factory() { - ALOGV("in %s", __func__); - return new ::android::C2SoftMpeg4EncFactory(); -} - -extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) { - ALOGV("in %s", __func__); - delete factory; -} diff --git a/media/codecs/mpeg4_h263/C2SoftMpeg4Enc.h b/media/codecs/mpeg4_h263/C2SoftMpeg4Enc.h deleted file mode 100644 index 43461fc..0000000 --- a/media/codecs/mpeg4_h263/C2SoftMpeg4Enc.h +++ /dev/null @@ -1,83 +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_MPEG4_ENC_H__ -#define C2_SOFT_MPEG4_ENC_H__ - -#include <map> - -#include <Codec2BufferUtils.h> -#include <SimpleC2Component.h> - -#include "mp4enc_api.h" - -namespace android { - -struct C2SoftMpeg4Enc : public SimpleC2Component { - class IntfImpl; - - C2SoftMpeg4Enc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - - // 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 ~C2SoftMpeg4Enc(); - -private: - std::shared_ptr<IntfImpl> mIntf; - - tagvideoEncControls *mHandle; - tagvideoEncOptions *mEncParams; - - bool mStarted; - bool mSignalledOutputEos; - bool mSignalledError; - - uint32_t mOutBufferSize; - // configurations used by component in process - // (TODO: keep this in intf but make them internal only) - std::shared_ptr<C2StreamPictureSizeInfo::input> mSize; - std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; - std::shared_ptr<C2StreamBitrateInfo::output> mBitrate; - - int64_t mNumInputFrames; - MP4EncodingMode mEncodeMode; - - MemoryBlockPool mConversionBuffers; - std::map<void *, MemoryBlock> mConversionBuffersInUse; - - c2_status_t initEncParams(); - c2_status_t initEncoder(); - - C2_DO_NOT_COPY(C2SoftMpeg4Enc); -}; - -} // namespace android - -#endif // C2_SOFT_MPEG4_ENC_H__ diff --git a/media/codecs/mpeg4_h263/MODULE_LICENSE_APACHE2 b/media/codecs/mpeg4_h263/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/mpeg4_h263/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/mpeg4_h263/NOTICE b/media/codecs/mpeg4_h263/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/mpeg4_h263/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/mpeg4_h263/patent_disclaimer.txt b/media/codecs/mpeg4_h263/patent_disclaimer.txt deleted file mode 100644 index b4bf11d..0000000 --- a/media/codecs/mpeg4_h263/patent_disclaimer.txt +++ /dev/null @@ -1,9 +0,0 @@ - -THIS IS NOT A GRANT OF PATENT RIGHTS. - -Google makes no representation or warranty that the codecs for which -source code is made available hereunder are unencumbered by -third-party patents. Those intending to use this source code in -hardware or software products are advised that implementations of -these codecs, including in open source software or shareware, may -require patent licenses from the relevant patent holders. diff --git a/media/codecs/opus/Android.bp b/media/codecs/opus/Android.bp deleted file mode 100644 index a6233a6..0000000 --- a/media/codecs/opus/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2opusdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftOpusDec.cpp"], - - shared_libs: ["libopus"], -} diff --git a/media/codecs/opus/C2SoftOpusDec.cpp b/media/codecs/opus/C2SoftOpusDec.cpp deleted file mode 100644 index 2439c3c..0000000 --- a/media/codecs/opus/C2SoftOpusDec.cpp +++ /dev/null @@ -1,544 +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 "C2SoftOpusDec" -#include <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftOpusDec.h" - -extern "C" { - #include <opus.h> - #include <opus_multistream.h> -} - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.opus.decoder"; - -class C2SoftOpusDec::IntfImpl : public C2InterfaceHelper { - public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper) - : C2InterfaceHelper(helper) { - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_OPUS)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 48000)) - .withFields({C2F(mSampleRate, value).equalTo(48000)}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).inRange(1, 8)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 6000)) - .withFields({C2F(mBitrate, value).inRange(6000, 510000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 960 * 6)) - .build()); - } - - private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftOpusDec::C2SoftOpusDec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : SimpleC2Component( - std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mDecoder(nullptr) { -} - -C2SoftOpusDec::~C2SoftOpusDec() { - onRelease(); -} - -c2_status_t C2SoftOpusDec::onInit() { - status_t err = initDecoder(); - return err == OK ? C2_OK : C2_NO_MEMORY; -} - -c2_status_t C2SoftOpusDec::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 C2SoftOpusDec::onReset() { - (void)onStop(); -} - -void C2SoftOpusDec::onRelease() { - if (mDecoder) { - opus_multistream_decoder_destroy(mDecoder); - mDecoder = nullptr; - } -} - -status_t C2SoftOpusDec::initDecoder() { - memset(&mHeader, 0, sizeof(mHeader)); - mCodecDelay = 0; - mSeekPreRoll = 0; - mSamplesToDiscard = 0; - mInputBufferCount = 0; - mSignalledError = false; - mSignalledOutputEos = false; - - return OK; -} - -c2_status_t C2SoftOpusDec::onFlush_sm() { - if (mDecoder) { - opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE); - mSamplesToDiscard = mSeekPreRoll; - mSignalledOutputEos = false; - } - return C2_OK; -} - -c2_status_t C2SoftOpusDec::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 C2SoftOpusDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - size_t inOffset = 0u; - size_t inSize = 0u; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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; - - ALOGI("Configuring decoder: %d Hz, %d channels", - kRate, mHeader.channels); - C2StreamSampleRateInfo::output sampleRateInfo(0u, kRate); - C2StreamChannelCountInfo::output channelCountInfo(0u, mHeader.channels); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config( - { &sampleRateInfo, &channelCountInfo }, - C2_MAY_BLOCK, - &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(sampleRateInfo)); - work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(channelCountInfo)); - } else { - ALOGE("Config Update failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - } - - ++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: - C2SoftOpusDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftOpusDec(COMPONENT_NAME, - id, - std::make_shared<C2SoftOpusDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftOpusDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftOpusDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftOpusDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/opus/C2SoftOpusDec.h b/media/codecs/opus/C2SoftOpusDec.h deleted file mode 100644 index 92b7426..0000000 --- a/media/codecs/opus/C2SoftOpusDec.h +++ /dev/null @@ -1,79 +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 ANDROID_C2_SOFT_OPUS_DEC_H_ -#define ANDROID_C2_SOFT_OPUS_DEC_H_ - -#include <SimpleC2Component.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 C2SoftOpusDec : public SimpleC2Component { - class IntfImpl; - - C2SoftOpusDec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl); - virtual ~C2SoftOpusDec(); - - // 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 - }; - - std::shared_ptr<IntfImpl> mIntf; - OpusMSDecoder *mDecoder; - OpusHeader mHeader; - - int64_t mCodecDelay; - int64_t mSeekPreRoll; - int64_t mSamplesToDiscard; - size_t mInputBufferCount; - bool mSignalledError; - bool mSignalledOutputEos; - - status_t initDecoder(); - - C2_DO_NOT_COPY(C2SoftOpusDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_OPUS_DEC_H_ diff --git a/media/codecs/raw/Android.bp b/media/codecs/raw/Android.bp deleted file mode 100644 index 150eb91..0000000 --- a/media/codecs/raw/Android.bp +++ /dev/null @@ -1,9 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2rawdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftRawDec.cpp"], -} diff --git a/media/codecs/raw/C2SoftRawDec.cpp b/media/codecs/raw/C2SoftRawDec.cpp deleted file mode 100644 index 5c83481..0000000 --- a/media/codecs/raw/C2SoftRawDec.cpp +++ /dev/null @@ -1,233 +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 "C2SoftRawDec" -#include <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftRawDec.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.raw.decoder"; - -class C2SoftRawDec::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 44100)) - .withFields({C2F(mSampleRate, value).inRange(8000, 192000)}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 2)) - .withFields({C2F(mChannelCount, value).inRange(1, 8)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(1, 10000000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 64 * 1024)) - .build()); - - addParameter( - DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING) - .withDefault(new C2StreamPcmEncodingInfo::output(0u, C2Config::PCM_16)) - .withFields({C2F(mPcmEncodingInfo, value).oneOf({ - C2Config::PCM_16, - C2Config::PCM_8, - C2Config::PCM_FLOAT}) - }) - .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps)) - .build()); - - } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; - std::shared_ptr<C2StreamPcmEncodingInfo::output> mPcmEncodingInfo; -}; - -C2SoftRawDec::C2SoftRawDec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl) { -} - -C2SoftRawDec::~C2SoftRawDec() { - onRelease(); -} - -c2_status_t C2SoftRawDec::onInit() { - mSignalledEos = false; - return C2_OK; -} - -c2_status_t C2SoftRawDec::onStop() { - mSignalledEos = false; - return C2_OK; -} - -void C2SoftRawDec::onReset() { - (void)onStop(); -} - -void C2SoftRawDec::onRelease() { -} - -c2_status_t C2SoftRawDec::onFlush_sm() { - return onStop(); -} - -void C2SoftRawDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - (void)pool; - work->result = C2_OK; - work->workletsProcessed = 1u; - - if (mSignalledEos) { - work->result = C2_BAD_VALUE; - return; - } - - ALOGV("in buffer attr. timestamp %d frameindex %d", - (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 (!work->input.buffers.empty()) { - work->worklets.front()->output.buffers.push_back(work->input.buffers[0]); - } - if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) { - mSignalledEos = true; - ALOGV("signalled EOS"); - } -} - -c2_status_t C2SoftRawDec::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: - C2SoftRawDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftRawDec(COMPONENT_NAME, - id, - std::make_shared<C2SoftRawDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftRawDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftRawDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftRawDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/raw/C2SoftRawDec.h b/media/codecs/raw/C2SoftRawDec.h deleted file mode 100644 index 7dfdec5..0000000 --- a/media/codecs/raw/C2SoftRawDec.h +++ /dev/null @@ -1,53 +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 ANDROID_C2_SOFT_RAW_DEC_H_ -#define ANDROID_C2_SOFT_RAW_DEC_H_ - -#include <SimpleC2Component.h> - - -namespace android { - -struct C2SoftRawDec : public SimpleC2Component { - class IntfImpl; - - C2SoftRawDec(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - virtual ~C2SoftRawDec(); - - // 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: - std::shared_ptr<IntfImpl> mIntf; - bool mSignalledEos; - - C2_DO_NOT_COPY(C2SoftRawDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_RAW_DEC_H_ diff --git a/media/codecs/raw/MODULE_LICENSE_APACHE2 b/media/codecs/raw/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/raw/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/raw/NOTICE b/media/codecs/raw/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/raw/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/vorbis/Android.bp b/media/codecs/vorbis/Android.bp deleted file mode 100644 index 7477da6..0000000 --- a/media/codecs/vorbis/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2vorbisdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftVorbisDec.cpp"], - - shared_libs: ["libvorbisidec"], -} diff --git a/media/codecs/vorbis/C2SoftVorbisDec.cpp b/media/codecs/vorbis/C2SoftVorbisDec.cpp deleted file mode 100644 index 280ae36..0000000 --- a/media/codecs/vorbis/C2SoftVorbisDec.cpp +++ /dev/null @@ -1,493 +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 "C2SoftVorbisDec" -#include <log/log.h> - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftVorbisDec.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 COMPONENT_NAME[] = "c2.android.vorbis.decoder"; - -class C2SoftVorbisDec::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_VORBIS)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 48000)) - .withFields({C2F(mSampleRate, value).inRange(8000, 96000)}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).inRange(1, 8)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(32000, 500000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192 * 2 * sizeof(int16_t))) - .build()); - } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; -}; - -C2SoftVorbisDec::C2SoftVorbisDec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mState(nullptr), - mVi(nullptr) { -} - -C2SoftVorbisDec::~C2SoftVorbisDec() { - onRelease(); -} - -c2_status_t C2SoftVorbisDec::onInit() { - status_t err = initDecoder(); - return err == OK ? C2_OK : C2_NO_MEMORY; -} - -c2_status_t C2SoftVorbisDec::onStop() { - if (mState) { - vorbis_dsp_clear(mState); - delete mState; - mState = nullptr; - } - - if (mVi) { - vorbis_info_clear(mVi); - delete mVi; - mVi = nullptr; - } - mNumFramesLeftOnPage = -1; - mSignalledOutputEos = false; - mSignalledError = false; - - return (initDecoder() == OK ? C2_OK : C2_CORRUPTED); -} - -void C2SoftVorbisDec::onReset() { - (void)onStop(); -} - -void C2SoftVorbisDec::onRelease() { - if (mState) { - vorbis_dsp_clear(mState); - delete mState; - mState = nullptr; - } - - if (mVi) { - vorbis_info_clear(mVi); - delete mVi; - mVi = nullptr; - } -} - -status_t C2SoftVorbisDec::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; - mSignalledError = false; - mSignalledOutputEos = false; - mInfoUnpacked = false; - mBooksUnpacked = false; - return OK; -} - -c2_status_t C2SoftVorbisDec::onFlush_sm() { - mNumFramesLeftOnPage = -1; - mSignalledOutputEos = false; - if (mState) vorbis_dsp_restart(mState); - - return C2_OK; -} - -c2_status_t C2SoftVorbisDec::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 C2SoftVorbisDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - size_t inOffset = 0u; - size_t inSize = 0u; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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; - int32_t numChannels = mVi->channels; - int32_t samplingRate = mVi->rate; - if (inSize > 7 && !memcmp(&data[1], "vorbis", 6)) { - if ((data[0] != 1) && (data[0] != 5)) { - ALOGE("unexpected type received %d", data[0]); - 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 (data[0] == 1) { - 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 != samplingRate || - mVi->channels != numChannels) { - ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels); - samplingRate = mVi->rate; - numChannels = mVi->channels; - - C2StreamSampleRateInfo::output sampleRateInfo(0u, samplingRate); - C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config( - { &sampleRateInfo, &channelCountInfo }, - C2_MAY_BLOCK, - &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(sampleRateInfo)); - work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(channelCountInfo)); - } else { - ALOGE("Config Update failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - mInfoUnpacked = true; - } else { - if (!mInfoUnpacked) { - ALOGE("Data with type:5 sent before sending type:1"); - 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; - } - mBooksUnpacked = true; - } - fillEmptyWork(work); - if (eos) { - mSignalledOutputEos = true; - ALOGV("signalled EOS"); - } - return; - } - - if (!mInfoUnpacked || !mBooksUnpacked) { - ALOGE("Missing CODEC_CONFIG data mInfoUnpacked: %d mBooksUnpack %d", mInfoUnpacked, mBooksUnpacked); - mSignalledError = true; - work->result = C2_CORRUPTED; - 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: - C2SoftVorbisDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftVorbisDec(COMPONENT_NAME, - id, - std::make_shared<C2SoftVorbisDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftVorbisDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftVorbisDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftVorbisDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/vorbis/C2SoftVorbisDec.h b/media/codecs/vorbis/C2SoftVorbisDec.h deleted file mode 100644 index 3bf7326..0000000 --- a/media/codecs/vorbis/C2SoftVorbisDec.h +++ /dev/null @@ -1,70 +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 ANDROID_C2_SOFT_VORBIS_DEC_H_ -#define ANDROID_C2_SOFT_VORBIS_DEC_H_ - -#include <SimpleC2Component.h> - - -struct vorbis_dsp_state; -struct vorbis_info; - -namespace android { - -struct C2SoftVorbisDec : public SimpleC2Component { - class IntfImpl; - - C2SoftVorbisDec(const char *name, c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl); - virtual ~C2SoftVorbisDec(); - - // 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, - }; - - std::shared_ptr<IntfImpl> mIntf; - vorbis_dsp_state *mState; - vorbis_info *mVi; - - int32_t mNumFramesLeftOnPage; - bool mSignalledError; - bool mSignalledOutputEos; - bool mInfoUnpacked; - bool mBooksUnpacked; - status_t initDecoder(); - - C2_DO_NOT_COPY(C2SoftVorbisDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_VORBIS_DEC_H_ - diff --git a/media/codecs/vorbis/MODULE_LICENSE_APACHE2 b/media/codecs/vorbis/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/vorbis/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/vorbis/NOTICE b/media/codecs/vorbis/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/codecs/vorbis/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/vpx/Android.bp b/media/codecs/vpx/Android.bp deleted file mode 100644 index cc83371..0000000 --- a/media/codecs/vpx/Android.bp +++ /dev/null @@ -1,60 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2vp9dec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftVpxDec.cpp"], - - shared_libs: ["libvpx"], - - cflags: [ - "-DVP9", - ], -} - -cc_library_shared { - name: "libstagefright_soft_c2vp8dec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftVpxDec.cpp"], - - shared_libs: ["libvpx"], -} - -cc_library_shared { - name: "libstagefright_soft_c2vp9enc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: [ - "C2SoftVp9Enc.cpp", - "C2SoftVpxEnc.cpp", - ], - - shared_libs: ["libvpx"], - - cflags: ["-DVP9"], -} - -cc_library_shared { - name: "libstagefright_soft_c2vp8enc", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: [ - "C2SoftVp8Enc.cpp", - "C2SoftVpxEnc.cpp", - ], - - shared_libs: ["libvpx"], -} - diff --git a/media/codecs/vpx/C2SoftVp8Enc.cpp b/media/codecs/vpx/C2SoftVp8Enc.cpp deleted file mode 100644 index 0ae717a..0000000 --- a/media/codecs/vpx/C2SoftVp8Enc.cpp +++ /dev/null @@ -1,114 +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 "C2SoftVp8Enc" -#include <utils/Log.h> -#include <utils/misc.h> - -#include "C2SoftVp8Enc.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.vp8.encoder"; - -C2SoftVp8Enc::C2SoftVp8Enc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : C2SoftVpxEnc(name, id, intfImpl), mDCTPartitions(0), mProfile(1) {} - -void C2SoftVp8Enc::setCodecSpecificInterface() { - mCodecInterface = vpx_codec_vp8_cx(); -} - -void C2SoftVp8Enc::setCodecSpecificConfiguration() { - switch (mProfile) { - case 1: - mCodecConfiguration->g_profile = 0; - break; - - case 2: - mCodecConfiguration->g_profile = 1; - break; - - case 4: - mCodecConfiguration->g_profile = 2; - break; - - case 8: - mCodecConfiguration->g_profile = 3; - break; - - default: - mCodecConfiguration->g_profile = 0; - } -} - -vpx_codec_err_t C2SoftVp8Enc::setCodecSpecificControls() { - vpx_codec_err_t codec_return = vpx_codec_control(mCodecContext, - VP8E_SET_TOKEN_PARTITIONS, - mDCTPartitions); - if (codec_return != VPX_CODEC_OK) { - ALOGE("Error setting dct partitions for vpx encoder."); - } - return codec_return; -} - -class C2SoftVp8EncFactory : public C2ComponentFactory { -public: - C2SoftVp8EncFactory() - : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) {} - - 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 C2SoftVp8Enc(COMPONENT_NAME, id, - std::make_shared<C2SoftVpxEnc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftVpxEnc::IntfImpl>( - COMPONENT_NAME, id, - std::make_shared<C2SoftVpxEnc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftVp8EncFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // namespace android - -extern "C" ::C2ComponentFactory* CreateCodec2Factory() { - ALOGV("in %s", __func__); - return new ::android::C2SoftVp8EncFactory(); -} - -extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) { - ALOGV("in %s", __func__); - delete factory; -} diff --git a/media/codecs/vpx/C2SoftVp8Enc.h b/media/codecs/vpx/C2SoftVp8Enc.h deleted file mode 100644 index ed6f356..0000000 --- a/media/codecs/vpx/C2SoftVp8Enc.h +++ /dev/null @@ -1,60 +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 ANDROID_C2_SOFT_VP8_ENC_H__ -#define ANDROID_C2_SOFT_VP8_ENC_H__ - -#include "C2SoftVpxEnc.h" - -namespace android { - -// Exposes vp8 encoder as a c2 Component -// -// In addition to the base class settings, Only following encoder settings are -// available: -// - token partitioning -struct C2SoftVp8Enc : public C2SoftVpxEnc { - C2SoftVp8Enc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - - protected: - // Populates |mCodecInterface| with codec specific settings. - virtual void setCodecSpecificInterface(); - - // Sets codec specific configuration. - virtual void setCodecSpecificConfiguration(); - - // Initializes codec specific encoder settings. - virtual vpx_codec_err_t setCodecSpecificControls(); - - private: - // Max value supported for DCT partitions - static const uint32_t kMaxDCTPartitions = 3; - - // vp8 specific configuration parameter - // that enables token partitioning of - // the stream into substreams - int32_t mDCTPartitions; - - // C2 Profile parameter - int32_t mProfile; - - C2_DO_NOT_COPY(C2SoftVp8Enc); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_VP8_ENC_H__ diff --git a/media/codecs/vpx/C2SoftVp9Enc.cpp b/media/codecs/vpx/C2SoftVp9Enc.cpp deleted file mode 100644 index b26170f..0000000 --- a/media/codecs/vpx/C2SoftVp9Enc.cpp +++ /dev/null @@ -1,144 +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 "C2SoftVp9Enc" -#include <utils/Log.h> -#include <utils/misc.h> - -#include "C2SoftVp9Enc.h" - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.vp9.encoder"; - -C2SoftVp9Enc::C2SoftVp9Enc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : C2SoftVpxEnc(name, id, intfImpl), - mProfile(1), - mLevel(0), - mTileColumns(0), - mFrameParallelDecoding(false) { -} - -void C2SoftVp9Enc::setCodecSpecificInterface() { - mCodecInterface = vpx_codec_vp9_cx(); -} - -void C2SoftVp9Enc::setCodecSpecificConfiguration() { - switch (mProfile) { - case 1: - mCodecConfiguration->g_profile = 0; - break; - - case 2: - mCodecConfiguration->g_profile = 1; - break; - - case 4: - mCodecConfiguration->g_profile = 2; - break; - - case 8: - mCodecConfiguration->g_profile = 3; - break; - - default: - mCodecConfiguration->g_profile = 0; - } -} - -vpx_codec_err_t C2SoftVp9Enc::setCodecSpecificControls() { - vpx_codec_err_t codecReturn = vpx_codec_control( - mCodecContext, VP9E_SET_TILE_COLUMNS, mTileColumns); - if (codecReturn != VPX_CODEC_OK) { - ALOGE("Error setting VP9E_SET_TILE_COLUMNS to %d. vpx_codec_control() " - "returned %d", mTileColumns, codecReturn); - return codecReturn; - } - codecReturn = vpx_codec_control( - mCodecContext, VP9E_SET_FRAME_PARALLEL_DECODING, - mFrameParallelDecoding); - if (codecReturn != VPX_CODEC_OK) { - ALOGE("Error setting VP9E_SET_FRAME_PARALLEL_DECODING to %d." - "vpx_codec_control() returned %d", mFrameParallelDecoding, - codecReturn); - return codecReturn; - } - codecReturn = vpx_codec_control(mCodecContext, VP9E_SET_ROW_MT, 1); - if (codecReturn != VPX_CODEC_OK) { - ALOGE("Error setting VP9E_SET_ROW_MT to 1. vpx_codec_control() " - "returned %d", codecReturn); - return codecReturn; - } - - // For VP9, we always set CPU_USED to 8 (because the realtime default is 0 - // which is too slow). - codecReturn = vpx_codec_control(mCodecContext, VP8E_SET_CPUUSED, 8); - if (codecReturn != VPX_CODEC_OK) { - ALOGE("Error setting VP8E_SET_CPUUSED to 8. vpx_codec_control() " - "returned %d", codecReturn); - return codecReturn; - } - return codecReturn; -} - -class C2SoftVp9EncFactory : public C2ComponentFactory { -public: - C2SoftVp9EncFactory() - : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) {} - - 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 C2SoftVp9Enc(COMPONENT_NAME, id, - std::make_shared<C2SoftVpxEnc::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftVpxEnc::IntfImpl>( - COMPONENT_NAME, id, - std::make_shared<C2SoftVpxEnc::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftVp9EncFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // namespace android - -extern "C" ::C2ComponentFactory* CreateCodec2Factory() { - ALOGV("in %s", __func__); - return new ::android::C2SoftVp9EncFactory(); -} - -extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) { - ALOGV("in %s", __func__); - delete factory; -} diff --git a/media/codecs/vpx/C2SoftVp9Enc.h b/media/codecs/vpx/C2SoftVp9Enc.h deleted file mode 100644 index 77ef8fd..0000000 --- a/media/codecs/vpx/C2SoftVp9Enc.h +++ /dev/null @@ -1,59 +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 ANDROID_C2_SOFT_VP9_ENC_H__ -#define ANDROID_C2_SOFT_VP9_ENC_H__ - -#include "C2SoftVpxEnc.h" - -namespace android { - -// Exposes vp9 encoder as a c2 Component -// -// In addition to the base class settings, Only following encoder settings are -// available: -// - tile rows -// - tile columns -// - frame parallel mode -struct C2SoftVp9Enc : public C2SoftVpxEnc { - C2SoftVp9Enc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - - protected: - // Populates |mCodecInterface| with codec specific settings. - virtual void setCodecSpecificInterface(); - - // Sets codec specific configuration. - virtual void setCodecSpecificConfiguration(); - - // Initializes codec specific encoder settings. - virtual vpx_codec_err_t setCodecSpecificControls(); - - private: - // C2 Profile & Level parameter - int32_t mProfile; - int32_t mLevel __unused; - - int32_t mTileColumns; - - bool mFrameParallelDecoding; - - C2_DO_NOT_COPY(C2SoftVp9Enc); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_VP9_ENC_H__ diff --git a/media/codecs/vpx/C2SoftVpxDec.cpp b/media/codecs/vpx/C2SoftVpxDec.cpp deleted file mode 100644 index 8ecbf5d..0000000 --- a/media/codecs/vpx/C2SoftVpxDec.cpp +++ /dev/null @@ -1,697 +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 "C2SoftVpxDec" -#include <log/log.h> - -#include <media/stagefright/foundation/AUtils.h> -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftVpxDec.h" - -namespace android { - -#ifdef VP9 -constexpr char COMPONENT_NAME[] = "c2.android.vp9.decoder"; -#else -constexpr char COMPONENT_NAME[] = "c2.android.vp8.decoder"; -#endif - -class C2SoftVpxDec::IntfImpl : public SimpleInterface<void>::BaseParams { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : SimpleInterface<void>::BaseParams( - helper, - COMPONENT_NAME, - C2Component::KIND_DECODER, - C2Component::DOMAIN_VIDEO, -#ifdef VP9 - MEDIA_MIMETYPE_VIDEO_VP9 -#else - MEDIA_MIMETYPE_VIDEO_VP8 -#endif - ) { - noPrivateBuffers(); // TODO: account for our buffers here - noInputReferences(); - noOutputReferences(); - noInputLatency(); - noTimeStretch(); - - // TODO: output latency and reordering - - addParameter( - DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES) - .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL)) - .build()); - - addParameter( - DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE) - .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 2048, 2), - C2F(mSize, height).inRange(2, 2048, 2), - }) - .withSetter(SizeSetter) - .build()); - -#ifdef VP9 - // TODO: Add C2Config::PROFILE_VP9_2HDR ?? - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_VP9_0, C2Config::LEVEL_VP9_5)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_VP9_0, - C2Config::PROFILE_VP9_2}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_VP9_1, - C2Config::LEVEL_VP9_1_1, - C2Config::LEVEL_VP9_2, - C2Config::LEVEL_VP9_2_1, - C2Config::LEVEL_VP9_3, - C2Config::LEVEL_VP9_3_1, - C2Config::LEVEL_VP9_4, - C2Config::LEVEL_VP9_4_1, - C2Config::LEVEL_VP9_5, - }) - }) - .withSetter(ProfileLevelSetter, mSize) - .build()); - - mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0); - addParameter( - DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO) - .withDefault(mHdr10PlusInfoInput) - .withFields({ - C2F(mHdr10PlusInfoInput, m.value).any(), - }) - .withSetter(Hdr10PlusInfoInputSetter) - .build()); - - mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0); - addParameter( - DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO) - .withDefault(mHdr10PlusInfoOutput) - .withFields({ - C2F(mHdr10PlusInfoOutput, m.value).any(), - }) - .withSetter(Hdr10PlusInfoOutputSetter) - .build()); - -#if 0 - // sample BT.2020 static info - mHdrStaticInfo = std::make_shared<C2StreamHdrStaticInfo::output>(); - mHdrStaticInfo->mastering = { - .red = { .x = 0.708, .y = 0.292 }, - .green = { .x = 0.170, .y = 0.797 }, - .blue = { .x = 0.131, .y = 0.046 }, - .white = { .x = 0.3127, .y = 0.3290 }, - .maxLuminance = 1000, - .minLuminance = 0.1, - }; - mHdrStaticInfo->maxCll = 1000; - mHdrStaticInfo->maxFall = 120; - - mHdrStaticInfo->maxLuminance = 0; // disable static info - - helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>(); - addParameter( - DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO) - .withDefault(mHdrStaticInfo) - .withFields({ - C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1), - // TODO - }) - .withSetter(HdrStaticInfoSetter) - .build()); -#endif -#else - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withConstValue(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_UNUSED, C2Config::LEVEL_UNUSED)) - .build()); -#endif - - addParameter( - DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE) - .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 2048, 2), - C2F(mSize, height).inRange(2, 2048, 2), - }) - .withSetter(MaxPictureSizeSetter, mSize) - .build()); - - addParameter( - DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4)) - .withFields({ - C2F(mMaxInputSize, value).any(), - }) - .calculatedAs(MaxInputSizeSetter, mMaxSize) - .build()); - - C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() }; - std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - 1u, 0u, 8u /* bitDepth */, C2Color::YUV_420); - memcpy(defaultColorInfo->m.locations, locations, sizeof(locations)); - - defaultColorInfo = - C2StreamColorInfo::output::AllocShared( - { C2ChromaOffsetStruct::ITU_YUV_420_0() }, - 0u, 8u /* bitDepth */, C2Color::YUV_420); - helper->addStructDescriptors<C2ChromaOffsetStruct>(); - - addParameter( - DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO) - .withConstValue(defaultColorInfo) - .build()); - - // TODO: support more formats? - addParameter( - DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT) - .withConstValue(new C2StreamPixelFormatInfo::output( - 0u, HAL_PIXEL_FORMAT_YCBCR_420_888)) - .build()); - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe, - C2P<C2VideoSizeStreamInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - // TODO: get max width/height from the size's field helpers vs. hardcoding - me.set().width = c2_min(c2_max(me.v.width, size.v.width), 2048u); - me.set().height = c2_min(c2_max(me.v.height, size.v.height), 2048u); - return C2R::Ok(); - } - - static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me, - const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) { - (void)mayBlock; - // assume compression ratio of 2 - me.set().value = (((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072); - return C2R::Ok(); - } - - - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me, - const C2P<C2StreamPictureSizeInfo::output> &size) { - (void)mayBlock; - (void)size; - (void)me; // TODO: validate - return C2R::Ok(); - } - - static C2R Hdr10PlusInfoInputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::input> &me) { - (void)mayBlock; - (void)me; // TODO: validate - return C2R::Ok(); - } - - static C2R Hdr10PlusInfoOutputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::output> &me) { - (void)mayBlock; - (void)me; // TODO: validate - return C2R::Ok(); - } - -private: - std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; - std::shared_ptr<C2StreamPictureSizeInfo::output> mSize; - std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize; - std::shared_ptr<C2StreamColorInfo::output> mColorInfo; - std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat; -#ifdef VP9 -#if 0 - std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo; -#endif - std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput; - std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput; -#endif -}; - -C2SoftVpxDec::C2SoftVpxDec( - const char *name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mCodecCtx(nullptr) { -} - -C2SoftVpxDec::~C2SoftVpxDec() { - onRelease(); -} - -c2_status_t C2SoftVpxDec::onInit() { - status_t err = initDecoder(); - return err == OK ? C2_OK : C2_CORRUPTED; -} - -c2_status_t C2SoftVpxDec::onStop() { - mSignalledError = false; - mSignalledOutputEos = false; - - return C2_OK; -} - -void C2SoftVpxDec::onReset() { - (void)onStop(); - c2_status_t err = onFlush_sm(); - if (err != C2_OK) - { - ALOGW("Failed to flush decoder. Try to hard reset decoder"); - destroyDecoder(); - (void)initDecoder(); - } -} - -void C2SoftVpxDec::onRelease() { - destroyDecoder(); -} - -c2_status_t C2SoftVpxDec::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 C2SoftVpxDec::initDecoder() { -#ifdef VP9 - mMode = MODE_VP9; -#else - mMode = MODE_VP8; -#endif - - mWidth = 320; - mHeight = 240; - mFrameParallelMode = false; - mSignalledOutputEos = false; - mSignalledError = false; - - if (!mCodecCtx) { - mCodecCtx = new vpx_codec_ctx_t; - } - if (!mCodecCtx) { - ALOGE("mCodecCtx is null"); - return NO_MEMORY; - } - - 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 C2SoftVpxDec::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 C2SoftVpxDec::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, intf = this->mIntf]( - 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; - - for (const std::unique_ptr<C2Param> ¶m: work->input.configUpdate) { - if (param) { - C2StreamHdr10PlusInfo::input *hdr10PlusInfo = - C2StreamHdr10PlusInfo::input::From(param.get()); - - if (hdr10PlusInfo != nullptr) { - std::vector<std::unique_ptr<C2SettingResult>> failures; - std::unique_ptr<C2Param> outParam = C2Param::CopyAsStream( - *param.get(), true /*output*/, param->stream()); - c2_status_t err = intf->config( - { outParam.get() }, C2_MAY_BLOCK, &failures); - if (err == C2_OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(*outParam.get())); - } else { - ALOGE("finishWork: Config update size failed"); - } - break; - } - } - } - }; - if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) { - fillWork(work); - } else { - finish(index, fillWork); - } -} - -void C2SoftVpxDec::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 0u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - - size_t inOffset = 0u; - size_t inSize = 0u; - C2ReadView rView = mDummyReadView; - if (!work->input.buffers.empty()) { - rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); - inSize = rView.capacity(); - 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"); - } - } - - int64_t frameIndex = work->input.ordinal.frameIndex.peekll(); - - if (inSize) { - uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset); - 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); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - 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 C2SoftVpxDec::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; - - if (img->d_w != mWidth || img->d_h != mHeight) { - mWidth = img->d_w; - mHeight = img->d_h; - - C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures); - if (err == C2_OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(size)); - } else { - ALOGE("Config update size failed"); - mSignalledError = true; - work->workletsProcessed = 1u; - work->result = C2_CORRUPTED; - return false; - } - - } - 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 C2SoftVpxDec::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 C2SoftVpxDec::drain( - uint32_t drainMode, - const std::shared_ptr<C2BlockPool> &pool) { - return drainInternal(drainMode, pool, nullptr); -} - -class C2SoftVpxFactory : public C2ComponentFactory { -public: - C2SoftVpxFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftVpxDec(COMPONENT_NAME, id, - std::make_shared<C2SoftVpxDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftVpxDec::IntfImpl>( - COMPONENT_NAME, id, - std::make_shared<C2SoftVpxDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftVpxFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // 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/codecs/vpx/C2SoftVpxDec.h b/media/codecs/vpx/C2SoftVpxDec.h deleted file mode 100644 index 60c8484..0000000 --- a/media/codecs/vpx/C2SoftVpxDec.h +++ /dev/null @@ -1,79 +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 ANDROID_C2_SOFT_VPX_DEC_H_ -#define ANDROID_C2_SOFT_VPX_DEC_H_ - -#include <SimpleC2Component.h> - - -#include "vpx/vpx_decoder.h" -#include "vpx/vp8dx.h" - -namespace android { - -struct C2SoftVpxDec : public SimpleC2Component { - class IntfImpl; - - C2SoftVpxDec(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - virtual ~C2SoftVpxDec(); - - // 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; - - std::shared_ptr<IntfImpl> mIntf; - 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); - - C2_DO_NOT_COPY(C2SoftVpxDec); -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_VPX_DEC_H_ diff --git a/media/codecs/vpx/C2SoftVpxEnc.cpp b/media/codecs/vpx/C2SoftVpxEnc.cpp deleted file mode 100644 index 155a84f..0000000 --- a/media/codecs/vpx/C2SoftVpxEnc.cpp +++ /dev/null @@ -1,670 +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 "C2SoftVpxEnc" -#include <log/log.h> -#include <utils/misc.h> - -#include <media/hardware/VideoAPI.h> - -#include <Codec2BufferUtils.h> -#include <C2Debug.h> -#include "C2SoftVpxEnc.h" - -#ifndef INT32_MAX -#define INT32_MAX 2147483647 -#endif - -namespace android { - -#if 0 -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; -} -#endif - -C2SoftVpxEnc::C2SoftVpxEnc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl) - : SimpleC2Component( - std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mCodecContext(nullptr), - mCodecConfiguration(nullptr), - mCodecInterface(nullptr), - mStrideAlign(2), - mColorFormat(VPX_IMG_FMT_I420), - mBitrateControlMode(VPX_VBR), - mErrorResilience(false), - mMinQuantizer(0), - mMaxQuantizer(0), - mTemporalLayers(0), - mTemporalPatternType(VPXTemporalLayerPatternNone), - mTemporalPatternLength(0), - mTemporalPatternIdx(0), - mLastTimestamp(0x7FFFFFFFFFFFFFFFull), - mSignalledOutputEos(false), - mSignalledError(false) { - memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio)); - mTemporalLayerBitrateRatio[0] = 100; -} - -C2SoftVpxEnc::~C2SoftVpxEnc() { - onRelease(); -} - -c2_status_t C2SoftVpxEnc::onInit() { - status_t err = initEncoder(); - return err == OK ? C2_OK : C2_CORRUPTED; -} - -void C2SoftVpxEnc::onRelease() { - if (mCodecContext) { - vpx_codec_destroy(mCodecContext); - delete mCodecContext; - mCodecContext = nullptr; - } - - if (mCodecConfiguration) { - delete mCodecConfiguration; - mCodecConfiguration = nullptr; - } - - // this one is not allocated by us - mCodecInterface = nullptr; -} - -c2_status_t C2SoftVpxEnc::onStop() { - onRelease(); - mLastTimestamp = 0x7FFFFFFFFFFFFFFFLL; - mSignalledOutputEos = false; - mSignalledError = false; - return C2_OK; -} - -void C2SoftVpxEnc::onReset() { - (void)onStop(); -} - -c2_status_t C2SoftVpxEnc::onFlush_sm() { - return onStop(); -} - -status_t C2SoftVpxEnc::initEncoder() { - vpx_codec_err_t codec_return; - status_t result = UNKNOWN_ERROR; - { - IntfImpl::Lock lock = mIntf->lock(); - mSize = mIntf->getSize_l(); - mBitrate = mIntf->getBitrate_l(); - mBitrateMode = mIntf->getBitrateMode_l(); - mFrameRate = mIntf->getFrameRate_l(); - mIntraRefresh = mIntf->getIntraRefresh_l(); - mRequestSync = mIntf->getRequestSync_l(); - mTemporalLayers = mIntf->getTemporalLayers_l()->m.layerCount; - } - - switch (mBitrateMode->value) { - case C2Config::BITRATE_VARIABLE: - mBitrateControlMode = VPX_VBR; - break; - case C2Config::BITRATE_CONST: - default: - mBitrateControlMode = VPX_CBR; - break; - break; - } - - setCodecSpecificInterface(); - if (!mCodecInterface) goto CleanUp; - - ALOGD("VPx: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u", - (uint32_t)mBitrateControlMode, mTemporalLayers, mIntf->getSyncFramePeriod(), - mMinQuantizer, mMaxQuantizer); - - mCodecConfiguration = new vpx_codec_enc_cfg_t; - if (!mCodecConfiguration) goto CleanUp; - codec_return = vpx_codec_enc_config_default(mCodecInterface, - mCodecConfiguration, - 0); - if (codec_return != VPX_CODEC_OK) { - ALOGE("Error populating default configuration for vpx encoder."); - goto CleanUp; - } - - mCodecConfiguration->g_w = mSize->width; - mCodecConfiguration->g_h = mSize->height; - //mCodecConfiguration->g_threads = getCpuCoreCount(); - mCodecConfiguration->g_threads = 0; - mCodecConfiguration->g_error_resilient = mErrorResilience; - - // timebase unit is microsecond - // g_timebase is in seconds (i.e. 1/1000000 seconds) - mCodecConfiguration->g_timebase.num = 1; - mCodecConfiguration->g_timebase.den = 1000000; - // rc_target_bitrate is in kbps, mBitrate in bps - mCodecConfiguration->rc_target_bitrate = (mBitrate->value + 500) / 1000; - mCodecConfiguration->rc_end_usage = mBitrateControlMode; - // Disable frame drop - not allowed in MediaCodec now. - mCodecConfiguration->rc_dropframe_thresh = 0; - // Disable lagged encoding. - mCodecConfiguration->g_lag_in_frames = 0; - if (mBitrateControlMode == VPX_CBR) { - // Disable spatial resizing. - mCodecConfiguration->rc_resize_allowed = 0; - // Single-pass mode. - mCodecConfiguration->g_pass = VPX_RC_ONE_PASS; - // Maximum amount of bits that can be subtracted from the target - // bitrate - expressed as percentage of the target bitrate. - mCodecConfiguration->rc_undershoot_pct = 100; - // Maximum amount of bits that can be added to the target - // bitrate - expressed as percentage of the target bitrate. - mCodecConfiguration->rc_overshoot_pct = 15; - // Initial value of the buffer level in ms. - mCodecConfiguration->rc_buf_initial_sz = 500; - // Amount of data that the encoder should try to maintain in ms. - mCodecConfiguration->rc_buf_optimal_sz = 600; - // The amount of data that may be buffered by the decoding - // application in ms. - mCodecConfiguration->rc_buf_sz = 1000; - // Enable error resilience - needed for packet loss. - mCodecConfiguration->g_error_resilient = 1; - // Maximum key frame interval - for CBR boost to 3000 - mCodecConfiguration->kf_max_dist = 3000; - // Encoder determines optimal key frame placement automatically. - mCodecConfiguration->kf_mode = VPX_KF_AUTO; - } - - // Frames temporal pattern - for now WebRTC like pattern is only supported. - switch (mTemporalLayers) { - case 0: - mTemporalPatternLength = 0; - break; - case 1: - mCodecConfiguration->ts_number_layers = 1; - mCodecConfiguration->ts_rate_decimator[0] = 1; - mCodecConfiguration->ts_periodicity = 1; - mCodecConfiguration->ts_layer_id[0] = 0; - mTemporalPattern[0] = kTemporalUpdateLastRefAll; - mTemporalPatternLength = 1; - break; - case 2: - mCodecConfiguration->ts_number_layers = 2; - mCodecConfiguration->ts_rate_decimator[0] = 2; - mCodecConfiguration->ts_rate_decimator[1] = 1; - mCodecConfiguration->ts_periodicity = 2; - mCodecConfiguration->ts_layer_id[0] = 0; - mCodecConfiguration->ts_layer_id[1] = 1; - mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef; - mTemporalPattern[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; - mTemporalPattern[2] = kTemporalUpdateLastRefAltRef; - mTemporalPattern[3] = kTemporalUpdateGoldenRefAltRef; - mTemporalPattern[4] = kTemporalUpdateLastRefAltRef; - mTemporalPattern[5] = kTemporalUpdateGoldenRefAltRef; - mTemporalPattern[6] = kTemporalUpdateLastRefAltRef; - mTemporalPattern[7] = kTemporalUpdateNone; - mTemporalPatternLength = 8; - break; - case 3: - mCodecConfiguration->ts_number_layers = 3; - mCodecConfiguration->ts_rate_decimator[0] = 4; - mCodecConfiguration->ts_rate_decimator[1] = 2; - mCodecConfiguration->ts_rate_decimator[2] = 1; - mCodecConfiguration->ts_periodicity = 4; - mCodecConfiguration->ts_layer_id[0] = 0; - mCodecConfiguration->ts_layer_id[1] = 2; - mCodecConfiguration->ts_layer_id[2] = 1; - mCodecConfiguration->ts_layer_id[3] = 2; - mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef; - mTemporalPattern[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef; - mTemporalPattern[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; - mTemporalPattern[3] = kTemporalUpdateNone; - mTemporalPattern[4] = kTemporalUpdateLastRefAltRef; - mTemporalPattern[5] = kTemporalUpdateNone; - mTemporalPattern[6] = kTemporalUpdateGoldenRefAltRef; - mTemporalPattern[7] = kTemporalUpdateNone; - mTemporalPatternLength = 8; - break; - default: - ALOGE("Wrong number of temporal layers %zu", mTemporalLayers); - goto CleanUp; - } - // Set bitrate values for each layer - for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) { - mCodecConfiguration->ts_target_bitrate[i] = - mCodecConfiguration->rc_target_bitrate * - mTemporalLayerBitrateRatio[i] / 100; - } - if (mIntf->getSyncFramePeriod() >= 0) { - mCodecConfiguration->kf_max_dist = mIntf->getSyncFramePeriod(); - mCodecConfiguration->kf_min_dist = mIntf->getSyncFramePeriod(); - mCodecConfiguration->kf_mode = VPX_KF_AUTO; - } - if (mMinQuantizer > 0) { - mCodecConfiguration->rc_min_quantizer = mMinQuantizer; - } - if (mMaxQuantizer > 0) { - mCodecConfiguration->rc_max_quantizer = mMaxQuantizer; - } - setCodecSpecificConfiguration(); - mCodecContext = new vpx_codec_ctx_t; - if (!mCodecContext) goto CleanUp; - codec_return = vpx_codec_enc_init(mCodecContext, - mCodecInterface, - mCodecConfiguration, - 0); // flags - if (codec_return != VPX_CODEC_OK) { - ALOGE("Error initializing vpx encoder"); - goto CleanUp; - } - - // Extra CBR settings - if (mBitrateControlMode == VPX_CBR) { - codec_return = vpx_codec_control(mCodecContext, - VP8E_SET_STATIC_THRESHOLD, - 1); - if (codec_return == VPX_CODEC_OK) { - uint32_t rc_max_intra_target = - (uint32_t)(mCodecConfiguration->rc_buf_optimal_sz * mFrameRate->value / 20 + 0.5); - // Don't go below 3 times per frame bandwidth. - if (rc_max_intra_target < 300) { - rc_max_intra_target = 300; - } - codec_return = vpx_codec_control(mCodecContext, - VP8E_SET_MAX_INTRA_BITRATE_PCT, - rc_max_intra_target); - } - if (codec_return == VPX_CODEC_OK) { - codec_return = vpx_codec_control(mCodecContext, - VP8E_SET_CPUUSED, - -8); - } - if (codec_return != VPX_CODEC_OK) { - ALOGE("Error setting cbr parameters for vpx encoder."); - goto CleanUp; - } - } - - codec_return = setCodecSpecificControls(); - if (codec_return != VPX_CODEC_OK) goto CleanUp; - - { - uint32_t width = mSize->width; - uint32_t height = mSize->height; - if (((uint64_t)width * height) > - ((uint64_t)INT32_MAX / 3)) { - ALOGE("b/25812794, Buffer size is too big, width=%u, height=%u.", width, height); - } else { - uint32_t stride = (width + mStrideAlign - 1) & ~(mStrideAlign - 1); - uint32_t vstride = (height + mStrideAlign - 1) & ~(mStrideAlign - 1); - mConversionBuffer = MemoryBlock::Allocate(stride * vstride * 3 / 2); - if (!mConversionBuffer.size()) { - ALOGE("Allocating conversion buffer failed."); - } else { - mNumInputFrames = -1; - return OK; - } - } - } - -CleanUp: - onRelease(); - return result; -} - -vpx_enc_frame_flags_t C2SoftVpxEnc::getEncodeFlags() { - vpx_enc_frame_flags_t flags = 0; - if (mTemporalPatternLength > 0) { - int patternIdx = mTemporalPatternIdx % mTemporalPatternLength; - mTemporalPatternIdx++; - switch (mTemporalPattern[patternIdx]) { - case kTemporalUpdateLast: - flags |= VP8_EFLAG_NO_UPD_GF; - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_REF_GF; - flags |= VP8_EFLAG_NO_REF_ARF; - break; - case kTemporalUpdateGoldenWithoutDependency: - flags |= VP8_EFLAG_NO_REF_GF; - [[fallthrough]]; - case kTemporalUpdateGolden: - flags |= VP8_EFLAG_NO_REF_ARF; - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_UPD_LAST; - break; - case kTemporalUpdateAltrefWithoutDependency: - flags |= VP8_EFLAG_NO_REF_ARF; - flags |= VP8_EFLAG_NO_REF_GF; - [[fallthrough]]; - case kTemporalUpdateAltref: - flags |= VP8_EFLAG_NO_UPD_GF; - flags |= VP8_EFLAG_NO_UPD_LAST; - break; - case kTemporalUpdateNoneNoRefAltref: - flags |= VP8_EFLAG_NO_REF_ARF; - [[fallthrough]]; - case kTemporalUpdateNone: - flags |= VP8_EFLAG_NO_UPD_GF; - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_UPD_LAST; - flags |= VP8_EFLAG_NO_UPD_ENTROPY; - break; - case kTemporalUpdateNoneNoRefGoldenRefAltRef: - flags |= VP8_EFLAG_NO_REF_GF; - flags |= VP8_EFLAG_NO_UPD_GF; - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_UPD_LAST; - flags |= VP8_EFLAG_NO_UPD_ENTROPY; - break; - case kTemporalUpdateGoldenWithoutDependencyRefAltRef: - flags |= VP8_EFLAG_NO_REF_GF; - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_UPD_LAST; - break; - case kTemporalUpdateLastRefAltRef: - flags |= VP8_EFLAG_NO_UPD_GF; - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_REF_GF; - break; - case kTemporalUpdateGoldenRefAltRef: - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_UPD_LAST; - break; - case kTemporalUpdateLastAndGoldenRefAltRef: - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_REF_GF; - break; - case kTemporalUpdateLastRefAll: - flags |= VP8_EFLAG_NO_UPD_ARF; - flags |= VP8_EFLAG_NO_UPD_GF; - break; - } - } - return flags; -} - -// TODO: add support for YUV input color formats -// TODO: add support for SVC, ARF. SVC and ARF returns multiple frames -// (hierarchical / noshow) in one call. These frames should be combined in to -// a single buffer and sent back to the client -void C2SoftVpxEnc::process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - // Initialize encoder if not already - if (!mCodecContext && OK != initEncoder()) { - ALOGE("Failed to initialize encoder"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - std::shared_ptr<const C2GraphicView> rView; - std::shared_ptr<C2Buffer> inputBuffer; - if (!work->input.buffers.empty()) { - inputBuffer = work->input.buffers[0]; - rView = std::make_shared<const C2GraphicView>( - inputBuffer->data().graphicBlocks().front().map().get()); - if (rView->error() != C2_OK) { - ALOGE("graphic view map err = %d", rView->error()); - work->result = C2_CORRUPTED; - return; - } - } else { - ALOGV("Empty input Buffer"); - 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; - return; - } - - const C2ConstGraphicBlock inBuffer = - inputBuffer->data().graphicBlocks().front(); - if (inBuffer.width() != mSize->width || - inBuffer.height() != mSize->height) { - ALOGE("unexpected Input buffer attributes %d(%d) x %d(%d)", - inBuffer.width(), mSize->width, inBuffer.height(), - mSize->height); - mSignalledError = true; - work->result = C2_BAD_VALUE; - return; - } - bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); - vpx_image_t raw_frame; - const C2PlanarLayout &layout = rView->layout(); - uint32_t width = rView->width(); - uint32_t height = rView->height(); - if (width > 0x8000 || height > 0x8000) { - ALOGE("Image too big: %u x %u", width, height); - work->result = C2_BAD_VALUE; - return; - } - uint32_t stride = (width + mStrideAlign - 1) & ~(mStrideAlign - 1); - uint32_t vstride = (height + mStrideAlign - 1) & ~(mStrideAlign - 1); - switch (layout.type) { - case C2PlanarLayout::TYPE_RGB: - case C2PlanarLayout::TYPE_RGBA: { - ConvertRGBToPlanarYUV(mConversionBuffer.data(), stride, vstride, - mConversionBuffer.size(), *rView.get()); - vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, width, height, - mStrideAlign, mConversionBuffer.data()); - break; - } - case C2PlanarLayout::TYPE_YUV: { - if (!IsYUV420(*rView)) { - ALOGE("input is not YUV420"); - work->result = C2_BAD_VALUE; - return; - } - - if (layout.planes[layout.PLANE_Y].colInc == 1 - && layout.planes[layout.PLANE_U].colInc == 1 - && layout.planes[layout.PLANE_V].colInc == 1) { - // I420 compatible - though with custom offset and stride - vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, width, height, - mStrideAlign, (uint8_t*)rView->data()[0]); - raw_frame.planes[1] = (uint8_t*)rView->data()[1]; - raw_frame.planes[2] = (uint8_t*)rView->data()[2]; - raw_frame.stride[0] = layout.planes[layout.PLANE_Y].rowInc; - raw_frame.stride[1] = layout.planes[layout.PLANE_U].rowInc; - raw_frame.stride[2] = layout.planes[layout.PLANE_V].rowInc; - } else { - // copy to I420 - MediaImage2 img = CreateYUV420PlanarMediaImage2(width, height, stride, vstride); - if (mConversionBuffer.size() >= stride * vstride * 3 / 2) { - status_t err = ImageCopy(mConversionBuffer.data(), &img, *rView); - if (err != OK) { - ALOGE("Buffer conversion failed: %d", err); - work->result = C2_BAD_VALUE; - return; - } - vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, stride, vstride, - mStrideAlign, (uint8_t*)rView->data()[0]); - vpx_img_set_rect(&raw_frame, 0, 0, width, height); - } else { - ALOGE("Conversion buffer is too small: %u x %u for %zu", - stride, vstride, mConversionBuffer.size()); - work->result = C2_BAD_VALUE; - return; - } - } - break; - } - default: - ALOGE("Unrecognized plane type: %d", layout.type); - work->result = C2_BAD_VALUE; - return; - } - - vpx_enc_frame_flags_t flags = getEncodeFlags(); - // handle dynamic config parameters - { - IntfImpl::Lock lock = mIntf->lock(); - std::shared_ptr<C2StreamIntraRefreshTuning::output> intraRefresh = mIntf->getIntraRefresh_l(); - std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l(); - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> requestSync = mIntf->getRequestSync_l(); - lock.unlock(); - - if (intraRefresh != mIntraRefresh) { - mIntraRefresh = intraRefresh; - ALOGV("Got mIntraRefresh request"); - } - - if (requestSync != mRequestSync) { - // we can handle IDR immediately - if (requestSync->value) { - // unset request - C2StreamRequestSyncFrameTuning::output clearSync(0u, C2_FALSE); - std::vector<std::unique_ptr<C2SettingResult>> failures; - mIntf->config({ &clearSync }, C2_MAY_BLOCK, &failures); - ALOGV("Got sync request"); - flags |= VPX_EFLAG_FORCE_KF; - } - mRequestSync = requestSync; - } - - if (bitrate != mBitrate) { - mBitrate = bitrate; - mCodecConfiguration->rc_target_bitrate = - (mBitrate->value + 500) / 1000; - vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext, - mCodecConfiguration); - if (res != VPX_CODEC_OK) { - ALOGE("vpx encoder failed to update bitrate: %s", - vpx_codec_err_to_string(res)); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - } - - uint64_t inputTimeStamp = work->input.ordinal.timestamp.peekull(); - uint32_t frameDuration; - if (inputTimeStamp > mLastTimestamp) { - frameDuration = (uint32_t)(inputTimeStamp - mLastTimestamp); - } else { - // Use default of 30 fps in case of 0 frame rate. - float frameRate = mFrameRate->value; - if (frameRate < 0.001) { - frameRate = 30; - } - frameDuration = (uint32_t)(1000000 / frameRate + 0.5); - } - mLastTimestamp = inputTimeStamp; - - vpx_codec_err_t codec_return = vpx_codec_encode(mCodecContext, &raw_frame, - inputTimeStamp, - frameDuration, flags, - VPX_DL_REALTIME); - if (codec_return != VPX_CODEC_OK) { - ALOGE("vpx encoder failed to encode frame"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - bool populated = false; - vpx_codec_iter_t encoded_packet_iterator = nullptr; - const vpx_codec_cx_pkt_t* encoded_packet; - while ((encoded_packet = vpx_codec_get_cx_data( - mCodecContext, &encoded_packet_iterator))) { - if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) { - std::shared_ptr<C2LinearBlock> block; - C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }; - c2_status_t err = pool->fetchLinearBlock(encoded_packet->data.frame.sz, 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; - } - - memcpy(wView.data(), encoded_packet->data.frame.buf, encoded_packet->data.frame.sz); - ++mNumInputFrames; - - ALOGD("bytes generated %zu", encoded_packet->data.frame.sz); - uint32_t flags = 0; - if (eos) { - flags |= C2FrameData::FLAG_END_OF_STREAM; - } - work->worklets.front()->output.flags = (C2FrameData::flags_t)flags; - work->worklets.front()->output.buffers.clear(); - std::shared_ptr<C2Buffer> buffer = createLinearBuffer(block); - if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY) { - buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>( - 0u /* stream id */, C2PictureTypeKeyFrame)); - } - work->worklets.front()->output.buffers.push_back(buffer); - work->worklets.front()->output.ordinal = work->input.ordinal; - work->worklets.front()->output.ordinal.timestamp = encoded_packet->data.frame.pts; - work->workletsProcessed = 1u; - populated = true; - if (eos) { - mSignalledOutputEos = true; - ALOGV("signalled EOS"); - } - } - } - if (!populated) { - work->workletsProcessed = 0u; - } -} - -c2_status_t C2SoftVpxEnc::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; -} - -} // namespace android diff --git a/media/codecs/vpx/C2SoftVpxEnc.h b/media/codecs/vpx/C2SoftVpxEnc.h deleted file mode 100644 index 87ed1a9..0000000 --- a/media/codecs/vpx/C2SoftVpxEnc.h +++ /dev/null @@ -1,437 +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 ANDROID_C2_SOFT_VPX_ENC_H__ -#define ANDROID_C2_SOFT_VPX_ENC_H__ - -#include <media/stagefright/foundation/MediaDefs.h> - -#include <C2PlatformSupport.h> -#include <Codec2BufferUtils.h> -#include <SimpleC2Component.h> -#include <SimpleC2Interface.h> -#include <util/C2InterfaceHelper.h> - -#include "vpx/vpx_encoder.h" -#include "vpx/vpx_codec.h" -#include "vpx/vpx_image.h" -#include "vpx/vp8cx.h" - -namespace android { - -// TODO: These defs taken from deprecated OMX_VideoExt.h. Move these definitions -// to a new header file and include it. - -/** Maximum number of temporal layers */ -#define MAXTEMPORALLAYERS 3 - -/** temporal layer patterns */ -typedef enum TemporalPatternType { - VPXTemporalLayerPatternNone = 0, - VPXTemporalLayerPatternWebRTC = 1, - VPXTemporalLayerPatternMax = 0x7FFFFFFF -} TemporalPatternType; - -// Base class for a VPX Encoder Component -// -// Only following encoder settings are available (codec specific settings might -// be available in the sub-classes): -// - video resolution -// - target bitrate -// - rate control (constant / variable) -// - frame rate -// - error resilience -// - reconstruction & loop filters (g_profile) -// -// Only following color formats are recognized -// - C2PlanarLayout::TYPE_RGB -// - C2PlanarLayout::TYPE_RGBA -// -// Following settings are not configurable by the client -// - encoding deadline is realtime -// - multithreaded encoding utilizes a number of threads equal -// to online cpu's available -// - the algorithm interface for encoder is decided by the sub-class in use -// - fractional bits of frame rate is discarded -// - timestamps are in microseconds, therefore encoder timebase is fixed -// to 1/1000000 - -struct C2SoftVpxEnc : public SimpleC2Component { - class IntfImpl; - - C2SoftVpxEnc(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - - // From SimpleC2Component - c2_status_t onInit() override final; - c2_status_t onStop() override final; - void onReset() override final; - void onRelease() override final; - c2_status_t onFlush_sm() override final; - - void process( - const std::unique_ptr<C2Work> &work, - const std::shared_ptr<C2BlockPool> &pool) override final; - c2_status_t drain( - uint32_t drainMode, - const std::shared_ptr<C2BlockPool> &pool) override final; - - protected: - std::shared_ptr<IntfImpl> mIntf; - virtual ~C2SoftVpxEnc(); - - // Initializes vpx encoder with available settings. - status_t initEncoder(); - - // Populates mCodecInterface with codec specific settings. - virtual void setCodecSpecificInterface() = 0; - - // Sets codec specific configuration. - virtual void setCodecSpecificConfiguration() = 0; - - // Sets codec specific encoder controls. - virtual vpx_codec_err_t setCodecSpecificControls() = 0; - - // Get current encode flags. - virtual vpx_enc_frame_flags_t getEncodeFlags(); - - enum TemporalReferences { - // For 1 layer case: reference all (last, golden, and alt ref), but only - // update last. - kTemporalUpdateLastRefAll = 12, - // First base layer frame for 3 temporal layers, which updates last and - // golden with alt ref dependency. - kTemporalUpdateLastAndGoldenRefAltRef = 11, - // First enhancement layer with alt ref dependency. - kTemporalUpdateGoldenRefAltRef = 10, - // First enhancement layer with alt ref dependency. - kTemporalUpdateGoldenWithoutDependencyRefAltRef = 9, - // Base layer with alt ref dependency. - kTemporalUpdateLastRefAltRef = 8, - // Highest enhacement layer without dependency on golden with alt ref - // dependency. - kTemporalUpdateNoneNoRefGoldenRefAltRef = 7, - // Second layer and last frame in cycle, for 2 layers. - kTemporalUpdateNoneNoRefAltref = 6, - // Highest enhancement layer. - kTemporalUpdateNone = 5, - // Second enhancement layer. - kTemporalUpdateAltref = 4, - // Second enhancement layer without dependency on previous frames in - // the second enhancement layer. - kTemporalUpdateAltrefWithoutDependency = 3, - // First enhancement layer. - kTemporalUpdateGolden = 2, - // First enhancement layer without dependency on previous frames in - // the first enhancement layer. - kTemporalUpdateGoldenWithoutDependency = 1, - // Base layer. - kTemporalUpdateLast = 0, - }; - enum { - kMaxTemporalPattern = 8 - }; - - // vpx specific opaque data structure that - // stores encoder state - vpx_codec_ctx_t* mCodecContext; - - // vpx specific data structure that - // stores encoder configuration - vpx_codec_enc_cfg_t* mCodecConfiguration; - - // vpx specific read-only data structure - // that specifies algorithm interface (e.g. vp8) - vpx_codec_iface_t* mCodecInterface; - - // align stride to the power of 2 - int32_t mStrideAlign; - - // Color format for the input port - vpx_img_fmt_t mColorFormat; - - // Bitrate control mode, either constant or variable - vpx_rc_mode mBitrateControlMode; - - // Parameter that denotes whether error resilience - // is enabled in encoder - bool mErrorResilience; - - // Minimum (best quality) quantizer - uint32_t mMinQuantizer; - - // Maximum (worst quality) quantizer - uint32_t mMaxQuantizer; - - // Number of coding temporal layers to be used. - size_t mTemporalLayers; - - // Temporal layer bitrare ratio in percentage - uint32_t mTemporalLayerBitrateRatio[MAXTEMPORALLAYERS]; - - // Temporal pattern type - TemporalPatternType mTemporalPatternType; - - // Temporal pattern length - size_t mTemporalPatternLength; - - // Temporal pattern current index - size_t mTemporalPatternIdx; - - // Frame type temporal pattern - TemporalReferences mTemporalPattern[kMaxTemporalPattern]; - - // Last input buffer timestamp - uint64_t mLastTimestamp; - - // Number of input frames - int64_t mNumInputFrames; - - // Conversion buffer is needed to input to - // yuv420 planar format. - MemoryBlock mConversionBuffer; - - // Signalled EOS - bool mSignalledOutputEos; - - // Signalled Error - bool mSignalledError; - - // configurations used by component in process - // (TODO: keep this in intf but make them internal only) - std::shared_ptr<C2StreamPictureSizeInfo::input> mSize; - std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh; - std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; - std::shared_ptr<C2StreamBitrateInfo::output> mBitrate; - std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode; - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync; - - C2_DO_NOT_COPY(C2SoftVpxEnc); -}; - -class C2SoftVpxEnc::IntfImpl : public C2InterfaceHelper { - public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper) - : C2InterfaceHelper(helper) { - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::input(0u, C2FormatVideo)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue( - new C2StreamFormatConfig::output(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_VIDEO_RAW)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( -#ifdef VP9 - MEDIA_MIMETYPE_VIDEO_VP9 -#else - MEDIA_MIMETYPE_VIDEO_VP8 -#endif - )) - .build()); - - addParameter(DefineParam(mUsage, C2_NAME_INPUT_STREAM_USAGE_SETTING) - .withConstValue(new C2StreamUsageTuning::input( - 0u, (uint64_t)C2MemoryUsage::CPU_READ)) - .build()); - - addParameter( - DefineParam(mSize, C2_NAME_STREAM_VIDEO_SIZE_SETTING) - .withDefault(new C2VideoSizeStreamTuning::input(0u, 320, 240)) - .withFields({ - C2F(mSize, width).inRange(2, 2048, 2), - C2F(mSize, height).inRange(2, 2048, 2), - }) - .withSetter(SizeSetter) - .build()); - - addParameter( - DefineParam(mBitrateMode, C2_PARAMKEY_BITRATE_MODE) - .withDefault(new C2StreamBitrateModeTuning::output( - 0u, C2Config::BITRATE_CONST)) - .withFields({ - C2F(mBitrateMode, value).oneOf({ - C2Config::BITRATE_CONST, C2Config::BITRATE_VARIABLE }) - }) - .withSetter( - Setter<decltype(*mBitrateMode)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mFrameRate, C2_NAME_STREAM_FRAME_RATE_SETTING) - .withDefault(new C2StreamFrameRateInfo::output(0u, 30.)) - // TODO: More restriction? - .withFields({C2F(mFrameRate, value).greaterThan(0.)}) - .withSetter( - Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mLayering, C2_PARAMKEY_TEMPORAL_LAYERING) - .withDefault(C2StreamTemporalLayeringTuning::output::AllocShared(0u, 0, 0, 0)) - .withFields({ - C2F(mLayering, m.layerCount).inRange(0, 4), - C2F(mLayering, m.bLayerCount).inRange(0, 0), - C2F(mLayering, m.bitrateRatios).inRange(0., 1.) - }) - .withSetter(LayeringSetter) - .build()); - - addParameter( - DefineParam(mSyncFramePeriod, C2_PARAMKEY_SYNC_FRAME_INTERVAL) - .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000)) - .withFields({C2F(mSyncFramePeriod, value).any()}) - .withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::output(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(4096, 40000000)}) - .withSetter(BitrateSetter) - .build()); - - addParameter( - DefineParam(mIntraRefresh, C2_PARAMKEY_INTRA_REFRESH) - .withConstValue(new C2StreamIntraRefreshTuning::output( - 0u, C2Config::INTRA_REFRESH_DISABLED, 0.)) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::output( - 0u, PROFILE_VP9_0, LEVEL_VP9_4_1)) - .withFields({ - C2F(mProfileLevel, profile).equalTo( - PROFILE_VP9_0 - ), - C2F(mProfileLevel, level).equalTo( - LEVEL_VP9_4_1), - }) - .withSetter(ProfileLevelSetter) - .build()); - - addParameter( - DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME) - .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE)) - .withFields({C2F(mRequestSync, value).oneOf({ C2_FALSE, C2_TRUE }) }) - .withSetter(Setter<decltype(*mRequestSync)>::NonStrictValueWithNoDeps) - .build()); - } - - static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (me.v.value <= 4096) { - me.set().value = 4096; - } - return res; - } - - static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe, - C2P<C2StreamPictureSizeInfo::input> &me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (!me.F(me.v.width).supportsAtAll(me.v.width)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width))); - me.set().width = oldMe.v.width; - } - if (!me.F(me.v.height).supportsAtAll(me.v.height)) { - res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height))); - me.set().height = oldMe.v.height; - } - return res; - } - - static C2R ProfileLevelSetter( - bool mayBlock, - C2P<C2StreamProfileLevelInfo::output> &me) { - (void)mayBlock; - if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) { - me.set().profile = PROFILE_VP9_0; - } - if (!me.F(me.v.level).supportsAtAll(me.v.level)) { - me.set().level = LEVEL_VP9_4_1; - } - return C2R::Ok(); - } - - static C2R LayeringSetter(bool mayBlock, C2P<C2StreamTemporalLayeringTuning::output>& me) { - (void)mayBlock; - C2R res = C2R::Ok(); - if (me.v.m.layerCount > 4) { - me.set().m.layerCount = 4; - } - me.set().m.bLayerCount = 0; - // ensure ratios are monotonic and clamped between 0 and 1 - for (size_t ix = 0; ix < me.v.flexCount(); ++ix) { - me.set().m.bitrateRatios[ix] = c2_clamp( - ix > 0 ? me.v.m.bitrateRatios[ix - 1] : 0, me.v.m.bitrateRatios[ix], 1.); - } - ALOGI("setting temporal layering %u + %u", me.v.m.layerCount, me.v.m.bLayerCount); - return res; - } - - // unsafe getters - std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const { return mSize; } - std::shared_ptr<C2StreamIntraRefreshTuning::output> getIntraRefresh_l() const { return mIntraRefresh; } - std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; } - std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; } - std::shared_ptr<C2StreamBitrateModeTuning::output> getBitrateMode_l() const { return mBitrateMode; } - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; } - std::shared_ptr<C2StreamTemporalLayeringTuning::output> getTemporalLayers_l() const { return mLayering; } - uint32_t getSyncFramePeriod() const { - if (mSyncFramePeriod->value < 0 || mSyncFramePeriod->value == INT64_MAX) { - return 0; - } - double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value; - return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.); - } - - private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamUsageTuning::input> mUsage; - std::shared_ptr<C2VideoSizeStreamTuning::input> mSize; - std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate; - std::shared_ptr<C2StreamTemporalLayeringTuning::output> mLayering; - std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh; - std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync; - std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod; - std::shared_ptr<C2BitrateTuning::output> mBitrate; - std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode; - std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel; -}; - -} // namespace android - -#endif // ANDROID_C2_SOFT_VPX_ENC_H__ diff --git a/media/codecs/vpx/MODULE_LICENSE_APACHE2 b/media/codecs/vpx/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/media/codecs/vpx/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/media/codecs/vpx/NOTICE b/media/codecs/vpx/NOTICE deleted file mode 100644 index faed58a..0000000 --- a/media/codecs/vpx/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2013, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/codecs/xaac/Android.bp b/media/codecs/xaac/Android.bp deleted file mode 100644 index 19c12cf..0000000 --- a/media/codecs/xaac/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -cc_library_shared { - name: "libstagefright_soft_c2xaacdec", - defaults: [ - "libstagefright_soft_c2-defaults", - "libstagefright_soft_c2_sanitize_all-defaults", - ], - - srcs: ["C2SoftXaacDec.cpp"], - - static_libs: ["libxaacdec"], -} diff --git a/media/codecs/xaac/C2SoftXaacDec.cpp b/media/codecs/xaac/C2SoftXaacDec.cpp deleted file mode 100644 index 1c0e70b..0000000 --- a/media/codecs/xaac/C2SoftXaacDec.cpp +++ /dev/null @@ -1,1583 +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 "C2SoftXaacDec" -#include <log/log.h> - -#include <inttypes.h> - -#include <cutils/properties.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/MediaDefs.h> -#include <media/stagefright/foundation/hexdump.h> - -#include <C2PlatformSupport.h> -#include <SimpleC2Interface.h> - -#include "C2SoftXaacDec.h" - -#define DRC_DEFAULT_MOBILE_REF_LEVEL -16.0 /* 64*-0.25dB = -16 dB below full scale for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_CUT 1.0 /* maximum compression of dynamic range for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_BOOST 1.0 /* maximum compression of dynamic range for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_HEAVY C2Config::DRC_COMPRESSION_HEAVY /* switch for heavy compression for mobile conf */ -#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */ -#define DRC_DEFAULT_MOBILE_ENC_LEVEL (0.25) /* 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" -#define PROP_DRC_OVERRIDE_EFFECT_TYPE "ro.aac_drc_effect_type" - -#define RETURN_IF_FATAL(retval, str) \ - if (retval & IA_FATAL_ERROR) { \ - ALOGE("Error in %s: Returned: %d", str, retval); \ - return retval; \ - } else if (retval != IA_NO_ERROR) { \ - ALOGW("Warning in %s: Returned: %d", str, retval); \ - } - - -namespace android { - -constexpr char COMPONENT_NAME[] = "c2.android.xaac.decoder"; - -class C2SoftXaacDec::IntfImpl : public C2InterfaceHelper { -public: - explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) - : C2InterfaceHelper(helper) { - - setDerivedInstance(this); - - addParameter( - DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) - .build()); - - addParameter( - DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) - .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) - .build()); - - addParameter( - DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::input>( - MEDIA_MIMETYPE_AUDIO_AAC)) - .build()); - - addParameter( - DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) - .withConstValue(AllocSharedString<C2PortMimeConfig::output>( - MEDIA_MIMETYPE_AUDIO_RAW)) - .build()); - - addParameter( - DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) - .withDefault(new C2StreamSampleRateInfo::output(0u, 44100)) - .withFields({C2F(mSampleRate, value).oneOf({ - 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 - })}) - .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) - .build()); - - addParameter( - DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) - .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) - .withFields({C2F(mChannelCount, value).inRange(1, 8)}) - .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) - .withDefault(new C2BitrateTuning::input(0u, 64000)) - .withFields({C2F(mBitrate, value).inRange(8000, 960000)}) - .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) - .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) - .build()); - - addParameter( - DefineParam(mAacFormat, C2_NAME_STREAM_AAC_FORMAT_SETTING) - .withDefault(new C2StreamAacFormatInfo::input(0u, C2AacStreamFormatRaw)) - .withFields({C2F(mAacFormat, value).oneOf({ - C2AacStreamFormatRaw, C2AacStreamFormatAdts - })}) - .withSetter(Setter<decltype(*mAacFormat)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL) - .withDefault(new C2StreamProfileLevelInfo::input(0u, - C2Config::PROFILE_AAC_LC, C2Config::LEVEL_UNUSED)) - .withFields({ - C2F(mProfileLevel, profile).oneOf({ - C2Config::PROFILE_AAC_LC, - C2Config::PROFILE_AAC_HE, - C2Config::PROFILE_AAC_HE_PS, - C2Config::PROFILE_AAC_LD, - C2Config::PROFILE_AAC_ELD, - C2Config::PROFILE_AAC_XHE}), - C2F(mProfileLevel, level).oneOf({ - C2Config::LEVEL_UNUSED - }) - }) - .withSetter(ProfileLevelSetter) - .build()); - - addParameter( - DefineParam(mDrcCompressMode, C2_PARAMKEY_DRC_COMPRESSION_MODE) - .withDefault(new C2StreamDrcCompressionModeTuning::input(0u, C2Config::DRC_COMPRESSION_HEAVY)) - .withFields({ - C2F(mDrcCompressMode, value).oneOf({ - C2Config::DRC_COMPRESSION_ODM_DEFAULT, - C2Config::DRC_COMPRESSION_NONE, - C2Config::DRC_COMPRESSION_LIGHT, - C2Config::DRC_COMPRESSION_HEAVY}) - }) - .withSetter(Setter<decltype(*mDrcCompressMode)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcTargetRefLevel, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL) - .withDefault(new C2StreamDrcTargetReferenceLevelTuning::input(0u, DRC_DEFAULT_MOBILE_REF_LEVEL)) - .withFields({C2F(mDrcTargetRefLevel, value).inRange(-31.75, 0.25)}) - .withSetter(Setter<decltype(*mDrcTargetRefLevel)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcEncTargetLevel, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL) - .withDefault(new C2StreamDrcEncodedTargetLevelTuning::input(0u, DRC_DEFAULT_MOBILE_ENC_LEVEL)) - .withFields({C2F(mDrcEncTargetLevel, value).inRange(-31.75, 0.25)}) - .withSetter(Setter<decltype(*mDrcEncTargetLevel)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcBoostFactor, C2_PARAMKEY_DRC_BOOST_FACTOR) - .withDefault(new C2StreamDrcBoostFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_BOOST)) - .withFields({C2F(mDrcBoostFactor, value).inRange(0, 1.)}) - .withSetter(Setter<decltype(*mDrcBoostFactor)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcAttenuationFactor, C2_PARAMKEY_DRC_ATTENUATION_FACTOR) - .withDefault(new C2StreamDrcAttenuationFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_CUT)) - .withFields({C2F(mDrcAttenuationFactor, value).inRange(0, 1.)}) - .withSetter(Setter<decltype(*mDrcAttenuationFactor)>::StrictValueWithNoDeps) - .build()); - - addParameter( - DefineParam(mDrcEffectType, C2_PARAMKEY_DRC_EFFECT_TYPE) - .withDefault(new C2StreamDrcEffectTypeTuning::input(0u, C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE)) - .withFields({ - C2F(mDrcEffectType, value).oneOf({ - C2Config::DRC_EFFECT_ODM_DEFAULT, - C2Config::DRC_EFFECT_OFF, - C2Config::DRC_EFFECT_NONE, - C2Config::DRC_EFFECT_LATE_NIGHT, - C2Config::DRC_EFFECT_NOISY_ENVIRONMENT, - C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE, - C2Config::DRC_EFFECT_LOW_PLAYBACK_LEVEL, - C2Config::DRC_EFFECT_DIALOG_ENHANCEMENT, - C2Config::DRC_EFFECT_GENERAL_COMPRESSION}) - }) - .withSetter(Setter<decltype(*mDrcEffectType)>::StrictValueWithNoDeps) - .build()); - } - - bool isAdts() const { return mAacFormat->value == C2AacStreamFormatAdts; } - uint32_t getBitrate() const { return mBitrate->value; } - static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me) { - (void)mayBlock; - (void)me; // TODO: validate - return C2R::Ok(); - } - int32_t getDrcCompressMode() const { return mDrcCompressMode->value == C2Config::DRC_COMPRESSION_HEAVY ? 1 : 0; } - int32_t getDrcTargetRefLevel() const { return (mDrcTargetRefLevel->value <= 0 ? -mDrcTargetRefLevel->value * 4. + 0.5 : -1); } - int32_t getDrcEncTargetLevel() const { return (mDrcEncTargetLevel->value <= 0 ? -mDrcEncTargetLevel->value * 4. + 0.5 : -1); } - int32_t getDrcBoostFactor() const { return mDrcBoostFactor->value * 127. + 0.5; } - int32_t getDrcAttenuationFactor() const { return mDrcAttenuationFactor->value * 127. + 0.5; } - int32_t getDrcEffectType() const { return mDrcEffectType->value; } - -private: - std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; - std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; - std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; - std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; - std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; - std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; - std::shared_ptr<C2BitrateTuning::input> mBitrate; - std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; - std::shared_ptr<C2StreamAacFormatInfo::input> mAacFormat; - std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; - std::shared_ptr<C2StreamDrcCompressionModeTuning::input> mDrcCompressMode; - std::shared_ptr<C2StreamDrcTargetReferenceLevelTuning::input> mDrcTargetRefLevel; - std::shared_ptr<C2StreamDrcEncodedTargetLevelTuning::input> mDrcEncTargetLevel; - std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor; - std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor; - std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType; - // TODO Add : C2StreamAacSbrModeTuning -}; - -C2SoftXaacDec::C2SoftXaacDec( - const char* name, - c2_node_id_t id, - const std::shared_ptr<IntfImpl> &intfImpl) - : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), - mIntf(intfImpl), - mXheaacCodecHandle(nullptr), - mMpegDDrcHandle(nullptr), - mOutputDrainBuffer(nullptr) { -} - -C2SoftXaacDec::~C2SoftXaacDec() { - onRelease(); -} - -c2_status_t C2SoftXaacDec::onInit() { - mOutputFrameLength = 1024; - mInputBuffer = nullptr; - mOutputBuffer = nullptr; - mSampFreq = 0; - mNumChannels = 0; - mPcmWdSz = 0; - mChannelMask = 0; - mNumOutBytes = 0; - mCurFrameIndex = 0; - mCurTimestamp = 0; - mIsCodecInitialized = false; - mIsCodecConfigFlushRequired = false; - mSignalledOutputEos = false; - mSignalledError = false; - mOutputDrainBufferWritePos = 0; - mDRCFlag = 0; - mMpegDDRCPresent = 0; - mMemoryVec.clear(); - mDrcMemoryVec.clear(); - - IA_ERRORCODE err = initDecoder(); - return err == IA_NO_ERROR ? C2_OK : C2_CORRUPTED; - -} - -c2_status_t C2SoftXaacDec::onStop() { - mOutputFrameLength = 1024; - drainDecoder(); - // reset the "configured" state - mSampFreq = 0; - mNumChannels = 0; - mPcmWdSz = 0; - mChannelMask = 0; - mNumOutBytes = 0; - mCurFrameIndex = 0; - mCurTimestamp = 0; - mSignalledOutputEos = false; - mSignalledError = false; - mOutputDrainBufferWritePos = 0; - mDRCFlag = 0; - mMpegDDRCPresent = 0; - - return C2_OK; -} - -void C2SoftXaacDec::onReset() { - (void)onStop(); -} - -void C2SoftXaacDec::onRelease() { - IA_ERRORCODE errCode = deInitXAACDecoder(); - if (IA_NO_ERROR != errCode) ALOGE("deInitXAACDecoder() failed %d", errCode); - - errCode = deInitMPEGDDDrc(); - if (IA_NO_ERROR != errCode) ALOGE("deInitMPEGDDDrc() failed %d", errCode); - - if (mOutputDrainBuffer) { - delete[] mOutputDrainBuffer; - mOutputDrainBuffer = nullptr; - } -} - -IA_ERRORCODE C2SoftXaacDec::initDecoder() { - ALOGV("initDecoder()"); - IA_ERRORCODE err_code = IA_NO_ERROR; - - err_code = initXAACDecoder(); - if (err_code != IA_NO_ERROR) { - ALOGE("initXAACDecoder Failed"); - /* Call deInit to free any allocated memory */ - deInitXAACDecoder(); - return IA_FATAL_ERROR; - } - - if (!mOutputDrainBuffer) { - mOutputDrainBuffer = new (std::nothrow) char[kOutputDrainBufferSize]; - if (!mOutputDrainBuffer) return IA_FATAL_ERROR; - } - - err_code = initXAACDrc(); - RETURN_IF_FATAL(err_code, "initXAACDrc"); - - - return IA_NO_ERROR; -} - -static 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 C2SoftXaacDec::finishWork(const std::unique_ptr<C2Work>& work, - const std::shared_ptr<C2BlockPool>& pool) { - ALOGV("mCurFrameIndex = %" PRIu64, mCurFrameIndex); - - std::shared_ptr<C2LinearBlock> block; - C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}; - // TODO: error handling, proper usage, etc. - c2_status_t err = - pool->fetchLinearBlock(mOutputDrainBufferWritePos, usage, &block); - if (err != C2_OK) { - ALOGE("fetchLinearBlock failed : err = %d", err); - work->result = C2_NO_MEMORY; - return; - } - C2WriteView wView = block->map().get(); - int16_t* outBuffer = reinterpret_cast<int16_t*>(wView.data()); - memcpy(outBuffer, mOutputDrainBuffer, mOutputDrainBufferWritePos); - mOutputDrainBufferWritePos = 0; - - auto fillWork = [buffer = createLinearBuffer(block)]( - 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.buffers.push_back(buffer); - work->worklets.front()->output.ordinal = work->input.ordinal; - work->workletsProcessed = 1u; - }; - if (work && work->input.ordinal.frameIndex == c2_cntr64_t(mCurFrameIndex)) { - fillWork(work); - } else { - finish(mCurFrameIndex, fillWork); - } - - ALOGV("out timestamp %" PRIu64 " / %u", mCurTimestamp, block->capacity()); -} - -void C2SoftXaacDec::process(const std::unique_ptr<C2Work>& work, - const std::shared_ptr<C2BlockPool>& pool) { - // Initialize output work - work->result = C2_OK; - work->workletsProcessed = 1u; - work->worklets.front()->output.configUpdate.clear(); - work->worklets.front()->output.flags = work->input.flags; - - if (mSignalledError || mSignalledOutputEos) { - work->result = C2_BAD_VALUE; - return; - } - uint8_t* inBuffer = nullptr; - uint32_t inBufferLength = 0; - C2ReadView view = mDummyReadView; - size_t offset = 0u; - size_t size = 0u; - if (!work->input.buffers.empty()) { - view = work->input.buffers[0]->data().linearBlocks().front().map().get(); - size = view.capacity(); - } - if (size && view.error()) { - ALOGE("read view map failed %d", view.error()); - work->result = view.error(); - return; - } - - bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; - bool codecConfig = - (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0; - if (codecConfig) { - if (size == 0u) { - ALOGE("empty codec config"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - // const_cast because of libAACdec method signature. - inBuffer = const_cast<uint8_t*>(view.data() + offset); - inBufferLength = size; - - /* GA header configuration sent to Decoder! */ - IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength); - if (IA_NO_ERROR != err_code) { - ALOGE("configXAACDecoder err_code = %d", err_code); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - work->worklets.front()->output.flags = work->input.flags; - work->worklets.front()->output.ordinal = work->input.ordinal; - work->worklets.front()->output.buffers.clear(); - return; - } - - mCurFrameIndex = work->input.ordinal.frameIndex.peeku(); - mCurTimestamp = work->input.ordinal.timestamp.peeku(); - mOutputDrainBufferWritePos = 0; - char* tempOutputDrainBuffer = mOutputDrainBuffer; - while (size > 0u) { - if ((kOutputDrainBufferSize * sizeof(int16_t) - - mOutputDrainBufferWritePos) < - (mOutputFrameLength * sizeof(int16_t) * mNumChannels)) { - ALOGV("skipping decode: not enough space left in DrainBuffer"); - break; - } - - ALOGV("inAttribute size = %zu", size); - if (mIntf->isAdts()) { - ALOGV("ADTS"); - 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 = - const_cast<uint8_t*>(adtsHeader + adtsHeaderSize); - inBufferLength = aac_frame_length - adtsHeaderSize; - - offset += adtsHeaderSize; - size -= adtsHeaderSize; - } - } - } - - if (signalError) { - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } else { - ALOGV("Non ADTS"); - // const_cast because of libAACdec method signature. - inBuffer = const_cast<uint8_t*>(view.data() + offset); - inBufferLength = size; - } - - signed int prevSampleRate = mSampFreq; - signed int prevNumChannels = mNumChannels; - - /* XAAC decoder expects first frame to be fed via configXAACDecoder API - * which should initialize the codec. Once this state is reached, call the - * decodeXAACStream API with same frame to decode! */ - if (!mIsCodecInitialized) { - IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength); - if (IA_NO_ERROR != err_code) { - ALOGE("configXAACDecoder Failed 2 err_code = %d", err_code); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - if ((mSampFreq != prevSampleRate) || - (mNumChannels != prevNumChannels)) { - ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", - prevSampleRate, mSampFreq, prevNumChannels, mNumChannels); - - C2StreamSampleRateInfo::output sampleRateInfo(0u, mSampFreq); - C2StreamChannelCountInfo::output channelCountInfo(0u, mNumChannels); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mIntf->config( - { &sampleRateInfo, &channelCountInfo }, - C2_MAY_BLOCK, - &failures); - if (err == OK) { - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(sampleRateInfo)); - work->worklets.front()->output.configUpdate.push_back( - C2Param::Copy(channelCountInfo)); - } else { - ALOGE("Config Update failed"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - } - } - - signed int bytesConsumed = 0; - IA_ERRORCODE errorCode = IA_NO_ERROR; - if (mIsCodecInitialized) { - mIsCodecConfigFlushRequired = true; - errorCode = decodeXAACStream(inBuffer, inBufferLength, - &bytesConsumed, &mNumOutBytes); - } else if (!mIsCodecConfigFlushRequired) { - ALOGW("Assumption that first frame after header initializes decoder Failed!"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - size -= bytesConsumed; - offset += bytesConsumed; - - if (inBufferLength != (uint32_t)bytesConsumed) - ALOGW("All data not consumed"); - - /* In case of error, decoder would have given out empty buffer */ - if ((IA_NO_ERROR != errorCode) && (0 == mNumOutBytes) && mIsCodecInitialized) - mNumOutBytes = mOutputFrameLength * (mPcmWdSz / 8) * mNumChannels; - - if (!bytesConsumed) { - ALOGW("bytesConsumed = 0 should never happen"); - } - - if ((uint32_t)mNumOutBytes > - mOutputFrameLength * sizeof(int16_t) * mNumChannels) { - ALOGE("mNumOutBytes > mOutputFrameLength * sizeof(int16_t) * mNumChannels, should never happen"); - mSignalledError = true; - work->result = C2_CORRUPTED; - return; - } - - if (IA_NO_ERROR != errorCode) { - // TODO: check for overflow, ASAN - memset(mOutputBuffer, 0, mNumOutBytes); - - // Discard input buffer. - size = 0; - - // fall through - } - memcpy(tempOutputDrainBuffer, mOutputBuffer, mNumOutBytes); - tempOutputDrainBuffer += mNumOutBytes; - mOutputDrainBufferWritePos += mNumOutBytes; - } - - if (mOutputDrainBufferWritePos) { - finishWork(work, pool); - } else { - fillEmptyWork(work); - } - if (eos) mSignalledOutputEos = true; -} - -c2_status_t C2SoftXaacDec::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; -} - -IA_ERRORCODE C2SoftXaacDec::configflushDecode() { - IA_ERRORCODE err_code; - uint32_t ui_init_done; - uint32_t inBufferLength = 8203; - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_FLUSH_MEM, - nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_FLUSH_MEM"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_INPUT_BYTES, - 0, - &inBufferLength); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_FLUSH_MEM, - nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_FLUSH_MEM"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_DONE_QUERY, - &ui_init_done); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_DONE_QUERY"); - - if (ui_init_done) { - err_code = getXAACStreamInfo(); - RETURN_IF_FATAL(err_code, "getXAACStreamInfo"); - ALOGV("Found Codec with below config---\nsampFreq %d\nnumChannels %d\npcmWdSz %d\nchannelMask %d\noutputFrameLength %d", - mSampFreq, mNumChannels, mPcmWdSz, mChannelMask, mOutputFrameLength); - mIsCodecInitialized = true; - } - return IA_NO_ERROR; -} - -c2_status_t C2SoftXaacDec::onFlush_sm() { - if (mIsCodecInitialized) { - IA_ERRORCODE err_code = configflushDecode(); - if (err_code != IA_NO_ERROR) { - ALOGE("Error in configflushDecode: Error %d", err_code); - } - } - drainDecoder(); - mSignalledOutputEos = false; - mSignalledError = false; - - return C2_OK; -} - -IA_ERRORCODE C2SoftXaacDec::drainDecoder() { - /* Output delay compensation logic should sit here. */ - /* Nothing to be done as XAAC decoder does not introduce output buffer delay */ - - return 0; -} - -IA_ERRORCODE C2SoftXaacDec::initXAACDecoder() { - /* First part */ - /* Error Handler Init */ - /* Get Library Name, Library Version and API Version */ - /* Initialize API structure + Default config set */ - /* Set config params from user */ - /* Initialize memory tables */ - /* Get memory information and allocate memory */ - - mInputBufferSize = 0; - mInputBuffer = nullptr; - mOutputBuffer = nullptr; - /* Process struct initing end */ - - /* ******************************************************************/ - /* Initialize API structure and set config params to default */ - /* ******************************************************************/ - /* API size */ - uint32_t pui_api_size; - /* Get the API size */ - IA_ERRORCODE err_code = ixheaacd_dec_api(nullptr, - IA_API_CMD_GET_API_SIZE, - 0, - &pui_api_size); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE"); - - /* Allocate memory for API */ - mXheaacCodecHandle = memalign(4, pui_api_size); - if (!mXheaacCodecHandle) { - ALOGE("malloc for pui_api_size + 4 >> %d Failed", pui_api_size + 4); - return IA_FATAL_ERROR; - } - mMemoryVec.push(mXheaacCodecHandle); - - /* Set the config params to default values */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, - nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS"); - - /* Get the API size */ - err_code = ia_drc_dec_api(nullptr, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size); - - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE"); - - /* Allocate memory for API */ - mMpegDDrcHandle = memalign(4, pui_api_size); - if (!mMpegDDrcHandle) { - ALOGE("malloc for pui_api_size + 4 >> %d Failed", pui_api_size + 4); - return IA_FATAL_ERROR; - } - mMemoryVec.push(mMpegDDrcHandle); - - /* Set the config params to default values */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, nullptr); - - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS"); - - /* ******************************************************************/ - /* Set config parameters */ - /* ******************************************************************/ - uint32_t ui_mp4_flag = 1; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4, - &ui_mp4_flag); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4"); - - /* ******************************************************************/ - /* Initialize Memory info tables */ - /* ******************************************************************/ - uint32_t ui_proc_mem_tabs_size; - pVOID pv_alloc_ptr; - /* Get memory info tables size */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_MEMTABS_SIZE, - 0, - &ui_proc_mem_tabs_size); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEMTABS_SIZE"); - - pv_alloc_ptr = memalign(4, ui_proc_mem_tabs_size); - if (!pv_alloc_ptr) { - ALOGE("Malloc for size (ui_proc_mem_tabs_size + 4) = %d failed!", ui_proc_mem_tabs_size + 4); - return IA_FATAL_ERROR; - } - mMemoryVec.push(pv_alloc_ptr); - - /* Set pointer for process memory tables */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_MEMTABS_PTR, - 0, - pv_alloc_ptr); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR"); - - /* initialize the API, post config, fill memory tables */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, - nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS"); - - /* ******************************************************************/ - /* Allocate Memory with info from library */ - /* ******************************************************************/ - /* There are four different types of memories, that needs to be allocated */ - /* persistent,scratch,input and output */ - for (int i = 0; i < 4; i++) { - int ui_size = 0, ui_alignment = 0, ui_type = 0; - - /* Get memory size */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_MEM_INFO_SIZE, - i, - &ui_size); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE"); - - /* Get memory alignment */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_MEM_INFO_ALIGNMENT, - i, - &ui_alignment); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT"); - - /* Get memory type */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_MEM_INFO_TYPE, - i, - &ui_type); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE"); - - pv_alloc_ptr = memalign(ui_alignment, ui_size); - if (!pv_alloc_ptr) { - ALOGE("Malloc for size (ui_size + ui_alignment) = %d failed!", - ui_size + ui_alignment); - return IA_FATAL_ERROR; - } - mMemoryVec.push(pv_alloc_ptr); - - /* Set the buffer pointer */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_MEM_PTR, - i, - pv_alloc_ptr); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR"); - if (ui_type == IA_MEMTYPE_INPUT) { - mInputBuffer = (pWORD8)pv_alloc_ptr; - mInputBufferSize = ui_size; - } - if (ui_type == IA_MEMTYPE_OUTPUT) - mOutputBuffer = (pWORD8)pv_alloc_ptr; - } - /* End first part */ - - return IA_NO_ERROR; -} - -status_t C2SoftXaacDec::initXAACDrc() { - IA_ERRORCODE err_code = IA_NO_ERROR; - unsigned int ui_drc_val; - // DRC_PRES_MODE_WRAP_DESIRED_TARGET - int32_t targetRefLevel = mIntf->getDrcTargetRefLevel(); - ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel); - ui_drc_val = (unsigned int)targetRefLevel; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL, - &ui_drc_val); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL"); - - /* Use ui_drc_val from PROP_DRC_OVERRIDE_REF_LEVEL or DRC_DEFAULT_MOBILE_REF_LEVEL - * for IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS too */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS, &ui_drc_val); - - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS"); - - int32_t attenuationFactor = mIntf->getDrcAttenuationFactor(); - ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor); - ui_drc_val = (unsigned int)attenuationFactor; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT, - &ui_drc_val); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT"); - - // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR - int32_t boostFactor = mIntf->getDrcBoostFactor(); - ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor); - ui_drc_val = (unsigned int)boostFactor; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST, - &ui_drc_val); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST"); - - // DRC_PRES_MODE_WRAP_DESIRED_HEAVY - int32_t compressMode = mIntf->getDrcCompressMode(); - ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode); - ui_drc_val = (unsigned int)compressMode; - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP, - &ui_drc_val); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP"); - - // AAC_UNIDRC_SET_EFFECT - int32_t effectType = mIntf->getDrcEffectType(); - ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType); - ui_drc_val = (unsigned int)effectType; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE, &ui_drc_val); - - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE"); - - return IA_NO_ERROR; -} - -IA_ERRORCODE C2SoftXaacDec::deInitXAACDecoder() { - ALOGV("deInitXAACDecoder"); - - /* Error code */ - IA_ERRORCODE err_code = IA_NO_ERROR; - - if (mXheaacCodecHandle) { - /* Tell that the input is over in this buffer */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INPUT_OVER, - 0, - nullptr); - } - - /* Irrespective of error returned in IA_API_CMD_INPUT_OVER, free allocated memory */ - for (void* buf : mMemoryVec) { - if (buf) free(buf); - } - mMemoryVec.clear(); - mXheaacCodecHandle = nullptr; - - return err_code; -} - -IA_ERRORCODE C2SoftXaacDec::deInitMPEGDDDrc() { - ALOGV("deInitMPEGDDDrc"); - - for (void* buf : mDrcMemoryVec) { - if (buf) free(buf); - } - mDrcMemoryVec.clear(); - return IA_NO_ERROR; -} - -IA_ERRORCODE C2SoftXaacDec::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) { - if (mInputBufferSize < inBufferLength) { - ALOGE("Cannot config AAC, input buffer size %d < inBufferLength %d", mInputBufferSize, inBufferLength); - return false; - } - /* Copy the buffer passed by Android plugin to codec input buffer */ - memcpy(mInputBuffer, inBuffer, inBufferLength); - - /* Set number of bytes to be processed */ - IA_ERRORCODE err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_INPUT_BYTES, - 0, - &inBufferLength); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES"); - - if (mIsCodecConfigFlushRequired) { - /* If codec is already initialized, then GA header is passed again */ - /* Need to call the Flush API instead of INIT_PROCESS */ - mIsCodecInitialized = false; /* Codec needs to be Reinitialized after flush */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_GA_HDR, - nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_GA_HDR"); - } else { - /* Initialize the process */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_PROCESS, - nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_PROCESS"); - } - - uint32_t ui_init_done; - /* Checking for end of initialization */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_DONE_QUERY, - &ui_init_done); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_DONE_QUERY"); - - /* How much buffer is used in input buffers */ - int32_t i_bytes_consumed; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CURIDX_INPUT_BUF, - 0, - &i_bytes_consumed); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_CURIDX_INPUT_BUF"); - - if (ui_init_done) { - err_code = getXAACStreamInfo(); - RETURN_IF_FATAL(err_code, "getXAACStreamInfo"); - ALOGI("Found Codec with below config---\nsampFreq %d\nnumChannels %d\npcmWdSz %d\nchannelMask %d\noutputFrameLength %d", - mSampFreq, mNumChannels, mPcmWdSz, mChannelMask, mOutputFrameLength); - mIsCodecInitialized = true; - - err_code = configMPEGDDrc(); - RETURN_IF_FATAL(err_code, "configMPEGDDrc"); - } - - return IA_NO_ERROR; -} -IA_ERRORCODE C2SoftXaacDec::initMPEGDDDrc() { - IA_ERRORCODE err_code = IA_NO_ERROR; - - for (int i = 0; i < (WORD32)2; i++) { - WORD32 ui_size, ui_alignment, ui_type; - pVOID pv_alloc_ptr; - - /* Get memory size */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size); - - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE"); - - /* Get memory alignment */ - err_code = - ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment); - - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT"); - - /* Get memory type */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE"); - - pv_alloc_ptr = memalign(4, ui_size); - if (pv_alloc_ptr == nullptr) { - ALOGE(" Cannot create requested memory %d", ui_size); - return IA_FATAL_ERROR; - } - mDrcMemoryVec.push(pv_alloc_ptr); - - /* Set the buffer pointer */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr); - - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR"); - } - - WORD32 ui_size; - ui_size = 8192 * 2; - - mDrcInBuf = (int8_t*)memalign(4, ui_size); - if (mDrcInBuf == nullptr) { - ALOGE(" Cannot create requested memory %d", ui_size); - return IA_FATAL_ERROR; - } - mDrcMemoryVec.push(mDrcInBuf); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2, mDrcInBuf); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR"); - - mDrcOutBuf = (int8_t*)memalign(4, ui_size); - if (mDrcOutBuf == nullptr) { - ALOGE(" Cannot create requested memory %d", ui_size); - return IA_FATAL_ERROR; - } - mDrcMemoryVec.push(mDrcOutBuf); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3, mDrcOutBuf); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR"); - - return IA_NO_ERROR; -} -int C2SoftXaacDec::configMPEGDDrc() { - IA_ERRORCODE err_code = IA_NO_ERROR; - int i_effect_type; - int i_loud_norm; - int i_target_loudness; - unsigned int i_sbr_mode; - - /* Sampling Frequency */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ, &mSampFreq); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ"); - /* Total Number of Channels */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS"); - - /* PCM word size */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ"); - - /*Set Effect Type*/ - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE, &i_effect_type); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE, &i_effect_type); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE"); - - /*Set target loudness */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS, - &i_target_loudness); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS, &i_target_loudness); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS"); - - /*Set loud_norm_flag*/ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM, &i_loud_norm); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_DRC_LOUD_NORM, &i_loud_norm); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_LOUD_NORM"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE, &i_sbr_mode); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, nullptr); - - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS"); - - /* Free any memory that is allocated for MPEG D Drc so far */ - deInitMPEGDDDrc(); - - err_code = initMPEGDDDrc(); - if (err_code != IA_NO_ERROR) { - ALOGE("initMPEGDDDrc failed with error %d", err_code); - deInitMPEGDDDrc(); - return err_code; - } - - /* DRC buffers - buf[0] - contains extension element pay load loudness related - buf[1] - contains extension element pay load*/ - { - VOID* p_array[2][16]; - WORD32 ii; - WORD32 buf_sizes[2][16]; - WORD32 num_elements; - WORD32 num_config_ext; - WORD32 bit_str_fmt = 1; - - WORD32 uo_num_chan; - - memset(buf_sizes, 0, 32 * sizeof(WORD32)); - - err_code = - ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_BUF_SIZES, &buf_sizes[0][0]); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_BUF_SIZES"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_PTR, &p_array); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_PTR"); - - err_code = - ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_SET_BUFF_PTR, nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_SET_BUFF_PTR"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_NUM_ELE, &num_elements); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_NUM_ELE"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_NUM_CONFIG_EXT, &num_config_ext); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_NUM_CONFIG_EXT"); - - for (ii = 0; ii < num_config_ext; ii++) { - /*copy loudness bitstream*/ - if (buf_sizes[0][ii] > 0) { - memcpy(mDrcInBuf, p_array[0][ii], buf_sizes[0][ii]); - - /*Set bitstream_split_format */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT"); - - /* Set number of bytes to be processed */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_IL_BS, 0, - &buf_sizes[0][ii]); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES_IL_BS"); - - /* Execute process */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_CPY_IL_BSF_BUFF, nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_CPY_IL_BSF_BUFF"); - - mDRCFlag = 1; - } - } - - for (ii = 0; ii < num_elements; ii++) { - /*copy config bitstream*/ - if (buf_sizes[1][ii] > 0) { - memcpy(mDrcInBuf, p_array[1][ii], buf_sizes[1][ii]); - /* Set number of bytes to be processed */ - - /*Set bitstream_split_format */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_IC_BS, 0, - &buf_sizes[1][ii]); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES_IC_BS"); - - /* Execute process */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_CPY_IC_BSF_BUFF, nullptr); - - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_CPY_IC_BSF_BUFF"); - - mDRCFlag = 1; - } - } - - if (mDRCFlag == 1) { - mMpegDDRCPresent = 1; - } else { - mMpegDDRCPresent = 0; - } - - /*Read interface buffer config file bitstream*/ - if (mMpegDDRCPresent == 1) { - WORD32 interface_is_present = 1; - - if (i_sbr_mode != 0) { - if (i_sbr_mode == 1) { - mOutputFrameLength = 2048; - } else if (i_sbr_mode == 3) { - mOutputFrameLength = 4096; - } else { - mOutputFrameLength = 1024; - } - } else { - mOutputFrameLength = 4096; - } - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE, (WORD32 *)&mOutputFrameLength); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE"); - - err_code = - ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_INT_PRESENT, &interface_is_present); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_INT_PRESENT"); - - /* Execute process */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_CPY_IN_BSF_BUFF, nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_CPY_IN_BSF_BUFF"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_PROCESS, nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_PROCESS"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS, &uo_num_chan); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS"); - } - } - - return err_code; -} - -IA_ERRORCODE C2SoftXaacDec::decodeXAACStream(uint8_t* inBuffer, - uint32_t inBufferLength, - int32_t* bytesConsumed, - int32_t* outBytes) { - if (mInputBufferSize < inBufferLength) { - ALOGE("Cannot config AAC, input buffer size %d < inBufferLength %d", mInputBufferSize, inBufferLength); - return -1; - } - /* Copy the buffer passed by Android plugin to codec input buffer */ - memcpy(mInputBuffer, inBuffer, inBufferLength); - - /* Set number of bytes to be processed */ - IA_ERRORCODE err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_SET_INPUT_BYTES, - 0, - &inBufferLength); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES"); - - /* Execute process */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_EXECUTE, - IA_CMD_TYPE_DO_EXECUTE, - nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE"); - - /* Checking for end of processing */ - uint32_t ui_exec_done; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_EXECUTE, - IA_CMD_TYPE_DONE_QUERY, - &ui_exec_done); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DONE_QUERY"); - - if (ui_exec_done != 1) { - VOID* p_array; // ITTIAM:buffer to handle gain payload - WORD32 buf_size = 0; // ITTIAM:gain payload length - WORD32 bit_str_fmt = 1; - WORD32 gain_stream_flag = 1; - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN, &buf_size); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN"); - - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF, &p_array); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF"); - - if (buf_size > 0) { - /*Set bitstream_split_format */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT"); - - memcpy(mDrcInBuf, p_array, buf_size); - /* Set number of bytes to be processed */ - err_code = - ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_BS, 0, &buf_size); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG, &gain_stream_flag); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT"); - - /* Execute process */ - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, - IA_CMD_TYPE_INIT_CPY_BSF_BUFF, nullptr); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT"); - - mMpegDDRCPresent = 1; - } - } - - /* How much buffer is used in input buffers */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CURIDX_INPUT_BUF, - 0, - bytesConsumed); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_CURIDX_INPUT_BUF"); - - /* Get the output bytes */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_OUTPUT_BYTES, - 0, - outBytes); - RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_OUTPUT_BYTES"); - - if (mMpegDDRCPresent == 1) { - memcpy(mDrcInBuf, mOutputBuffer, *outBytes); - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES, 0, outBytes); - RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES"); - - err_code = - ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, nullptr); - RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE"); - - memcpy(mOutputBuffer, mDrcOutBuf, *outBytes); - } - return IA_NO_ERROR; -} - -IA_ERRORCODE C2SoftXaacDec::getXAACStreamInfo() { - IA_ERRORCODE err_code = IA_NO_ERROR; - - /* Sampling frequency */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ, - &mSampFreq); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ"); - - /* Total Number of Channels */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS, - &mNumChannels); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS"); - if (mNumChannels > MAX_CHANNEL_COUNT) { - ALOGE(" No of channels are more than max channels\n"); - return IA_FATAL_ERROR; - } - - /* PCM word size */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ, - &mPcmWdSz); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ"); - if ((mPcmWdSz / 8) != 2) { - ALOGE(" No of channels are more than max channels\n"); - return IA_FATAL_ERROR; - } - - /* channel mask to tell the arrangement of channels in bit stream */ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MASK, - &mChannelMask); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MASK"); - - /* Channel mode to tell MONO/STEREO/DUAL-MONO/NONE_OF_THESE */ - uint32_t ui_channel_mode; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MODE, - &ui_channel_mode); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MODE"); - if (ui_channel_mode == 0) - ALOGV("Channel Mode: MONO_OR_PS\n"); - else if (ui_channel_mode == 1) - ALOGV("Channel Mode: STEREO\n"); - else if (ui_channel_mode == 2) - ALOGV("Channel Mode: DUAL-MONO\n"); - else - ALOGV("Channel Mode: NONE_OF_THESE or MULTICHANNEL\n"); - - /* Channel mode to tell SBR PRESENT/NOT_PRESENT */ - uint32_t ui_sbr_mode; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, - IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE, - &ui_sbr_mode); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE"); - if (ui_sbr_mode == 0) - ALOGV("SBR Mode: NOT_PRESENT\n"); - else if (ui_sbr_mode == 1) - ALOGV("SBR Mode: PRESENT\n"); - else - ALOGV("SBR Mode: ILLEGAL\n"); - - /* mOutputFrameLength = 1024 * (1 + SBR_MODE) for AAC */ - /* For USAC it could be 1024 * 3 , support to query */ - /* not yet added in codec */ - mOutputFrameLength = 1024 * (1 + ui_sbr_mode); - ALOGI("mOutputFrameLength %d ui_sbr_mode %d", mOutputFrameLength, ui_sbr_mode); - - return IA_NO_ERROR; -} - -IA_ERRORCODE C2SoftXaacDec::setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, - int32_t drcRefLevel, - int32_t drcHeavyCompression, - int32_t drEffectType) { - IA_ERRORCODE err_code = IA_NO_ERROR; - - int32_t ui_drc_enable = 1; - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_ENABLE, - &ui_drc_enable); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_ENABLE"); - if (drcCut != -1) { - err_code = - ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT, &drcCut); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT"); - } - - if (drcBoost != -1) { - err_code = ixheaacd_dec_api( - mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST, &drcBoost); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST"); - } - - if (drcRefLevel != -1) { - err_code = ixheaacd_dec_api( - mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL, &drcRefLevel); - RETURN_IF_FATAL(err_code, - "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL"); - } - - if (drcRefLevel != -1) { - err_code = ixheaacd_dec_api( - mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS, &drcRefLevel); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS"); - } - - if (drcHeavyCompression != -1) { - err_code = - ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP, - &drcHeavyCompression); - RETURN_IF_FATAL(err_code, - "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP"); - } - - err_code = - ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE, &drEffectType); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE"); - - int32_t i_effect_type, i_target_loudness, i_loud_norm; - /*Set Effect Type*/ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE, - &i_effect_type); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE"); - - err_code = - ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE, &i_effect_type); - - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE"); - - /*Set target loudness */ - err_code = ixheaacd_dec_api( - mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS, &i_target_loudness); - RETURN_IF_FATAL(err_code, - "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS, - &i_target_loudness); - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS"); - - /*Set loud_norm_flag*/ - err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, - IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM, - &i_loud_norm); - RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM"); - - err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, - IA_DRC_DEC_CONFIG_DRC_LOUD_NORM, &i_loud_norm); - - RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_LOUD_NORM"); - - return IA_NO_ERROR; -} - -class C2SoftXaacDecFactory : public C2ComponentFactory { -public: - C2SoftXaacDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( - GetCodec2PlatformComponentStore()->getParamReflector())) { - } - - 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 C2SoftXaacDec(COMPONENT_NAME, - id, - std::make_shared<C2SoftXaacDec::IntfImpl>(mHelper)), - 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 = std::shared_ptr<C2ComponentInterface>( - new SimpleInterface<C2SoftXaacDec::IntfImpl>( - COMPONENT_NAME, id, std::make_shared<C2SoftXaacDec::IntfImpl>(mHelper)), - deleter); - return C2_OK; - } - - virtual ~C2SoftXaacDecFactory() override = default; - -private: - std::shared_ptr<C2ReflectorHelper> mHelper; -}; - -} // namespace android - -extern "C" ::C2ComponentFactory* CreateCodec2Factory() { - ALOGV("in %s", __func__); - return new ::android::C2SoftXaacDecFactory(); -} - -extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) { - ALOGV("in %s", __func__); - delete factory; -} diff --git a/media/codecs/xaac/C2SoftXaacDec.h b/media/codecs/xaac/C2SoftXaacDec.h deleted file mode 100644 index 5c8567f..0000000 --- a/media/codecs/xaac/C2SoftXaacDec.h +++ /dev/null @@ -1,131 +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 ANDROID_C2_SOFT_XAAC_DEC_H_ -#define ANDROID_C2_SOFT_XAAC_DEC_H_ -#include <utils/Vector.h> -#include <SimpleC2Component.h> - -#include "ixheaacd_type_def.h" -#include "ixheaacd_error_standards.h" -#include "ixheaacd_error_handler.h" -#include "ixheaacd_apicmd_standards.h" -#include "ixheaacd_memory_standards.h" -#include "ixheaacd_aac_config.h" - -#include "impd_apicmd_standards.h" -#include "impd_drc_config_params.h" - -#define MAX_CHANNEL_COUNT 8 /* maximum number of audio channels that can be decoded */ -#define MAX_NUM_BLOCKS 8 /* maximum number of audio blocks that can be decoded */ - -extern "C" IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_module_obj, - WORD32 i_cmd, WORD32 i_idx, pVOID pv_value); -extern "C" IA_ERRORCODE ia_drc_dec_api(pVOID p_ia_module_obj, - WORD32 i_cmd, WORD32 i_idx, pVOID pv_value); -extern "C" IA_ERRORCODE ixheaacd_get_config_param(pVOID p_ia_process_api_obj, - pWORD32 pi_samp_freq, - pWORD32 pi_num_chan, - pWORD32 pi_pcm_wd_sz, - pWORD32 pi_channel_mask); - -namespace android { - -struct C2SoftXaacDec : public SimpleC2Component { - class IntfImpl; - - C2SoftXaacDec(const char* name, c2_node_id_t id, - const std::shared_ptr<IntfImpl>& intfImpl); - virtual ~C2SoftXaacDec(); - - // 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 { - kOutputDrainBufferSize = 2048 * MAX_CHANNEL_COUNT * MAX_NUM_BLOCKS, - }; - - std::shared_ptr<IntfImpl> mIntf; - void* mXheaacCodecHandle; - void* mMpegDDrcHandle; - uint32_t mInputBufferSize; - uint32_t mOutputFrameLength; - int8_t* mInputBuffer; - int8_t* mOutputBuffer; - int32_t mSampFreq; - int32_t mNumChannels; - int32_t mPcmWdSz; - int32_t mChannelMask; - int32_t mNumOutBytes; - uint64_t mCurFrameIndex; - uint64_t mCurTimestamp; - bool mIsCodecInitialized; - bool mIsCodecConfigFlushRequired; - int8_t* mDrcInBuf; - int8_t* mDrcOutBuf; - int32_t mMpegDDRCPresent; - int32_t mDRCFlag; - - Vector<void*> mMemoryVec; - Vector<void*> mDrcMemoryVec; - - size_t mInputBufferCount __unused; - size_t mOutputBufferCount __unused; - bool mSignalledOutputEos; - bool mSignalledError; - char* mOutputDrainBuffer; - uint32_t mOutputDrainBufferWritePos; - - IA_ERRORCODE initDecoder(); - IA_ERRORCODE setDrcParameter(); - IA_ERRORCODE configflushDecode(); - IA_ERRORCODE drainDecoder(); - void finishWork(const std::unique_ptr<C2Work>& work, - const std::shared_ptr<C2BlockPool>& pool); - - IA_ERRORCODE initXAACDrc(); - IA_ERRORCODE initXAACDecoder(); - IA_ERRORCODE deInitXAACDecoder(); - IA_ERRORCODE initMPEGDDDrc(); - IA_ERRORCODE deInitMPEGDDDrc(); - IA_ERRORCODE configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength); - int configMPEGDDrc(); - IA_ERRORCODE decodeXAACStream(uint8_t* inBuffer, - uint32_t inBufferLength, - int32_t* bytesConsumed, - int32_t* outBytes); - IA_ERRORCODE getXAACStreamInfo(); - IA_ERRORCODE setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, - int32_t drcRefLevel, int32_t drcHeavyCompression, - int32_t drEffectType); - - C2_DO_NOT_COPY(C2SoftXaacDec); -}; - -} // namespace android - -#endif // C2_SOFT_XAAC_H_ diff --git a/media/sfplugin/Android.bp b/media/sfplugin/Android.bp deleted file mode 100644 index 95d2740..0000000 --- a/media/sfplugin/Android.bp +++ /dev/null @@ -1,60 +0,0 @@ -cc_library_shared { - name: "libstagefright_ccodec", - - srcs: [ - "C2OMXNode.cpp", - "CCodec.cpp", - "CCodecBufferChannel.cpp", - "CCodecConfig.cpp", - "Codec2Buffer.cpp", - "Codec2InfoBuilder.cpp", - "ReflectedParamUpdater.cpp", - "SkipCutBuffer.cpp", - ], - - cflags: [ - "-Werror", - "-Wall", - ], - - header_libs: [ - "libmediadrm_headers", - "libstagefright_codec2_internal", - "media_ndk_headers", - ], - - shared_libs: [ - "android.hardware.cas.native@1.0", - "android.hardware.graphics.bufferqueue@1.0", - "android.hardware.media.omx@1.0", - "hardware.google.media.c2@1.0", - "libbase", - "libbinder", - "libcodec2_hidl_client", - "libcutils", - "libgui", - "libhidlallocatorutils", - "libhidlbase", - "liblog", - "libmedia_codeclist", - "libmedia_omx", - "libstagefright_bufferqueue_helper", - "libstagefright_ccodec_utils", - "libstagefright_codec2", - "libstagefright_codec2_vndk", - "libstagefright_codecbase", - "libstagefright_foundation", - "libstagefright_omx_utils", - "libstagefright_xmlparser", - "libui", - "libutils", - ], - - sanitize: { - cfi: true, - misc_undefined: [ - "unsigned-integer-overflow", - "signed-integer-overflow", - ], - }, -} diff --git a/media/sfplugin/C2OMXNode.cpp b/media/sfplugin/C2OMXNode.cpp deleted file mode 100644 index 03d859a..0000000 --- a/media/sfplugin/C2OMXNode.cpp +++ /dev/null @@ -1,329 +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 "C2OMXNode.h" - -namespace android { - -namespace { - -class Buffer2D : public C2Buffer { -public: - explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {} -}; - -} // namespace - -C2OMXNode::C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp) - : mComp(comp), mFrameIndex(0), mWidth(0), mHeight(0), - mAdjustTimestampGapUs(0), mFirstInputFrame(true) { - // TODO: read from intf() - if (!strncmp(comp->getName().c_str(), "c2.android.", 11)) { - mUsage = GRALLOC_USAGE_SW_READ_OFTEN; - } else { - mUsage = GRALLOC_USAGE_HW_VIDEO_ENCODER; - } -} - -status_t C2OMXNode::freeNode() { - mComp.reset(); - return OK; -} - -status_t C2OMXNode::sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) { - if (cmd == OMX_CommandStateSet && param == OMX_StateLoaded) { - // Reset first input frame so if C2OMXNode is recycled, the timestamp does not become - // negative. This is a workaround for HW codecs that do not handle timestamp rollover. - mFirstInputFrame = true; - } - 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: { - OMX_U32 *usage = (OMX_U32 *)params; - *usage = mUsage; - 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 = mWidth; - pDef->format.video.nFrameHeight = mHeight; - err = OK; - break; - } - default: - break; - } - return err; -} - -status_t C2OMXNode::setParameter(OMX_INDEXTYPE index, const void *params, size_t size) { - // handle max/fixed frame duration control - if (index == (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl - && params != NULL - && size == sizeof(OMX_PARAM_U32TYPE)) { - // The incoming number is an int32_t contained in OMX_U32. - mAdjustTimestampGapUs = (int32_t)((OMX_PARAM_U32TYPE*)params)->nU32; - return OK; - } - 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<Codec2Client::Component> comp = mComp.lock(); - if (!comp) { - return NO_INIT; - } - - uint32_t c2Flags = (flags & OMX_BUFFERFLAG_EOS) - ? C2FrameData::FLAG_END_OF_STREAM : 0; - std::shared_ptr<C2GraphicBlock> block; - - C2Handle *handle = nullptr; - if (omxBuf.mBufferType == OMXBuffer::kBufferTypeANWBuffer - && omxBuf.mGraphicBuffer != nullptr) { - std::shared_ptr<C2GraphicAllocation> alloc; - handle = WrapNativeCodec2GrallocHandle( - 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)) { - return BAD_VALUE; - } - - std::unique_ptr<C2Work> work(new C2Work); - work->input.flags = (C2FrameData::flags_t)c2Flags; - work->input.ordinal.timestamp = timestamp; - - // WORKAROUND: adjust timestamp based on gapUs - { - work->input.ordinal.customOrdinal = timestamp; // save input timestamp - if (mFirstInputFrame) { - // grab timestamps on first frame - mPrevInputTimestamp = timestamp; - mPrevCodecTimestamp = timestamp; - mFirstInputFrame = false; - } else if (mAdjustTimestampGapUs > 0) { - work->input.ordinal.timestamp = - mPrevCodecTimestamp - + c2_min((timestamp - mPrevInputTimestamp).peek(), mAdjustTimestampGapUs); - } else if (mAdjustTimestampGapUs < 0) { - work->input.ordinal.timestamp = mPrevCodecTimestamp - mAdjustTimestampGapUs; - } - mPrevInputTimestamp = work->input.ordinal.customOrdinal; - mPrevCodecTimestamp = work->input.ordinal.timestamp; - ALOGV("adjusting %lld to %lld (gap=%lld)", - work->input.ordinal.customOrdinal.peekll(), - work->input.ordinal.timestamp.peekll(), - (long long)mAdjustTimestampGapUs); - } - - 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())), - [buffer, source = getSource()](C2Buffer *ptr) { - delete ptr; - // 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(&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; - } - 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); - return OK; -} - -sp<IOMXBufferSource> C2OMXNode::getSource() { - return mBufferSource; -} - -void C2OMXNode::setFrameSize(uint32_t width, uint32_t height) { - mWidth = width; - mHeight = height; -} - -} // namespace android diff --git a/media/sfplugin/C2OMXNode.h b/media/sfplugin/C2OMXNode.h deleted file mode 100644 index b5a815e..0000000 --- a/media/sfplugin/C2OMXNode.h +++ /dev/null @@ -1,103 +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> -#include <codec2/hidl/client.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 { - explicit C2OMXNode(const std::shared_ptr<Codec2Client::Component> &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(); - void setFrameSize(uint32_t width, uint32_t height); - -private: - std::weak_ptr<Codec2Client::Component> mComp; - sp<IOMXBufferSource> mBufferSource; - std::shared_ptr<C2Allocator> mAllocator; - std::atomic_uint64_t mFrameIndex; - uint32_t mWidth; - uint32_t mHeight; - uint64_t mUsage; - - // WORKAROUND: timestamp adjustment - - // if >0: this is the max timestamp gap, if <0: this is -1 times the fixed timestamp gap - // if 0: no timestamp adjustment is made - // note that C2OMXNode can be recycled between encoding sessions. - int32_t mAdjustTimestampGapUs; - bool mFirstInputFrame; // true for first input - c2_cntr64_t mPrevInputTimestamp; // input timestamp for previous frame - c2_cntr64_t mPrevCodecTimestamp; // adjusted (codec) timestamp for previous frame -}; - -} // namespace android - -#endif // C2_OMX_NODE_H_ diff --git a/media/sfplugin/CCodec.cpp b/media/sfplugin/CCodec.cpp deleted file mode 100644 index 944a8a5..0000000 --- a/media/sfplugin/CCodec.cpp +++ /dev/null @@ -1,1768 +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 <utils/Log.h> - -#include <sstream> -#include <thread> - -#include <C2Config.h> -#include <C2Debug.h> -#include <C2ParamInternal.h> -#include <C2PlatformSupport.h> - -#include <android/IGraphicBufferSource.h> -#include <android/IOMXBufferSource.h> -#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h> -#include <android/hardware/media/omx/1.0/IOmx.h> -#include <android-base/stringprintf.h> -#include <cutils/properties.h> -#include <gui/IGraphicBufferProducer.h> -#include <gui/Surface.h> -#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h> -#include <media/omx/1.0/WGraphicBufferSource.h> -#include <media/openmax/OMX_IndexExt.h> -#include <media/stagefright/BufferProducerWrapper.h> -#include <media/stagefright/MediaCodecConstants.h> -#include <media/stagefright/PersistentSurface.h> -#include <media/stagefright/codec2/1.0/InputSurface.h> - -#include "C2OMXNode.h" -#include "CCodec.h" -#include "CCodecBufferChannel.h" -#include "InputSurfaceWrapper.h" - -extern "C" android::PersistentSurface *CreateInputSurface(); - -namespace android { - -using namespace std::chrono_literals; -using ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer; -using android::base::StringPrintf; -using BGraphicBufferSource = ::android::IGraphicBufferSource; -using ::hardware::google::media::c2::V1_0::IInputSurface; - -namespace { - -class CCodecWatchdog : public AHandler { -private: - enum { - kWhatWatch, - }; - constexpr static int64_t kWatchIntervalUs = 3300000; // 3.3 secs - -public: - static sp<CCodecWatchdog> getInstance() { - static sp<CCodecWatchdog> instance(new CCodecWatchdog); - static std::once_flag flag; - // Call Init() only once. - std::call_once(flag, Init, instance); - return instance; - } - - ~CCodecWatchdog() = default; - - void watch(sp<CCodec> codec) { - bool shouldPost = false; - { - Mutexed<std::set<wp<CCodec>>>::Locked codecs(mCodecsToWatch); - // If a watch message is in flight, piggy-back this instance as well. - // Otherwise, post a new watch message. - shouldPost = codecs->empty(); - codecs->emplace(codec); - } - if (shouldPost) { - ALOGV("posting watch message"); - (new AMessage(kWhatWatch, this))->post(kWatchIntervalUs); - } - } - -protected: - void onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatWatch: { - Mutexed<std::set<wp<CCodec>>>::Locked codecs(mCodecsToWatch); - ALOGV("watch for %zu codecs", codecs->size()); - for (auto it = codecs->begin(); it != codecs->end(); ++it) { - sp<CCodec> codec = it->promote(); - if (codec == nullptr) { - continue; - } - codec->initiateReleaseIfStuck(); - } - codecs->clear(); - break; - } - - default: { - TRESPASS("CCodecWatchdog: unrecognized message"); - } - } - } - -private: - CCodecWatchdog() : mLooper(new ALooper) {} - - static void Init(const sp<CCodecWatchdog> &thiz) { - ALOGV("Init"); - thiz->mLooper->setName("CCodecWatchdog"); - thiz->mLooper->registerHandler(thiz); - thiz->mLooper->start(); - } - - sp<ALooper> mLooper; - - Mutexed<std::set<wp<CCodec>>> mCodecsToWatch; -}; - -class C2InputSurfaceWrapper : public InputSurfaceWrapper { -public: - explicit C2InputSurfaceWrapper( - const std::shared_ptr<Codec2Client::InputSurface> &surface) : - mSurface(surface) { - } - - ~C2InputSurfaceWrapper() override = default; - - status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override { - if (mConnection != nullptr) { - return ALREADY_EXISTS; - } - return toStatusT(mSurface->connectToComponent(comp, &mConnection), - C2_OPERATION_InputSurface_connectToComponent); - } - - void disconnect() override { - if (mConnection != nullptr) { - mConnection->disconnect(); - mConnection = nullptr; - } - } - - status_t start() override { - // InputSurface does not distinguish started state - return OK; - } - - status_t signalEndOfInputStream() override { - C2InputSurfaceEosTuning eos(true); - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = mSurface->getConfigurable()->config({&eos}, C2_MAY_BLOCK, &failures); - if (err != C2_OK) { - return UNKNOWN_ERROR; - } - return OK; - } - - status_t configure(Config &config __unused) { - // TODO - return OK; - } - -private: - std::shared_ptr<Codec2Client::InputSurface> mSurface; - std::shared_ptr<Codec2Client::InputSurfaceConnection> mConnection; -}; - -class GraphicBufferSourceWrapper : public InputSurfaceWrapper { -public: -// explicit GraphicBufferSourceWrapper(const sp<BGraphicBufferSource> &source) : mSource(source) {} - GraphicBufferSourceWrapper( - const sp<BGraphicBufferSource> &source, - uint32_t width, - uint32_t height) - : mSource(source), mWidth(width), mHeight(height) { - mDataSpace = HAL_DATASPACE_BT709; - } - ~GraphicBufferSourceWrapper() override = default; - - status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override { - mNode = new C2OMXNode(comp); - mNode->setFrameSize(mWidth, mHeight); - - // NOTE: we do not use/pass through color aspects from GraphicBufferSource as we - // communicate that directly to the component. - mSource->configure(mNode, mDataSpace); - 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(); - } - - status_t GetStatus(const binder::Status &status) { - status_t err = OK; - if (!status.isOk()) { - err = status.serviceSpecificErrorCode(); - if (err == OK) { - err = status.transactionError(); - if (err == OK) { - // binder status failed, but there is no servie or transaction error - err = UNKNOWN_ERROR; - } - } - } - return err; - } - - status_t start() override { - 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; - } - - status_t signalEndOfInputStream() override { - return GetStatus(mSource->signalEndOfInputStream()); - } - - status_t configure(Config &config) { - std::stringstream status; - status_t err = OK; - - // handle each configuration granually, in case we need to handle part of the configuration - // elsewhere - - // TRICKY: we do not unset frame delay repeating - if (config.mMinFps > 0 && config.mMinFps != mConfig.mMinFps) { - int64_t us = 1e6 / config.mMinFps + 0.5; - status_t res = GetStatus(mSource->setRepeatPreviousFrameDelayUs(us)); - status << " minFps=" << config.mMinFps << " => repeatDelayUs=" << us; - if (res != OK) { - status << " (=> " << asString(res) << ")"; - err = res; - } - mConfig.mMinFps = config.mMinFps; - } - - // pts gap - if (config.mMinAdjustedFps > 0 || config.mFixedAdjustedFps > 0) { - if (mNode != nullptr) { - OMX_PARAM_U32TYPE ptrGapParam = {}; - ptrGapParam.nSize = sizeof(OMX_PARAM_U32TYPE); - ptrGapParam.nU32 = (config.mMinAdjustedFps > 0) - ? c2_min(INT32_MAX + 0., 1e6 / config.mMinAdjustedFps + 0.5) - : c2_max(0. - INT32_MAX, -1e6 / config.mFixedAdjustedFps - 0.5); - (void)mNode->setParameter( - (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl, - &ptrGapParam, sizeof(ptrGapParam)); - } - } - - // max fps - // TRICKY: we do not unset max fps to 0 unless using fixed fps - if ((config.mMaxFps > 0 || (config.mFixedAdjustedFps > 0 && config.mMaxFps == 0)) - && config.mMaxFps != mConfig.mMaxFps) { - status_t res = GetStatus(mSource->setMaxFps(config.mMaxFps)); - status << " maxFps=" << config.mMaxFps; - if (res != OK) { - status << " (=> " << asString(res) << ")"; - err = res; - } - mConfig.mMaxFps = config.mMaxFps; - } - - if (config.mTimeOffsetUs != mConfig.mTimeOffsetUs) { - status_t res = GetStatus(mSource->setTimeOffsetUs(config.mTimeOffsetUs)); - status << " timeOffset " << config.mTimeOffsetUs << "us"; - if (res != OK) { - status << " (=> " << asString(res) << ")"; - err = res; - } - mConfig.mTimeOffsetUs = config.mTimeOffsetUs; - } - - if (config.mCaptureFps != mConfig.mCaptureFps || config.mCodedFps != mConfig.mCodedFps) { - status_t res = - GetStatus(mSource->setTimeLapseConfig(config.mCodedFps, config.mCaptureFps)); - status << " timeLapse " << config.mCaptureFps << "fps as " << config.mCodedFps << "fps"; - if (res != OK) { - status << " (=> " << asString(res) << ")"; - err = res; - } - mConfig.mCaptureFps = config.mCaptureFps; - mConfig.mCodedFps = config.mCodedFps; - } - - if (config.mStartAtUs != mConfig.mStartAtUs - || (config.mStopped != mConfig.mStopped && !config.mStopped)) { - status_t res = GetStatus(mSource->setStartTimeUs(config.mStartAtUs)); - status << " start at " << config.mStartAtUs << "us"; - if (res != OK) { - status << " (=> " << asString(res) << ")"; - err = res; - } - mConfig.mStartAtUs = config.mStartAtUs; - mConfig.mStopped = config.mStopped; - } - - // suspend-resume - if (config.mSuspended != mConfig.mSuspended) { - status_t res = GetStatus(mSource->setSuspend(config.mSuspended, config.mSuspendAtUs)); - status << " " << (config.mSuspended ? "suspend" : "resume") - << " at " << config.mSuspendAtUs << "us"; - if (res != OK) { - status << " (=> " << asString(res) << ")"; - err = res; - } - mConfig.mSuspended = config.mSuspended; - mConfig.mSuspendAtUs = config.mSuspendAtUs; - } - - if (config.mStopped != mConfig.mStopped && config.mStopped) { - status_t res = GetStatus(mSource->setStopTimeUs(config.mStopAtUs)); - status << " stop at " << config.mStopAtUs << "us"; - if (res != OK) { - status << " (=> " << asString(res) << ")"; - err = res; - } else { - status << " delayUs"; - res = GetStatus(mSource->getStopTimeOffsetUs(&config.mInputDelayUs)); - if (res != OK) { - status << " (=> " << asString(res) << ")"; - } else { - status << "=" << config.mInputDelayUs << "us"; - } - mConfig.mInputDelayUs = config.mInputDelayUs; - } - mConfig.mStopAtUs = config.mStopAtUs; - mConfig.mStopped = config.mStopped; - } - - // color aspects (android._color-aspects) - - // consumer usage - ALOGD("ISConfig%s", status.str().c_str()); - return err; - } - -private: - sp<BGraphicBufferSource> mSource; - sp<C2OMXNode> mNode; - uint32_t mWidth; - uint32_t mHeight; - Config mConfig; -}; - -class Codec2ClientInterfaceWrapper : public C2ComponentStore { - std::shared_ptr<Codec2Client> mClient; - -public: - Codec2ClientInterfaceWrapper(std::shared_ptr<Codec2Client> client) - : mClient(client) { } - - virtual ~Codec2ClientInterfaceWrapper() = default; - - virtual c2_status_t config_sm( - const std::vector<C2Param *> ¶ms, - std::vector<std::unique_ptr<C2SettingResult>> *const failures) { - return mClient->config(params, C2_MAY_BLOCK, failures); - }; - - virtual c2_status_t copyBuffer( - std::shared_ptr<C2GraphicBuffer>, - std::shared_ptr<C2GraphicBuffer>) { - return C2_OMITTED; - } - - virtual c2_status_t createComponent( - C2String, std::shared_ptr<C2Component> *const component) { - component->reset(); - return C2_OMITTED; - } - - virtual c2_status_t createInterface( - C2String, std::shared_ptr<C2ComponentInterface> *const interface) { - interface->reset(); - return C2_OMITTED; - } - - virtual c2_status_t query_sm( - const std::vector<C2Param *> &stackParams, - const std::vector<C2Param::Index> &heapParamIndices, - std::vector<std::unique_ptr<C2Param>> *const heapParams) const { - return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams); - } - - virtual c2_status_t querySupportedParams_nb( - std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const { - return mClient->querySupportedParams(params); - } - - virtual c2_status_t querySupportedValues_sm( - std::vector<C2FieldSupportedValuesQuery> &fields) const { - return mClient->querySupportedValues(fields, C2_MAY_BLOCK); - } - - virtual C2String getName() const { - return mClient->getName(); - } - - virtual std::shared_ptr<C2ParamReflector> getParamReflector() const { - return mClient->getParamReflector(); - } - - virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() { - return std::vector<std::shared_ptr<const C2Component::Traits>>(); - } -}; - -} // namespace - -// CCodec::ClientListener - -struct CCodec::ClientListener : public Codec2Client::Listener { - - explicit ClientListener(const wp<CCodec> &codec) : mCodec(codec) {} - - virtual void onWorkDone( - const std::weak_ptr<Codec2Client::Component>& component, - std::list<std::unique_ptr<C2Work>>& workItems, - size_t numDiscardedInputBuffers) override { - (void)component; - sp<CCodec> codec(mCodec.promote()); - if (!codec) { - return; - } - codec->onWorkDone(workItems, numDiscardedInputBuffers); - } - - virtual void onTripped( - const std::weak_ptr<Codec2Client::Component>& component, - const std::vector<std::shared_ptr<C2SettingResult>>& settingResult - ) override { - // TODO - (void)component; - (void)settingResult; - } - - virtual void onError( - const std::weak_ptr<Codec2Client::Component>& component, - uint32_t errorCode) override { - // TODO - (void)component; - (void)errorCode; - } - - virtual void onDeath( - const std::weak_ptr<Codec2Client::Component>& component) override { - { // Log the death of the component. - std::shared_ptr<Codec2Client::Component> comp = component.lock(); - if (!comp) { - ALOGE("Codec2 component died."); - } else { - ALOGE("Codec2 component \"%s\" died.", comp->getName().c_str()); - } - } - - // Report to MediaCodec. - sp<CCodec> codec(mCodec.promote()); - if (!codec || !codec->mCallback) { - return; - } - codec->mCallback->onError(DEAD_OBJECT, ACTION_CODE_FATAL); - } - - virtual void onFramesRendered( - const std::vector<RenderedFrame>& renderedFrames) override { - // TODO - (void)renderedFrames; - } - - virtual void onInputBufferDone( - const std::shared_ptr<C2Buffer>& buffer) override { - sp<CCodec> codec(mCodec.promote()); - if (codec) { - codec->onInputBufferDone(buffer); - } - } - -private: - wp<CCodec> mCodec; -}; - -// CCodecCallbackImpl - -class CCodecCallbackImpl : public CCodecCallback { -public: - explicit CCodecCallbackImpl(CCodec *codec) : mCodec(codec) {} - ~CCodecCallbackImpl() override = default; - - void onError(status_t err, enum ActionCode actionCode) override { - mCodec->mCallback->onError(err, actionCode); - } - - void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) override { - mCodec->mCallback->onOutputFramesRendered( - {RenderedFrameInfo(mediaTimeUs, renderTimeNs)}); - } - - void onWorkQueued(bool eos) override { - mCodec->onWorkQueued(eos); - } - - void onOutputBuffersChanged() override { - mCodec->mCallback->onOutputBuffersChanged(); - } - -private: - CCodec *mCodec; -}; - -// CCodec - -CCodec::CCodec() - : mChannel(new CCodecBufferChannel(std::make_shared<CCodecCallbackImpl>(this))), - mQueuedWorkCount(0) { -} - -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; - } - ALOGD("allocate(%s)", codecInfo->getCodecName()); - mClientListener.reset(new ClientListener(this)); - - AString componentName = codecInfo->getCodecName(); - std::shared_ptr<Codec2Client> client; - - // set up preferred component store to access vendor store parameters - client = Codec2Client::CreateFromService("default", false); - if (client) { - ALOGI("setting up '%s' as default (vendor) store", client->getInstanceName().c_str()); - SetPreferredCodec2ComponentStore( - std::make_shared<Codec2ClientInterfaceWrapper>(client)); - } - - std::shared_ptr<Codec2Client::Component> comp = - Codec2Client::CreateComponentByName( - componentName.c_str(), - mClientListener, - &client); - if (!comp) { - ALOGE("Failed Create component: %s", componentName.c_str()); - Mutexed<State>::Locked state(mState); - state->set(RELEASED); - state.unlock(); - mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); - state.lock(); - return; - } - ALOGI("Created component [%s]", componentName.c_str()); - mChannel->setComponent(comp); - auto setAllocated = [this, comp, client] { - Mutexed<State>::Locked state(mState); - if (state->get() != ALLOCATING) { - state->set(RELEASED); - return UNKNOWN_ERROR; - } - state->set(ALLOCATED); - state->comp = comp; - mClient = client; - return OK; - }; - if (tryAndReportOnError(setAllocated) != OK) { - return; - } - - // initialize config here in case setParameters is called prior to configure - Mutexed<Config>::Locked config(mConfig); - status_t err = config->initialize(mClient, comp); - if (err != OK) { - ALOGW("Failed to initialize configuration support"); - // TODO: report error once we complete implementation. - } - config->queryConfiguration(comp); - - mCallback->onComponentAllocated(componentName.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<Codec2Client::Component> comp; - auto checkAllocated = [this, &comp] { - Mutexed<State>::Locked state(mState); - if (state->get() != ALLOCATED) { - state->set(RELEASED); - return UNKNOWN_ERROR; - } - comp = state->comp; - return OK; - }; - if (tryAndReportOnError(checkAllocated) != OK) { - return; - } - - auto doConfig = [msg, comp, this]() -> status_t { - 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) != (comp->getName().find("encoder") == std::string::npos)) { - return UNKNOWN_ERROR; - } - - int32_t storeMeta; - if (encoder - && msg->findInt32("android._input-metadata-buffer-type", &storeMeta) - && storeMeta != kMetadataBufferTypeInvalid) { - if (storeMeta != kMetadataBufferTypeANWBuffer) { - ALOGD("Only ANW buffers are supported for legacy metadata mode"); - return BAD_VALUE; - } - mChannel->setMetaMode(CCodecBufferChannel::MODE_ANW); - } - - sp<RefBase> obj; - sp<Surface> surface; - if (msg->findObject("native-window", &obj)) { - surface = static_cast<Surface *>(obj.get()); - setSurface(surface); - } - - Mutexed<Config>::Locked config(mConfig); - config->mUsingSurface = surface != nullptr; - - /* - * Handle input surface configuration - */ - if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE)) - && (config->mDomain & Config::IS_ENCODER)) { - config->mISConfig.reset(new InputSurfaceWrapper::Config{}); - { - config->mISConfig->mMinFps = 0; - int64_t value; - if (msg->findInt64("repeat-previous-frame-after", &value) && value > 0) { - config->mISConfig->mMinFps = 1e6 / value; - } - (void)msg->findFloat("max-fps-to-encoder", &config->mISConfig->mMaxFps); - config->mISConfig->mMinAdjustedFps = 0; - config->mISConfig->mFixedAdjustedFps = 0; - if (msg->findInt64("max-pts-gap-to-encoder", &value)) { - if (value < 0 && value >= INT32_MIN) { - config->mISConfig->mFixedAdjustedFps = -1e6 / value; - } else if (value > 0 && value <= INT32_MAX) { - config->mISConfig->mMinAdjustedFps = 1e6 / value; - } - } - } - - { - double value; - if (msg->findDouble("time-lapse-fps", &value)) { - config->mISConfig->mCaptureFps = value; - (void)msg->findAsFloat(KEY_FRAME_RATE, &config->mISConfig->mCodedFps); - } - } - - { - config->mISConfig->mSuspended = false; - config->mISConfig->mSuspendAtUs = -1; - int32_t value; - if (msg->findInt32("create-input-buffers-suspended", &value) && value) { - config->mISConfig->mSuspended = true; - } - } - } - - /* - * Handle desired color format. - */ - if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) { - int32_t format = -1; - if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) { - /* - * Also handle default color format (encoders require color format, so this is only - * needed for decoders. - */ - if (!(config->mDomain & Config::IS_ENCODER)) { - format = (surface == nullptr) ? COLOR_FormatYUV420Planar : COLOR_FormatSurface; - } - } - - if (format >= 0) { - msg->setInt32("android._color-format", format); - } - } - - std::vector<std::unique_ptr<C2Param>> configUpdate; - status_t err = config->getConfigUpdateFromSdkParams( - comp, msg, Config::IS_CONFIG, C2_DONT_BLOCK, &configUpdate); - if (err != OK) { - ALOGW("failed to convert configuration to c2 params"); - } - err = config->setParameters(comp, configUpdate, C2_DONT_BLOCK); - if (err != OK) { - ALOGW("failed to configure c2 params"); - return err; - } - - std::vector<std::unique_ptr<C2Param>> params; - C2StreamUsageTuning::input usage(0u, 0u); - C2StreamMaxBufferSizeInfo::input maxInputSize(0u, 0u); - - std::initializer_list<C2Param::Index> indices { - }; - c2_status_t c2err = comp->query( - { &usage, &maxInputSize }, - indices, - C2_DONT_BLOCK, - ¶ms); - if (c2err != C2_OK && c2err != C2_BAD_INDEX) { - ALOGE("Failed to query component interface: %d", c2err); - return UNKNOWN_ERROR; - } - if (params.size() != indices.size()) { - ALOGE("Component returns wrong number of params: expected %zu actual %zu", - indices.size(), params.size()); - return UNKNOWN_ERROR; - } - if (usage && (usage.value & C2MemoryUsage::CPU_READ)) { - config->mInputFormat->setInt32("using-sw-read-often", true); - } - - // NOTE: we don't blindly use client specified input size if specified as clients - // at times specify too small size. Instead, mimic the behavior from OMX, where the - // client specified size is only used to ask for bigger buffers than component suggested - // size. - int32_t clientInputSize = 0; - bool clientSpecifiedInputSize = - msg->findInt32(KEY_MAX_INPUT_SIZE, &clientInputSize) && clientInputSize > 0; - // TEMP: enforce minimum buffer size of 1MB for video decoders - // and 16K / 4K for audio encoders/decoders - if (maxInputSize.value == 0) { - if (config->mDomain & Config::IS_AUDIO) { - maxInputSize.value = encoder ? 16384 : 4096; - } else if (!encoder) { - maxInputSize.value = 1048576u; - } - } - - // verify that CSD fits into this size (if defined) - if ((config->mDomain & Config::IS_DECODER) && maxInputSize.value > 0) { - sp<ABuffer> csd; - for (size_t ix = 0; msg->findBuffer(StringPrintf("csd-%zu", ix).c_str(), &csd); ++ix) { - if (csd && csd->size() > maxInputSize.value) { - maxInputSize.value = csd->size(); - } - } - } - - // TODO: do this based on component requiring linear allocator for input - if ((config->mDomain & Config::IS_DECODER) || (config->mDomain & Config::IS_AUDIO)) { - if (clientSpecifiedInputSize) { - // Warn that we're overriding client's max input size if necessary. - if ((uint32_t)clientInputSize < maxInputSize.value) { - ALOGD("client requested max input size %d, which is smaller than " - "what component recommended (%u); overriding with component " - "recommendation.", clientInputSize, maxInputSize.value); - ALOGW("This behavior is subject to change. It is recommended that " - "app developers double check whether the requested " - "max input size is in reasonable range."); - } else { - maxInputSize.value = clientInputSize; - } - } - // Pass max input size on input format to the buffer channel (if supplied by the - // component or by a default) - if (maxInputSize.value) { - config->mInputFormat->setInt32( - KEY_MAX_INPUT_SIZE, - (int32_t)(c2_min(maxInputSize.value, uint32_t(INT32_MAX)))); - } - } - - if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) { - // propagate HDR static info to output format for both encoders and decoders - // if component supports this info, we will update from component, but only the raw port, - // so don't propagate if component already filled it in. - sp<ABuffer> hdrInfo; - if (msg->findBuffer(KEY_HDR_STATIC_INFO, &hdrInfo) - && !config->mOutputFormat->findBuffer(KEY_HDR_STATIC_INFO, &hdrInfo)) { - config->mOutputFormat->setBuffer(KEY_HDR_STATIC_INFO, hdrInfo); - } - - // Set desired color format from configuration parameter - int32_t format; - if (msg->findInt32("android._color-format", &format)) { - if (config->mDomain & Config::IS_ENCODER) { - config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format); - } else { - config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format); - } - } - } - - // propagate encoder delay and padding to output format - if ((config->mDomain & Config::IS_DECODER) && (config->mDomain & Config::IS_AUDIO)) { - int delay = 0; - if (msg->findInt32("encoder-delay", &delay)) { - config->mOutputFormat->setInt32("encoder-delay", delay); - } - int padding = 0; - if (msg->findInt32("encoder-padding", &padding)) { - config->mOutputFormat->setInt32("encoder-padding", padding); - } - } - - // set channel-mask - if (config->mDomain & Config::IS_AUDIO) { - int32_t mask; - if (msg->findInt32(KEY_CHANNEL_MASK, &mask)) { - if (config->mDomain & Config::IS_ENCODER) { - config->mInputFormat->setInt32(KEY_CHANNEL_MASK, mask); - } else { - config->mOutputFormat->setInt32(KEY_CHANNEL_MASK, mask); - } - } - } - - ALOGD("setup formats input: %s and output: %s", - config->mInputFormat->debugString().c_str(), - config->mOutputFormat->debugString().c_str()); - return OK; - }; - if (tryAndReportOnError(doConfig) != OK) { - return; - } - - Mutexed<Config>::Locked config(mConfig); - - mCallback->onComponentConfigured(config->mInputFormat, config->mOutputFormat); -} - -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->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() { - status_t err; - sp<IGraphicBufferProducer> bufferProducer; - - sp<AMessage> inputFormat; - sp<AMessage> outputFormat; - { - Mutexed<Config>::Locked config(mConfig); - inputFormat = config->mInputFormat; - outputFormat = config->mOutputFormat; - } - - std::shared_ptr<PersistentSurface> persistentSurface(CreateInputSurface()); - - if (persistentSurface->getHidlTarget()) { - sp<IInputSurface> inputSurface = IInputSurface::castFrom( - persistentSurface->getHidlTarget()); - if (!inputSurface) { - ALOGE("Corrupted input surface"); - mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR); - return; - } - err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>( - std::make_shared<Codec2Client::InputSurface>(inputSurface))); - bufferProducer = new H2BGraphicBufferProducer(inputSurface); - } else { - int32_t width = 0; - (void)outputFormat->findInt32("width", &width); - int32_t height = 0; - (void)outputFormat->findInt32("height", &height); - err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>( - persistentSurface->getBufferSource(), width, height)); - bufferProducer = persistentSurface->getBufferProducer(); - } - - if (err != OK) { - ALOGE("Failed to set up input surface: %d", err); - mCallback->onInputSurfaceCreationFailed(err); - return; - } - - mCallback->onInputSurfaceCreated( - inputFormat, - outputFormat, - new BufferProducerWrapper(bufferProducer)); -} - -status_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) { - Mutexed<Config>::Locked config(mConfig); - config->mUsingSurface = true; - - // we are now using surface - apply default color aspects to input format - as well as - // get dataspace - bool inputFormatChanged = config->updateFormats(config->IS_INPUT); - ALOGD("input format %s to %s", - inputFormatChanged ? "changed" : "unchanged", - config->mInputFormat->debugString().c_str()); - - // configure dataspace - static_assert(sizeof(int32_t) == sizeof(android_dataspace), "dataspace size mismatch"); - android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; - (void)config->mInputFormat->findInt32("android._dataspace", (int32_t*)&dataSpace); - surface->setDataSpace(dataSpace); - - status_t err = mChannel->setInputSurface(surface); - if (err != OK) { - // undo input format update - config->mUsingSurface = false; - (void)config->updateFormats(config->IS_INPUT); - return err; - } - config->mInputSurface = surface; - - if (config->mISConfig) { - surface->configure(*config->mISConfig); - } else { - ALOGD("ISConfig: no configuration"); - } - - 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) { - sp<AMessage> inputFormat; - sp<AMessage> outputFormat; - { - Mutexed<Config>::Locked config(mConfig); - inputFormat = config->mInputFormat; - outputFormat = config->mOutputFormat; - } - auto hidlTarget = surface->getHidlTarget(); - if (hidlTarget) { - sp<IInputSurface> inputSurface = - IInputSurface::castFrom(hidlTarget); - if (!inputSurface) { - ALOGE("Failed to set input surface: Corrupted surface."); - mCallback->onInputSurfaceDeclined(UNKNOWN_ERROR); - return; - } - status_t err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>( - std::make_shared<Codec2Client::InputSurface>(inputSurface))); - if (err != OK) { - ALOGE("Failed to set up input surface: %d", err); - mCallback->onInputSurfaceDeclined(err); - return; - } - } else { - int32_t width = 0; - (void)outputFormat->findInt32("width", &width); - int32_t height = 0; - (void)outputFormat->findInt32("height", &height); - status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>( - surface->getBufferSource(), width, height)); - if (err != OK) { - ALOGE("Failed to set up input surface: %d", err); - mCallback->onInputSurfaceDeclined(err); - return; - } - } - 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<Codec2Client::Component> 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) { - mCallback->onError(toStatusT(err, C2_OPERATION_Component_start), - ACTION_CODE_FATAL); - return; - } - sp<AMessage> inputFormat; - sp<AMessage> outputFormat; - status_t err2 = OK; - { - Mutexed<Config>::Locked config(mConfig); - inputFormat = config->mInputFormat; - outputFormat = config->mOutputFormat; - if (config->mInputSurface) { - err2 = config->mInputSurface->start(); - } - } - if (err2 != OK) { - mCallback->onError(err2, ACTION_CODE_FATAL); - return; - } - 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)mChannel->requestInitialInputBuffers(); -} - -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); - } - - mChannel->stop(); - (new AMessage(kWhatStop, this))->post(); -} - -void CCodec::stop() { - std::shared_ptr<Codec2Client::Component> 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; - } - status_t err = comp->stop(); - if (err != C2_OK) { - // TODO: convert err into status_t - mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); - } - - { - Mutexed<Config>::Locked config(mConfig); - if (config->mInputSurface) { - config->mInputSurface->disconnect(); - config->mInputSurface = nullptr; - } - } - { - Mutexed<State>::Locked state(mState); - if (state->get() == STOPPING) { - state->set(ALLOCATED); - } - } - mCallback->onStopCompleted(); -} - -void CCodec::initiateRelease(bool sendCallback /* = true */) { - bool clearInputSurfaceIfNeeded = false; - { - 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; - } - if (state->get() == STARTING - || state->get() == RUNNING - || state->get() == STOPPING) { - // Input surface may have been started, so clean up is needed. - clearInputSurfaceIfNeeded = true; - } - state->set(RELEASING); - } - - if (clearInputSurfaceIfNeeded) { - Mutexed<Config>::Locked config(mConfig); - if (config->mInputSurface) { - config->mInputSurface->disconnect(); - config->mInputSurface = nullptr; - } - } - - mChannel->stop(); - // thiz holds strong ref to this while the thread is running. - sp<CCodec> thiz(this); - std::thread([thiz, sendCallback] { thiz->release(sendCallback); }).detach(); -} - -void CCodec::release(bool sendCallback) { - std::shared_ptr<Codec2Client::Component> comp; - { - Mutexed<State>::Locked state(mState); - if (state->get() == RELEASED) { - if (sendCallback) { - state.unlock(); - mCallback->onReleaseCompleted(); - state.lock(); - } - return; - } - comp = state->comp; - } - 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; - } - - mChannel->stop(); - (new AMessage(kWhatFlush, this))->post(); -} - -void CCodec::flush() { - std::shared_ptr<Codec2Client::Component> 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; - } - - std::list<std::unique_ptr<C2Work>> flushedWork; - c2_status_t err = comp->flush(C2Component::FLUSH_COMPONENT, &flushedWork); - { - Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue); - flushedWork.splice(flushedWork.end(), *queue); - } - if (err != C2_OK) { - // TODO: convert err into status_t - mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); - } - - mChannel->flush(flushedWork); - subQueuedWorkCount(flushedWork.size()); - - { - 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)mChannel->requestInitialInputBuffers(); -} - -void CCodec::signalSetParameters(const sp<AMessage> ¶ms) { - setParameters(params); -} - -void CCodec::setParameters(const sp<AMessage> ¶ms) { - std::shared_ptr<Codec2Client::Component> comp; - auto checkState = [this, &comp] { - Mutexed<State>::Locked state(mState); - if (state->get() == RELEASED) { - return INVALID_OPERATION; - } - comp = state->comp; - return OK; - }; - if (tryAndReportOnError(checkState) != OK) { - return; - } - - Mutexed<Config>::Locked config(mConfig); - - /** - * Handle input surface parameters - */ - if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE)) - && (config->mDomain & Config::IS_ENCODER) && config->mInputSurface && config->mISConfig) { - (void)params->findInt64("time-offset-us", &config->mISConfig->mTimeOffsetUs); - - if (params->findInt64("skip-frames-before", &config->mISConfig->mStartAtUs)) { - config->mISConfig->mStopped = false; - } else if (params->findInt64("stop-time-us", &config->mISConfig->mStopAtUs)) { - config->mISConfig->mStopped = true; - } - - int32_t value; - if (params->findInt32("drop-input-frames", &value)) { - config->mISConfig->mSuspended = value; - config->mISConfig->mSuspendAtUs = -1; - (void)params->findInt64("drop-start-time-us", &config->mISConfig->mSuspendAtUs); - } - - (void)config->mInputSurface->configure(*config->mISConfig); - if (config->mISConfig->mStopped) { - config->mInputFormat->setInt64( - "android._stop-time-offset-us", config->mISConfig->mInputDelayUs); - } - } - - std::vector<std::unique_ptr<C2Param>> configUpdate; - (void)config->getConfigUpdateFromSdkParams( - comp, params, Config::IS_PARAM, C2_MAY_BLOCK, &configUpdate); - // Prefer to pass parameters to the buffer channel, so they can be synchronized with the frames. - // Parameter synchronization is not defined when using input surface. For now, route - // these directly to the component. - if (config->mInputSurface == nullptr - && (property_get_bool("debug.stagefright.ccodec_delayed_params", false) - || comp->getName().find("c2.android.") == 0)) { - mChannel->setParameters(configUpdate); - } else { - (void)config->setParameters(comp, configUpdate, C2_MAY_BLOCK); - } -} - -void CCodec::signalEndOfInputStream() { - mCallback->onSignaledInputEOS(mChannel->signalEndOfInputStream()); -} - -void CCodec::signalRequestIDRFrame() { - std::shared_ptr<Codec2Client::Component> comp; - { - Mutexed<State>::Locked state(mState); - if (state->get() == RELEASED) { - ALOGD("no IDR request sent since component is released"); - return; - } - comp = state->comp; - } - ALOGV("request IDR"); - Mutexed<Config>::Locked config(mConfig); - std::vector<std::unique_ptr<C2Param>> params; - params.push_back( - std::make_unique<C2StreamRequestSyncFrameTuning::output>(0u, true)); - config->setParameters(comp, params, C2_MAY_BLOCK); -} - -void CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems, - size_t numDiscardedInputBuffers) { - if (!workItems.empty()) { - { - Mutexed<std::list<size_t>>::Locked numDiscardedInputBuffersQueue( - mNumDiscardedInputBuffersQueue); - numDiscardedInputBuffersQueue->insert( - numDiscardedInputBuffersQueue->end(), - workItems.size() - 1, 0); - numDiscardedInputBuffersQueue->emplace_back( - numDiscardedInputBuffers); - } - { - Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue); - queue->splice(queue->end(), workItems); - } - } - (new AMessage(kWhatWorkDone, this))->post(); -} - -void CCodec::onInputBufferDone(const std::shared_ptr<C2Buffer>& buffer) { - mChannel->onInputBufferDone(buffer); -} - -void CCodec::onMessageReceived(const sp<AMessage> &msg) { - TimePoint now = std::chrono::steady_clock::now(); - CCodecWatchdog::getInstance()->watch(this); - 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, 250ms, "configure"); - sp<AMessage> format; - CHECK(msg->findMessage("format", &format)); - configure(format); - break; - } - case kWhatStart: { - // C2Component::start() should return within 500ms. - setDeadline(now, 550ms, "start"); - mQueuedWorkCount = 0; - start(); - break; - } - case kWhatStop: { - // C2Component::stop() should return within 500ms. - setDeadline(now, 550ms, "stop"); - stop(); - - mQueuedWorkCount = 0; - Mutexed<NamedTimePoint>::Locked deadline(mQueueDeadline); - deadline->set(TimePoint::max(), "none"); - 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; - size_t numDiscardedInputBuffers; - bool shouldPost = false; - { - Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue); - if (queue->empty()) { - break; - } - work.swap(queue->front()); - queue->pop_front(); - shouldPost = !queue->empty(); - } - { - Mutexed<std::list<size_t>>::Locked numDiscardedInputBuffersQueue( - mNumDiscardedInputBuffersQueue); - if (numDiscardedInputBuffersQueue->empty()) { - numDiscardedInputBuffers = 0; - } else { - numDiscardedInputBuffers = numDiscardedInputBuffersQueue->front(); - numDiscardedInputBuffersQueue->pop_front(); - } - } - if (shouldPost) { - (new AMessage(kWhatWorkDone, this))->post(); - } - - if (work->worklets.empty() - || !(work->worklets.front()->output.flags & C2FrameData::FLAG_INCOMPLETE)) { - subQueuedWorkCount(1); - } - // handle configuration changes in work done - Mutexed<Config>::Locked config(mConfig); - bool changed = false; - Config::Watcher<C2StreamInitDataInfo::output> initData = - config->watch<C2StreamInitDataInfo::output>(); - if (!work->worklets.empty() - && (work->worklets.front()->output.flags - & C2FrameData::FLAG_DISCARD_FRAME) == 0) { - - // copy buffer info to config - std::vector<std::unique_ptr<C2Param>> updates = - std::move(work->worklets.front()->output.configUpdate); - 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()) { - // move all info into output-stream #0 domain - updates.emplace_back(C2Param::CopyAsStream(*info, true /* output */, stream)); - } - for (const C2ConstGraphicBlock &block : buf->data().graphicBlocks()) { - // ALOGV("got output buffer with crop %u,%u+%u,%u and size %u,%u", - // block.crop().left, block.crop().top, - // block.crop().width, block.crop().height, - // block.width(), block.height()); - updates.emplace_back(new C2StreamCropRectInfo::output(stream, block.crop())); - updates.emplace_back(new C2StreamPictureSizeInfo::output( - stream, block.width(), block.height())); - break; // for now only do the first block - } - ++stream; - } - - changed = config->updateConfiguration(updates, config->mOutputDomain); - - // copy standard infos to graphic buffers if not already present (otherwise, we - // may overwrite the actual intermediate value with a final value) - stream = 0; - const static std::vector<C2Param::Index> stdGfxInfos = { - C2StreamRotationInfo::output::PARAM_TYPE, - C2StreamColorAspectsInfo::output::PARAM_TYPE, - C2StreamDataSpaceInfo::output::PARAM_TYPE, - C2StreamHdrStaticInfo::output::PARAM_TYPE, - C2StreamHdr10PlusInfo::output::PARAM_TYPE, - C2StreamPixelAspectRatioInfo::output::PARAM_TYPE, - C2StreamSurfaceScalingInfo::output::PARAM_TYPE - }; - for (const std::shared_ptr<C2Buffer> &buf : work->worklets.front()->output.buffers) { - if (buf->data().graphicBlocks().size()) { - for (C2Param::Index ix : stdGfxInfos) { - if (!buf->hasInfo(ix)) { - const C2Param *param = - config->getConfigParameterValue(ix.withStream(stream)); - if (param) { - std::shared_ptr<C2Param> info(C2Param::Copy(*param)); - buf->setInfo(std::static_pointer_cast<C2Info>(info)); - } - } - } - } - ++stream; - } - } - mChannel->onWorkDone( - std::move(work), changed ? config->mOutputFormat : nullptr, - initData.hasChanged() ? initData.update().get() : nullptr, - numDiscardedInputBuffers); - break; - } - case kWhatWatch: { - // watch message already posted; no-op. - break; - } - default: { - ALOGE("unrecognized message"); - break; - } - } - setDeadline(TimePoint::max(), 0ms, "none"); -} - -void CCodec::setDeadline( - const TimePoint &now, - const std::chrono::milliseconds &timeout, - const char *name) { - int32_t mult = std::max(1, property_get_int32("debug.stagefright.ccodec_timeout_mult", 1)); - Mutexed<NamedTimePoint>::Locked deadline(mDeadline); - deadline->set(now + (timeout * mult), name); -} - -void CCodec::initiateReleaseIfStuck() { - std::string name; - bool pendingDeadline = false; - for (Mutexed<NamedTimePoint> *deadlinePtr : { &mDeadline, &mQueueDeadline, &mEosDeadline }) { - Mutexed<NamedTimePoint>::Locked deadline(*deadlinePtr); - if (deadline->get() < std::chrono::steady_clock::now()) { - name = deadline->getName(); - break; - } - if (deadline->get() != TimePoint::max()) { - pendingDeadline = true; - } - } - if (name.empty()) { - // We're not stuck. - if (pendingDeadline) { - // If we are not stuck yet but still has deadline coming up, - // post watch message to check back later. - (new AMessage(kWhatWatch, this))->post(); - } - return; - } - - ALOGW("previous call to %s exceeded timeout", name.c_str()); - initiateRelease(false); - mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); -} - -void CCodec::onWorkQueued(bool eos) { - ALOGV("queued work count +1 from %d", mQueuedWorkCount.load()); - int32_t count = ++mQueuedWorkCount; - if (eos) { - CCodecWatchdog::getInstance()->watch(this); - Mutexed<NamedTimePoint>::Locked deadline(mEosDeadline); - deadline->set(std::chrono::steady_clock::now() + 3s, "eos"); - } - // TODO: query and use input/pipeline/output delay combined - if (count >= 4) { - CCodecWatchdog::getInstance()->watch(this); - Mutexed<NamedTimePoint>::Locked deadline(mQueueDeadline); - deadline->set(std::chrono::steady_clock::now() + 3s, "queue"); - } -} - -void CCodec::subQueuedWorkCount(uint32_t count) { - ALOGV("queued work count -%u from %d", count, mQueuedWorkCount.load()); - int32_t currentCount = (mQueuedWorkCount -= count); - if (currentCount == 0) { - Mutexed<NamedTimePoint>::Locked deadline(mEosDeadline); - deadline->set(TimePoint::max(), "none"); - } - Mutexed<NamedTimePoint>::Locked deadline(mQueueDeadline); - deadline->set(TimePoint::max(), "none"); -} - -} // namespace android - -extern "C" android::CodecBase *CreateCodec() { - return new android::CCodec; -} - -extern "C" android::PersistentSurface *CreateInputSurface() { - // Attempt to create a Codec2's input surface. - std::shared_ptr<android::Codec2Client::InputSurface> inputSurface = - android::Codec2Client::CreateInputSurface(); - if (inputSurface) { - return new android::PersistentSurface( - inputSurface->getGraphicBufferProducer(), - static_cast<android::sp<android::hidl::base::V1_0::IBase>>( - inputSurface->getHalInterface())); - } - - // Fall back to OMX. - using namespace android::hardware::media::omx::V1_0; - using namespace android::hardware::media::omx::V1_0::utils; - using namespace android::hardware::graphics::bufferqueue::V1_0::utils; - typedef android::hardware::media::omx::V1_0::Status OmxStatus; - android::sp<IOmx> omx = IOmx::getService(); - typedef android::hardware::graphics::bufferqueue::V1_0:: - IGraphicBufferProducer HGraphicBufferProducer; - typedef android::hardware::media::omx::V1_0:: - IGraphicBufferSource HGraphicBufferSource; - OmxStatus s; - android::sp<HGraphicBufferProducer> gbp; - android::sp<HGraphicBufferSource> gbs; - android::Return<void> transStatus = omx->createInputSurface( - [&s, &gbp, &gbs]( - OmxStatus status, - const android::sp<HGraphicBufferProducer>& producer, - const android::sp<HGraphicBufferSource>& source) { - s = status; - gbp = producer; - gbs = source; - }); - if (transStatus.isOk() && s == OmxStatus::OK) { - return new android::PersistentSurface( - new H2BGraphicBufferProducer(gbp), - sp<::android::IGraphicBufferSource>( - new LWGraphicBufferSource(gbs))); - } - - return nullptr; -} - diff --git a/media/sfplugin/CCodec.h b/media/sfplugin/CCodec.h deleted file mode 100644 index 78b009e..0000000 --- a/media/sfplugin/CCodec.h +++ /dev/null @@ -1,185 +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 <list> -#include <memory> -#include <set> - -#include <C2Component.h> -#include <codec2/hidl/client.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> - -#include "CCodecConfig.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> ¶ms) override; - virtual void signalEndOfInputStream() override; - virtual void signalRequestIDRFrame() override; - - void initiateReleaseIfStuck(); - void onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems, - size_t numDiscardedInputBuffers); - void onInputBufferDone(const std::shared_ptr<C2Buffer>& buffer); - -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 setParameters(const sp<AMessage> ¶ms); - - void setDeadline( - const TimePoint &now, - const std::chrono::milliseconds &timeout, - const char *name); - - void onWorkQueued(bool eos); - void subQueuedWorkCount(uint32_t count); - - enum { - kWhatAllocate, - kWhatConfigure, - kWhatStart, - kWhatFlush, - kWhatStop, - kWhatRelease, - kWhatCreateInputSurface, - kWhatSetInputSurface, - kWhatSetParameters, - - kWhatWorkDone, - kWhatWatch, - }; - - 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<Codec2Client::Component> comp; - private: - int mState; - }; - - struct NamedTimePoint { - NamedTimePoint() : mTimePoint(TimePoint::max()), mName("") {} - - 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<Codec2Client> mClient; - std::shared_ptr<Codec2Client::Listener> mClientListener; - struct ClientListener; - - Mutexed<NamedTimePoint> mDeadline; - std::atomic_int32_t mQueuedWorkCount; - Mutexed<NamedTimePoint> mQueueDeadline; - Mutexed<NamedTimePoint> mEosDeadline; - typedef CCodecConfig Config; - Mutexed<Config> mConfig; - Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue; - Mutexed<std::list<size_t>> mNumDiscardedInputBuffersQueue; - - friend class CCodecCallbackImpl; - - DISALLOW_EVIL_CONSTRUCTORS(CCodec); -}; - -} // namespace android - -#endif // C_CODEC_H_ diff --git a/media/sfplugin/CCodecBufferChannel.cpp b/media/sfplugin/CCodecBufferChannel.cpp deleted file mode 100644 index d4b08c1..0000000 --- a/media/sfplugin/CCodecBufferChannel.cpp +++ /dev/null @@ -1,2862 +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 <C2AllocatorGralloc.h> -#include <C2PlatformSupport.h> -#include <C2BlockInternal.h> -#include <C2Config.h> -#include <C2Debug.h> - -#include <android/hardware/cas/native/1.0/IDescrambler.h> -#include <android-base/stringprintf.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/ALookup.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/foundation/AUtils.h> -#include <media/stagefright/foundation/hexdump.h> -#include <media/stagefright/MediaCodec.h> -#include <media/stagefright/MediaCodecConstants.h> -#include <media/MediaCodecBuffer.h> -#include <system/window.h> - -#include "CCodecBufferChannel.h" -#include "Codec2Buffer.h" -#include "SkipCutBuffer.h" - -namespace android { - -using android::base::StringPrintf; -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(const char *componentName, const char *name = "Buffers") - : mComponentName(componentName), - mChannelName(std::string(componentName) + ":" + name), - mName(mChannelName.c_str()) { - } - virtual ~Buffers() = default; - - /** - * Set format for MediaCodec-facing buffers. - */ - void setFormat(const sp<AMessage> &format) { - CHECK(format != nullptr); - mFormat = format; - } - - /** - * Return a copy of current format. - */ - sp<AMessage> dupFormat() { - return mFormat != nullptr ? mFormat->dup() : nullptr; - } - - /** - * 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: - std::string mComponentName; ///< name of component for debugging - std::string mChannelName; ///< name of channel for debugging - const char *mName; ///< C-string version of channel name - // 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(const char *componentName, const char *name = "Input[]") - : Buffers(componentName, name) { } - 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 true if the buffer was on file - * and released successfully. - */ - virtual bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer, - bool release) = 0; - - /** - * Release the buffer that is no longer used by the codec process. Return - * true if and only if the buffer was on file and released successfully. - */ - virtual bool expireComponentBuffer( - const std::shared_ptr<C2Buffer> &c2buffer) = 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(size_t size) = 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(const char *componentName, const char *name = "Output") - : Buffers(componentName, name) { } - virtual ~OutputBuffers() = default; - - /** - * Register output C2Buffer from the component and obtain corresponding - * index and MediaCodecBuffer object. Returns false if registration - * fails. - */ - virtual status_t 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 status_t 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 true if the buffer was on file - * and released successfully. - */ - virtual bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) = 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(size_t size) = 0; - - /** - * Initialize SkipCutBuffer object. - */ - void initSkipCutBuffer( - int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) { - CHECK(mSkipCutBuffer == nullptr); - mDelay = delay; - mPadding = padding; - mSampleRate = sampleRate; - setSkipCutBuffer(delay, padding, channelCount); - } - - /** - * Update the SkipCutBuffer object. No-op if it's never initialized. - */ - void updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) { - if (mSkipCutBuffer == nullptr) { - return; - } - int32_t delay = mDelay; - int32_t padding = mPadding; - if (sampleRate != mSampleRate) { - delay = ((int64_t)delay * sampleRate) / mSampleRate; - padding = ((int64_t)padding * sampleRate) / mSampleRate; - } - setSkipCutBuffer(delay, padding, channelCount); - } - - /** - * Submit buffer to SkipCutBuffer object, if initialized. - */ - void submit(const sp<MediaCodecBuffer> &buffer) { - if (mSkipCutBuffer != nullptr) { - mSkipCutBuffer->submit(buffer); - } - } - - /** - * Transfer SkipCutBuffer object to the other Buffers object. - */ - void transferSkipCutBuffer(const sp<SkipCutBuffer> &scb) { - mSkipCutBuffer = scb; - } - -protected: - sp<SkipCutBuffer> mSkipCutBuffer; - -private: - int32_t mDelay; - int32_t mPadding; - int32_t mSampleRate; - - void setSkipCutBuffer(int32_t skip, int32_t cut, int32_t channelCount) { - if (mSkipCutBuffer != nullptr) { - size_t prevSize = mSkipCutBuffer->size(); - if (prevSize != 0u) { - ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize); - } - } - mSkipCutBuffer = new SkipCutBuffer(skip, cut, channelCount); - } - - DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers); -}; - -namespace { - -// TODO: get this info from component -const static size_t kMinInputBufferArraySize = 4; -const static size_t kMaxPipelineCapacity = 18; -const static size_t kChannelOutputDelay = 0; -const static size_t kMinOutputBufferArraySize = kMaxPipelineCapacity + - kChannelOutputDelay; -const static size_t kLinearBufferSize = 1048576; -// This can fit 4K RGBA frame, and most likely client won't need more than this. -const static size_t kMaxLinearBufferSize = 3840 * 2160 * 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(const char *name) - : mImplName(std::string(name) + ".Impl"), - mName(mImplName.c_str()) { } - - /** - * 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 == 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. - * \param c2buffer[in,out] pointer to C2Buffer to be populated. Ignored - * if null. - * \return true if the buffer is successfully released from a slot - * false otherwise - */ - bool releaseSlot( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer, - bool release) { - sp<Codec2Buffer> clientBuffer; - size_t index = mBuffers.size(); - for (size_t i = 0; i < mBuffers.size(); ++i) { - if (mBuffers[i].clientBuffer == buffer) { - clientBuffer = mBuffers[i].clientBuffer; - if (release) { - mBuffers[i].clientBuffer.clear(); - } - index = i; - break; - } - } - if (clientBuffer == nullptr) { - ALOGV("[%s] %s: No matching buffer found", mName, __func__); - return false; - } - std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock(); - if (!result) { - result = clientBuffer->asC2Buffer(); - mBuffers[index].compBuffer = result; - } - if (c2buffer) { - *c2buffer = result; - } - return true; - } - - bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) { - for (size_t i = 0; i < mBuffers.size(); ++i) { - std::shared_ptr<C2Buffer> compBuffer = - mBuffers[i].compBuffer.lock(); - if (!compBuffer || compBuffer != c2buffer) { - continue; - } - mBuffers[i].compBuffer.reset(); - ALOGV("[%s] codec released buffer #%zu", mName, i); - return true; - } - ALOGV("[%s] codec released an unknown buffer", mName); - return false; - } - - void flush() { - ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size()); - mBuffers.clear(); - } - -private: - friend class BuffersArrayImpl; - - std::string mImplName; ///< name for debugging - const char *mName; ///< C-string version of name - - struct Entry { - sp<Codec2Buffer> clientBuffer; - std::weak_ptr<C2Buffer> compBuffer; - }; - std::vector<Entry> mBuffers; -}; - -/** - * Static buffer slots implementation based on a fixed-size array. - */ -class BuffersArrayImpl { -public: - BuffersArrayImpl() - : mImplName("BuffersArrayImpl"), - mName(mImplName.c_str()) { } - - /** - * 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) { - mImplName = impl.mImplName + "[N]"; - mName = mImplName.c_str(); - for (size_t i = 0; i < impl.mBuffers.size(); ++i) { - sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer; - bool ownedByClient = (clientBuffer != nullptr); - if (!ownedByClient) { - clientBuffer = allocate(); - } - mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient }); - } - ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize); - 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, - * WOULD_BLOCK if slots are being used, - * NO_MEMORY if no slot matches the criteria, even though it's - * available - */ - status_t grabBuffer( - size_t *index, - sp<Codec2Buffer> *buffer, - std::function<bool(const sp<Codec2Buffer> &)> match = - [](const sp<Codec2Buffer> &) { return true; }) { - // allBuffersDontMatch remains true if all buffers are available but - // match() returns false for every buffer. - bool allBuffersDontMatch = true; - for (size_t i = 0; i < mBuffers.size(); ++i) { - if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) { - if (match(mBuffers[i].clientBuffer)) { - mBuffers[i].ownedByClient = true; - *buffer = mBuffers[i].clientBuffer; - (*buffer)->meta()->clear(); - (*buffer)->setRange(0, (*buffer)->capacity()); - *index = i; - return OK; - } - } else { - allBuffersDontMatch = false; - } - } - return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK; - } - - /** - * 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. - * \param c2buffer[in,out] pointer to C2Buffer to be populated. Ignored - * if null. - * \return true if the buffer is successfully returned - * false otherwise - */ - bool returnBuffer( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer, - bool release) { - sp<Codec2Buffer> clientBuffer; - size_t index = mBuffers.size(); - for (size_t i = 0; i < mBuffers.size(); ++i) { - if (mBuffers[i].clientBuffer == buffer) { - if (!mBuffers[i].ownedByClient) { - ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu", mName, i); - } - clientBuffer = mBuffers[i].clientBuffer; - if (release) { - mBuffers[i].ownedByClient = false; - } - index = i; - break; - } - } - if (clientBuffer == nullptr) { - ALOGV("[%s] %s: No matching buffer found", mName, __func__); - return false; - } - ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index); - std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock(); - if (!result) { - result = clientBuffer->asC2Buffer(); - mBuffers[index].compBuffer = result; - } - if (c2buffer) { - *c2buffer = result; - } - return true; - } - - bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) { - for (size_t i = 0; i < mBuffers.size(); ++i) { - std::shared_ptr<C2Buffer> compBuffer = - mBuffers[i].compBuffer.lock(); - if (!compBuffer) { - continue; - } - if (c2buffer == compBuffer) { - if (mBuffers[i].ownedByClient) { - // This should not happen. - ALOGD("[%s] codec released a buffer owned by client " - "(index %zu)", mName, i); - } - mBuffers[i].compBuffer.reset(); - ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i); - return true; - } - } - ALOGV("[%s] codec released an unknown buffer (array mode)", mName); - return false; - } - - /** - * 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; - } - } - - void realloc(std::function<sp<Codec2Buffer>()> alloc) { - size_t size = mBuffers.size(); - mBuffers.clear(); - for (size_t i = 0; i < size; ++i) { - mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false }); - } - } - -private: - std::string mImplName; ///< name for debugging - const char *mName; ///< C-string version of name - - struct Entry { - const sp<Codec2Buffer> clientBuffer; - std::weak_ptr<C2Buffer> compBuffer; - bool ownedByClient; - }; - std::vector<Entry> mBuffers; -}; - -class InputBuffersArray : public CCodecBufferChannel::InputBuffers { -public: - InputBuffersArray(const char *componentName, const char *name = "Input[N]") - : InputBuffers(componentName, name) { } - ~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( - size_t) 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; - } - - bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer, - bool release) override { - return mImpl.returnBuffer(buffer, c2buffer, release); - } - - bool expireComponentBuffer( - const std::shared_ptr<C2Buffer> &c2buffer) override { - return mImpl.expireComponentBuffer(c2buffer); - } - - void flush() override { - mImpl.flush(); - } - -private: - BuffersArrayImpl mImpl; -}; - -class LinearInputBuffers : public CCodecBufferChannel::InputBuffers { -public: - LinearInputBuffers(const char *componentName, const char *name = "1D-Input") - : InputBuffers(componentName, name), - mImpl(mName) { } - - bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override { - 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); - if (newBuffer == nullptr) { - return false; - } - *index = mImpl.assignSlot(newBuffer); - *buffer = newBuffer; - return true; - } - - bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer, - bool release) override { - return mImpl.releaseSlot(buffer, c2buffer, release); - } - - bool expireComponentBuffer( - const std::shared_ptr<C2Buffer> &c2buffer) override { - return mImpl.expireComponentBuffer(c2buffer); - } - - 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. - mImpl.flush(); - } - - std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode( - size_t size) final { - 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<InputBuffersArray> array( - new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]")); - array->setPool(mPool); - array->setFormat(mFormat); - array->initialize( - mImpl, - size, - [this, capacity] () -> sp<Codec2Buffer> { return alloc(capacity); }); - return std::move(array); - } - - virtual sp<Codec2Buffer> alloc(size_t size) { - 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, - size_t capacity, - const char *componentName, const char *name = "EncryptedInput") - : LinearInputBuffers(componentName, name), - 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 < kMinInputBufferArraySize; ++i) { - sp<IMemory> memory = mDealer->allocate(capacity); - if (memory == nullptr) { - ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated", mName, i); - break; - } - mMemoryVector.push_back({std::weak_ptr<C2LinearBlock>(), memory}); - } - } - - ~EncryptedLinearInputBuffers() override { - } - - sp<Codec2Buffer> alloc(size_t size) override { - sp<IMemory> memory; - size_t slot = 0; - for (; slot < mMemoryVector.size(); ++slot) { - if (mMemoryVector[slot].block.expired()) { - memory = mMemoryVector[slot].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 || block == nullptr) { - return nullptr; - } - - mMemoryVector[slot].block = block; - 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 GraphicMetadataInputBuffers : public CCodecBufferChannel::InputBuffers { -public: - GraphicMetadataInputBuffers(const char *componentName, const char *name = "2D-MetaInput") - : InputBuffers(componentName, name), - mImpl(mName), - mStore(GetCodec2PlatformAllocatorStore()) { } - ~GraphicMetadataInputBuffers() override = default; - - bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override { - 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); - if (newBuffer == nullptr) { - return false; - } - *index = mImpl.assignSlot(newBuffer); - *buffer = newBuffer; - return true; - } - - bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer, - bool release) override { - return mImpl.releaseSlot(buffer, c2buffer, release); - } - - bool expireComponentBuffer( - const std::shared_ptr<C2Buffer> &c2buffer) override { - return mImpl.expireComponentBuffer(c2buffer); - } - - 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( - size_t size) final { - std::shared_ptr<C2Allocator> alloc; - c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc); - if (err != C2_OK) { - return nullptr; - } - std::unique_ptr<InputBuffersArray> array( - new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]")); - array->setPool(mPool); - array->setFormat(mFormat); - array->initialize( - mImpl, - size, - [format = mFormat, alloc]() -> sp<Codec2Buffer> { - return new GraphicMetadataBuffer(format, alloc); - }); - return std::move(array); - } - -private: - FlexBuffersImpl mImpl; - std::shared_ptr<C2AllocatorStore> mStore; -}; - -class GraphicInputBuffers : public CCodecBufferChannel::InputBuffers { -public: - GraphicInputBuffers(const char *componentName, const char *name = "2D-BB-Input") - : InputBuffers(componentName, name), - mImpl(mName), - mLocalBufferPool(LocalBufferPool::Create( - kMaxLinearBufferSize * kMinInputBufferArraySize)) { } - ~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; - } - - bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer, - bool release) override { - return mImpl.releaseSlot(buffer, c2buffer, release); - } - - bool expireComponentBuffer( - const std::shared_ptr<C2Buffer> &c2buffer) override { - return mImpl.expireComponentBuffer(c2buffer); - } - 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( - size_t size) final { - std::unique_ptr<InputBuffersArray> array( - new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]")); - array->setPool(mPool); - array->setFormat(mFormat); - array->initialize( - mImpl, - size, - [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(const char *componentName, const char *name = "2D-Input") - : InputBuffers(componentName, name) { } - - bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override { - return false; - } - - bool releaseBuffer( - const sp<MediaCodecBuffer> &, std::shared_ptr<C2Buffer> *, bool) override { - return false; - } - - bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &) override { - return false; - } - - void flush() override { - } - - std::unique_ptr<CCodecBufferChannel::InputBuffers> toArrayMode( - size_t) 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(const char *componentName, const char *name = "Output[N]") - : OutputBuffers(componentName, name) { } - ~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( - size_t) final { - return nullptr; - } - - status_t 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 == WOULD_BLOCK) { - ALOGV("[%s] buffers temporarily not available", mName); - return err; - } else if (err != OK) { - ALOGD("[%s] grabBuffer failed: %d", mName, err); - return err; - } - c2Buffer->setFormat(mFormat); - if (!c2Buffer->copy(buffer)) { - ALOGD("[%s] copy buffer failed", mName); - return WOULD_BLOCK; - } - submit(c2Buffer); - *clientBuffer = c2Buffer; - ALOGV("[%s] grabbed buffer %zu", mName, *index); - return OK; - } - - status_t 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 err; - } - memcpy(c2Buffer->base(), csd->m.value, csd->flexCount()); - c2Buffer->setRange(0, csd->flexCount()); - c2Buffer->setFormat(mFormat); - *clientBuffer = c2Buffer; - return OK; - } - - bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override { - return mImpl.returnBuffer(buffer, c2buffer, true); - } - - void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) override { - (void)flushedWork; - mImpl.flush(); - if (mSkipCutBuffer != nullptr) { - mSkipCutBuffer->clear(); - } - } - - void getArray(Vector<sp<MediaCodecBuffer>> *array) const final { - mImpl.getArray(array); - } - - void realloc(const std::shared_ptr<C2Buffer> &c2buffer) { - std::function<sp<Codec2Buffer>()> alloc; - switch (c2buffer->data().type()) { - case C2BufferData::LINEAR: { - uint32_t size = kLinearBufferSize; - const size_t blockSize = c2buffer->data().linearBlocks().front().size(); - if (blockSize < kMaxLinearBufferSize / 2) { - size = blockSize * 2; - } else { - size = kMaxLinearBufferSize; - } - alloc = [format = mFormat, size] { - return new LocalLinearBuffer(format, new ABuffer(size)); - }; - break; - } - - // TODO: add support - case C2BufferData::GRAPHIC: FALLTHROUGH_INTENDED; - - case C2BufferData::INVALID: FALLTHROUGH_INTENDED; - case C2BufferData::LINEAR_CHUNKS: FALLTHROUGH_INTENDED; - case C2BufferData::GRAPHIC_CHUNKS: FALLTHROUGH_INTENDED; - default: - ALOGD("Unsupported type: %d", (int)c2buffer->data().type()); - return; - } - mImpl.realloc(alloc); - } - -private: - BuffersArrayImpl mImpl; -}; - -class FlexOutputBuffers : public CCodecBufferChannel::OutputBuffers { -public: - FlexOutputBuffers(const char *componentName, const char *name = "Output[]") - : OutputBuffers(componentName, name), - mImpl(mName) { } - - status_t 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; - ALOGV("[%s] registered buffer %zu", mName, *index); - return OK; - } - - status_t registerCsd( - const C2StreamCsdInfo::output *csd, - size_t *index, - sp<MediaCodecBuffer> *clientBuffer) final { - sp<Codec2Buffer> newBuffer = new LocalLinearBuffer( - mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount())); - *index = mImpl.assignSlot(newBuffer); - *clientBuffer = newBuffer; - return OK; - } - - bool releaseBuffer( - const sp<MediaCodecBuffer> &buffer, - std::shared_ptr<C2Buffer> *c2buffer) override { - return mImpl.releaseSlot(buffer, c2buffer, true); - } - - 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( - size_t size) override { - std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str())); - array->setFormat(mFormat); - array->transferSkipCutBuffer(mSkipCutBuffer); - array->initialize( - mImpl, - size, - [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: - LinearOutputBuffers(const char *componentName, const char *name = "1D-Output") - : FlexOutputBuffers(componentName, name) { } - - void flush( - const std::list<std::unique_ptr<C2Work>> &flushedWork) override { - if (mSkipCutBuffer != nullptr) { - mSkipCutBuffer->clear(); - } - FlexOutputBuffers::flush(flushedWork); - } - - sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override { - if (buffer == nullptr) { - ALOGV("[%s] using a dummy buffer", mName); - return new LocalLinearBuffer(mFormat, new ABuffer(0)); - } - if (buffer->data().type() != C2BufferData::LINEAR) { - ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type()); - // We expect linear output buffers from the component. - return nullptr; - } - if (buffer->data().linearBlocks().size() != 1u) { - ALOGV("[%s] no linear buffers", mName); - // We expect one and only one linear block from the component. - return nullptr; - } - sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer); - submit(clientBuffer); - return clientBuffer; - } - - sp<Codec2Buffer> allocateArrayBuffer() override { - // TODO: proper max output size - return new LocalLinearBuffer(mFormat, new ABuffer(kLinearBufferSize)); - } -}; - -class GraphicOutputBuffers : public FlexOutputBuffers { -public: - GraphicOutputBuffers(const char *componentName, const char *name = "2D-Output") - : FlexOutputBuffers(componentName, name) { } - - 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(const char *componentName, const char *name = "2D-BB-Output") - : FlexOutputBuffers(componentName, name), - mLocalBufferPool(LocalBufferPool::Create( - kMaxLinearBufferSize * kMinOutputBufferArraySize)) { } - ~RawGraphicOutputBuffers() override = default; - - sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override { - if (buffer == nullptr) { - sp<Codec2Buffer> c2buffer = ConstGraphicBlockBuffer::AllocateEmpty( - mFormat, - [lbp = mLocalBufferPool](size_t capacity) { - return lbp->newBuffer(capacity); - }); - c2buffer->setRange(0, 0); - return c2buffer; - } else { - 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) { - Mutex::Autolock l(mSync.mGuardLock); - // At this point it's guaranteed that mSync is not under state transition, - // as we are holding its mutex. - - Mutexed<CCodecBufferChannel::QueueSync::Counter>::Locked count(mSync.mCount); - if (count->value == -1) { - mRunning = false; - } else { - ++count->value; - mRunning = true; - } -} - -CCodecBufferChannel::QueueGuard::~QueueGuard() { - if (mRunning) { - // We are not holding mGuardLock at this point so that QueueSync::stop() can - // keep holding the lock until mCount reaches zero. - Mutexed<CCodecBufferChannel::QueueSync::Counter>::Locked count(mSync.mCount); - --count->value; - count->cond.broadcast(); - } -} - -void CCodecBufferChannel::QueueSync::start() { - Mutex::Autolock l(mGuardLock); - // If stopped, it goes to running state; otherwise no-op. - Mutexed<Counter>::Locked count(mCount); - if (count->value == -1) { - count->value = 0; - } -} - -void CCodecBufferChannel::QueueSync::stop() { - Mutex::Autolock l(mGuardLock); - Mutexed<Counter>::Locked count(mCount); - if (count->value == -1) { - // no-op - return; - } - // Holding mGuardLock 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. - while (count->value != 0) { - count.waitForCondition(count->cond); - } - count->value = -1; -} - -// CCodecBufferChannel::PipelineCapacity - -CCodecBufferChannel::PipelineCapacity::PipelineCapacity() - : input(0), component(0), - mName("<UNKNOWN COMPONENT>") { -} - -void CCodecBufferChannel::PipelineCapacity::initialize( - int newInput, - int newComponent, - const char* newName, - const char* callerTag) { - input.store(newInput, std::memory_order_relaxed); - component.store(newComponent, std::memory_order_relaxed); - mName = newName; - ALOGV("[%s] %s -- PipelineCapacity::initialize(): " - "pipeline availability initialized ==> " - "input = %d, component = %d", - mName, callerTag ? callerTag : "*", - newInput, newComponent); -} - -bool CCodecBufferChannel::PipelineCapacity::allocate(const char* callerTag) { - int prevInput = input.fetch_sub(1, std::memory_order_relaxed); - int prevComponent = component.fetch_sub(1, std::memory_order_relaxed); - if (prevInput > 0 && prevComponent > 0) { - ALOGV("[%s] %s -- PipelineCapacity::allocate() returns true: " - "pipeline availability -1 all ==> " - "input = %d, component = %d", - mName, callerTag ? callerTag : "*", - prevInput - 1, - prevComponent - 1); - return true; - } - input.fetch_add(1, std::memory_order_relaxed); - component.fetch_add(1, std::memory_order_relaxed); - ALOGV("[%s] %s -- PipelineCapacity::allocate() returns false: " - "pipeline availability unchanged ==> " - "input = %d, component = %d", - mName, callerTag ? callerTag : "*", - prevInput, - prevComponent); - return false; -} - -void CCodecBufferChannel::PipelineCapacity::free(const char* callerTag) { - int prevInput = input.fetch_add(1, std::memory_order_relaxed); - int prevComponent = component.fetch_add(1, std::memory_order_relaxed); - ALOGV("[%s] %s -- PipelineCapacity::free(): " - "pipeline availability +1 all ==> " - "input = %d, component = %d", - mName, callerTag ? callerTag : "*", - prevInput + 1, - prevComponent + 1); -} - -int CCodecBufferChannel::PipelineCapacity::freeInputSlots( - size_t numDiscardedInputBuffers, - const char* callerTag) { - int prevInput = input.fetch_add(numDiscardedInputBuffers, - std::memory_order_relaxed); - ALOGV("[%s] %s -- PipelineCapacity::freeInputSlots(%zu): " - "pipeline availability +%zu input ==> " - "input = %d, component = %d", - mName, callerTag ? callerTag : "*", - numDiscardedInputBuffers, - numDiscardedInputBuffers, - prevInput + static_cast<int>(numDiscardedInputBuffers), - component.load(std::memory_order_relaxed)); - return prevInput + static_cast<int>(numDiscardedInputBuffers); -} - -int CCodecBufferChannel::PipelineCapacity::freeComponentSlot( - const char* callerTag) { - int prevComponent = component.fetch_add(1, std::memory_order_relaxed); - ALOGV("[%s] %s -- PipelineCapacity::freeComponentSlot(): " - "pipeline availability +1 component ==> " - "input = %d, component = %d", - mName, callerTag ? callerTag : "*", - input.load(std::memory_order_relaxed), - prevComponent + 1); - return prevComponent + 1; -} - -// CCodecBufferChannel::ReorderStash - -CCodecBufferChannel::ReorderStash::ReorderStash() { - clear(); -} - -void CCodecBufferChannel::ReorderStash::clear() { - mPending.clear(); - mStash.clear(); - mDepth = 0; - mKey = C2Config::ORDINAL; -} - -void CCodecBufferChannel::ReorderStash::setDepth(uint32_t depth) { - mPending.splice(mPending.end(), mStash); - mDepth = depth; -} -void CCodecBufferChannel::ReorderStash::setKey(C2Config::ordinal_key_t key) { - mPending.splice(mPending.end(), mStash); - mKey = key; -} - -bool CCodecBufferChannel::ReorderStash::pop(Entry *entry) { - if (mPending.empty()) { - return false; - } - entry->buffer = mPending.front().buffer; - entry->timestamp = mPending.front().timestamp; - entry->flags = mPending.front().flags; - entry->ordinal = mPending.front().ordinal; - mPending.pop_front(); - return true; -} - -void CCodecBufferChannel::ReorderStash::emplace( - const std::shared_ptr<C2Buffer> &buffer, - int64_t timestamp, - int32_t flags, - const C2WorkOrdinalStruct &ordinal) { - for (auto it = mStash.begin(); it != mStash.end(); ++it) { - if (less(ordinal, it->ordinal)) { - mStash.emplace(it, buffer, timestamp, flags, ordinal); - return; - } - } - mStash.emplace_back(buffer, timestamp, flags, ordinal); - while (!mStash.empty() && mStash.size() > mDepth) { - mPending.push_back(mStash.front()); - mStash.pop_front(); - } -} - -void CCodecBufferChannel::ReorderStash::defer( - const CCodecBufferChannel::ReorderStash::Entry &entry) { - mPending.push_front(entry); -} - -bool CCodecBufferChannel::ReorderStash::hasPending() const { - return !mPending.empty(); -} - -bool CCodecBufferChannel::ReorderStash::less( - const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) { - switch (mKey) { - case C2Config::ORDINAL: return o1.frameIndex < o2.frameIndex; - case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp; - case C2Config::CUSTOM: return o1.customOrdinal < o2.customOrdinal; - default: - ALOGD("Unrecognized key; default to timestamp"); - return o1.frameIndex < o2.frameIndex; - } -} - -// CCodecBufferChannel - -CCodecBufferChannel::CCodecBufferChannel( - const std::shared_ptr<CCodecCallback> &callback) - : mHeapSeqNum(-1), - mCCodecCallback(callback), - mFrameIndex(0u), - mFirstValidFrameIndex(0u), - mMetaMode(MODE_NONE), - mAvailablePipelineCapacity(), - mInputMetEos(false) { - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - buffers->reset(new DummyInputBuffers("")); -} - -CCodecBufferChannel::~CCodecBufferChannel() { - if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) { - mCrypto->unsetHeap(mHeapSeqNum); - } -} - -void CCodecBufferChannel::setComponent( - const std::shared_ptr<Codec2Client::Component> &component) { - mComponent = component; - mComponentName = component->getName() + StringPrintf("#%d", int(uintptr_t(component.get()) % 997)); - mName = mComponentName.c_str(); -} - -status_t CCodecBufferChannel::setInputSurface( - const std::shared_ptr<InputSurfaceWrapper> &surface) { - ALOGV("[%s] setInputSurface", mName); - mInputSurface = surface; - return mInputSurface->connect(mComponent); -} - -status_t CCodecBufferChannel::signalEndOfInputStream() { - if (mInputSurface == nullptr) { - return INVALID_OPERATION; - } - return mInputSurface->signalEndOfInputStream(); -} - -status_t CCodecBufferChannel::queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer) { - int64_t timeUs; - CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); - - if (mInputMetEos) { - ALOGD("[%s] buffers after EOS ignored (%lld us)", mName, (long long)timeUs); - return OK; - } - - int32_t flags = 0; - int32_t tmp = 0; - bool eos = false; - if (buffer->meta()->findInt32("eos", &tmp) && tmp) { - eos = true; - mInputMetEos = true; - ALOGV("[%s] input EOS", mName); - } - if (buffer->meta()->findInt32("csd", &tmp) && tmp) { - flags |= C2FrameData::FLAG_CODEC_CONFIG; - } - ALOGV("[%s] queueInputBuffer: buffer->size() = %zu", mName, buffer->size()); - std::unique_ptr<C2Work> work(new C2Work); - work->input.ordinal.timestamp = timeUs; - work->input.ordinal.frameIndex = mFrameIndex++; - // WORKAROUND: until codecs support handling work after EOS and max output sizing, use timestamp - // manipulation to achieve image encoding via video codec, and to constrain encoded output. - // Keep client timestamp in customOrdinal - work->input.ordinal.customOrdinal = timeUs; - work->input.buffers.clear(); - - if (buffer->size() > 0u) { - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - std::shared_ptr<C2Buffer> c2buffer; - if (!(*buffers)->releaseBuffer(buffer, &c2buffer, false)) { - return -ENOENT; - } - work->input.buffers.push_back(c2buffer); - } else { - mAvailablePipelineCapacity.freeInputSlots(1, "queueInputBufferInternal"); - if (eos) { - flags |= C2FrameData::FLAG_END_OF_STREAM; - } - } - work->input.flags = (C2FrameData::flags_t)flags; - // TODO: fill info's - - work->input.configUpdate = std::move(mParamsToBeSet); - 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 = mComponent->queue(&items); - - if (err == C2_OK && eos && buffer->size() > 0u) { - mCCodecCallback->onWorkQueued(false); - work.reset(new C2Work); - work->input.ordinal.timestamp = timeUs; - work->input.ordinal.frameIndex = mFrameIndex++; - // WORKAROUND: keep client timestamp in customOrdinal - work->input.ordinal.customOrdinal = timeUs; - work->input.buffers.clear(); - work->input.flags = C2FrameData::FLAG_END_OF_STREAM; - - items.clear(); - items.push_back(std::move(work)); - err = mComponent->queue(&items); - } - if (err == C2_OK) { - mCCodecCallback->onWorkQueued(eos); - - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - bool released = (*buffers)->releaseBuffer(buffer, nullptr, true); - ALOGV("[%s] queueInputBuffer: buffer %sreleased", mName, released ? "" : "not "); - } - - feedInputBufferIfAvailableInternal(); - return err; -} - -status_t CCodecBufferChannel::setParameters(std::vector<std::unique_ptr<C2Param>> ¶ms) { - QueueGuard guard(mSync); - if (!guard.isRunning()) { - ALOGD("[%s] setParameters is only supported in the running state.", mName); - return -ENOSYS; - } - mParamsToBeSet.insert(mParamsToBeSet.end(), - std::make_move_iterator(params.begin()), - std::make_move_iterator(params.end())); - params.clear(); - return OK; -} - -status_t CCodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) { - QueueGuard guard(mSync); - if (!guard.isRunning()) { - ALOGD("[%s] No more buffers should be queued at current state.", mName); - 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()) { - ALOGD("[%s] No more buffers should be queued at current state.", mName); - return -ENOSYS; - } - - if (!hasCryptoOrDescrambler()) { - return -ENOSYS; - } - sp<EncryptedLinearBlockBuffer> encryptedBuffer((EncryptedLinearBlockBuffer *)buffer.get()); - - ssize_t result = -1; - ssize_t codecDataOffset = 0; - 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; - ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED; - - if (key != nullptr) { - sctrl = (ScramblingControl)key[0]; - // Adjust for the PES offset - codecDataOffset = key[2] | (key[3] << 8); - } - - auto returnVoid = mDescrambler->descramble( - sctrl, - 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) { - ALOGI("[%s] descramble failed, trans=%s, status=%d, result=%zd", - mName, returnVoid.description().c_str(), status, result); - return UNKNOWN_ERROR; - } - - if (result < codecDataOffset) { - ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result); - return BAD_VALUE; - } - - ALOGV("[%s] descramble succeeded, %zd bytes", mName, result); - - if (dstBuffer.type == BufferType::SHARED_MEMORY) { - encryptedBuffer->copyDecryptedContentFromMemory(result); - } - } - - buffer->setRange(codecDataOffset, result - codecDataOffset); - return queueInputBufferInternal(buffer); -} - -void CCodecBufferChannel::feedInputBufferIfAvailable() { - QueueGuard guard(mSync); - if (!guard.isRunning()) { - ALOGV("[%s] We're not running --- no input buffer reported", mName); - return; - } - feedInputBufferIfAvailableInternal(); -} - -void CCodecBufferChannel::feedInputBufferIfAvailableInternal() { - while (!mInputMetEos && - !mReorderStash.lock()->hasPending() && - mAvailablePipelineCapacity.allocate("feedInputBufferIfAvailable")) { - sp<MediaCodecBuffer> inBuffer; - size_t index; - { - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - if (!(*buffers)->requestNewBuffer(&index, &inBuffer)) { - ALOGV("[%s] no new buffer available", mName); - mAvailablePipelineCapacity.free("feedInputBufferIfAvailable"); - break; - } - } - ALOGV("[%s] new input index = %zu [%p]", mName, index, inBuffer.get()); - mCallback->onInputBufferAvailable(index, inBuffer); - } -} - -status_t CCodecBufferChannel::renderOutputBuffer( - const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) { - ALOGV("[%s] renderOutputBuffer: %p", mName, buffer.get()); - std::shared_ptr<C2Buffer> c2Buffer; - bool released = false; - { - Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers); - if (*buffers) { - released = (*buffers)->releaseBuffer(buffer, &c2Buffer); - } - } - // NOTE: some apps try to releaseOutputBuffer() with timestamp and/or render - // set to true. - sendOutputBuffers(); - // input buffer feeding may have been gated by pending output buffers - feedInputBufferIfAvailable(); - if (!c2Buffer) { - if (released) { - ALOGD("[%s] The app is calling releaseOutputBuffer() with " - "timestamp or render=true with non-video buffers. Apps should " - "call releaseOutputBuffer() with render=false for those.", - mName); - } - return INVALID_OPERATION; - } - -#if 0 - const std::vector<std::shared_ptr<const C2Info>> infoParams = c2Buffer->info(); - ALOGV("[%s] queuing gfx buffer with %zu infos", mName, infoParams.size()); - for (const std::shared_ptr<const C2Info> &info : infoParams) { - AString res; - for (size_t ix = 0; ix + 3 < info->size(); ix += 4) { - if (ix) res.append(", "); - res.append(*((int32_t*)info.get() + (ix / 4))); - } - ALOGV(" [%s]", res.c_str()); - } -#endif - std::shared_ptr<const C2StreamRotationInfo::output> rotation = - std::static_pointer_cast<const C2StreamRotationInfo::output>( - c2Buffer->getInfo(C2StreamRotationInfo::output::PARAM_TYPE)); - bool flip = rotation && (rotation->flip & 1); - uint32_t quarters = ((rotation ? rotation->value : 0) / 90) & 3; - uint32_t transform = 0; - switch (quarters) { - case 0: // no rotation - transform = flip ? HAL_TRANSFORM_FLIP_H : 0; - break; - case 1: // 90 degrees counter-clockwise - transform = flip ? (HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90) - : HAL_TRANSFORM_ROT_270; - break; - case 2: // 180 degrees - transform = flip ? HAL_TRANSFORM_FLIP_V : HAL_TRANSFORM_ROT_180; - break; - case 3: // 90 degrees clockwise - transform = flip ? (HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90) - : HAL_TRANSFORM_ROT_90; - break; - } - - std::shared_ptr<const C2StreamSurfaceScalingInfo::output> surfaceScaling = - std::static_pointer_cast<const C2StreamSurfaceScalingInfo::output>( - c2Buffer->getInfo(C2StreamSurfaceScalingInfo::output::PARAM_TYPE)); - uint32_t videoScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - if (surfaceScaling) { - videoScalingMode = surfaceScaling->value; - } - - // Use dataspace from format as it has the default aspects already applied - android_dataspace_t dataSpace = HAL_DATASPACE_UNKNOWN; // this is 0 - (void)buffer->format()->findInt32("android._dataspace", (int32_t *)&dataSpace); - - // HDR static info - std::shared_ptr<const C2StreamHdrStaticInfo::output> hdrStaticInfo = - std::static_pointer_cast<const C2StreamHdrStaticInfo::output>( - c2Buffer->getInfo(C2StreamHdrStaticInfo::output::PARAM_TYPE)); - - // HDR10 plus info - std::shared_ptr<const C2StreamHdr10PlusInfo::output> hdr10PlusInfo = - std::static_pointer_cast<const C2StreamHdr10PlusInfo::output>( - c2Buffer->getInfo(C2StreamHdr10PlusInfo::output::PARAM_TYPE)); - - { - Mutexed<OutputSurface>::Locked output(mOutputSurface); - if (output->surface == nullptr) { - ALOGI("[%s] cannot render buffer without surface", mName); - return OK; - } - } - - std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks(); - if (blocks.size() != 1u) { - ALOGD("[%s] expected 1 graphic block, but got %zu", mName, blocks.size()); - return UNKNOWN_ERROR; - } - const C2ConstGraphicBlock &block = blocks.front(); - - // TODO: revisit this after C2Fence implementation. - android::IGraphicBufferProducer::QueueBufferInput qbi( - timestampNs, - false, // droppable - dataSpace, - Rect(blocks.front().crop().left, - blocks.front().crop().top, - blocks.front().crop().right(), - blocks.front().crop().bottom()), - videoScalingMode, - transform, - Fence::NO_FENCE, 0); - if (hdrStaticInfo || hdr10PlusInfo) { - HdrMetadata hdr; - if (hdrStaticInfo) { - struct android_smpte2086_metadata smpte2086_meta = { - .displayPrimaryRed = { - hdrStaticInfo->mastering.red.x, hdrStaticInfo->mastering.red.y - }, - .displayPrimaryGreen = { - hdrStaticInfo->mastering.green.x, hdrStaticInfo->mastering.green.y - }, - .displayPrimaryBlue = { - hdrStaticInfo->mastering.blue.x, hdrStaticInfo->mastering.blue.y - }, - .whitePoint = { - hdrStaticInfo->mastering.white.x, hdrStaticInfo->mastering.white.y - }, - .maxLuminance = hdrStaticInfo->mastering.maxLuminance, - .minLuminance = hdrStaticInfo->mastering.minLuminance, - }; - - struct android_cta861_3_metadata cta861_meta = { - .maxContentLightLevel = hdrStaticInfo->maxCll, - .maxFrameAverageLightLevel = hdrStaticInfo->maxFall, - }; - - hdr.validTypes = HdrMetadata::SMPTE2086 | HdrMetadata::CTA861_3; - hdr.smpte2086 = smpte2086_meta; - hdr.cta8613 = cta861_meta; - } - if (hdr10PlusInfo) { - hdr.validTypes |= HdrMetadata::HDR10PLUS; - hdr.hdr10plus.assign( - hdr10PlusInfo->m.value, - hdr10PlusInfo->m.value + hdr10PlusInfo->flexCount()); - } - qbi.setHdrMetadata(hdr); - } - // we don't have dirty regions - qbi.setSurfaceDamage(Region::INVALID_REGION); - android::IGraphicBufferProducer::QueueBufferOutput qbo; - status_t result = mComponent->queueToOutputSurface(block, qbi, &qbo); - if (result != OK) { - ALOGI("[%s] queueBuffer failed: %d", mName, result); - return result; - } - ALOGV("[%s] queue buffer successful", mName); - - int64_t mediaTimeUs = 0; - (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs); - mCCodecCallback->onOutputFramesRendered(mediaTimeUs, timestampNs); - - return OK; -} - -status_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) { - 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)) { - buffers.unlock(); - released = true; - mAvailablePipelineCapacity.freeInputSlots(1, "discardBuffer"); - } - } - { - Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers); - if (*buffers && (*buffers)->releaseBuffer(buffer, nullptr)) { - buffers.unlock(); - released = true; - } - } - if (released) { - sendOutputBuffers(); - feedInputBufferIfAvailable(); - } else { - ALOGD("[%s] MediaCodec discarded an unknown buffer", mName); - } - 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(kMinInputBufferArraySize); - } - - (*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(kMinOutputBufferArraySize); - } - - (*buffers)->getArray(array); -} - -status_t CCodecBufferChannel::start( - const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) { - C2StreamBufferTypeSetting::input iStreamFormat(0u); - C2StreamBufferTypeSetting::output oStreamFormat(0u); - C2PortReorderBufferDepthTuning::output reorderDepth; - C2PortReorderKeySetting::output reorderKey; - c2_status_t err = mComponent->query( - { - &iStreamFormat, - &oStreamFormat, - &reorderDepth, - &reorderKey, - }, - {}, - C2_DONT_BLOCK, - nullptr); - if (err == C2_BAD_INDEX) { - if (!iStreamFormat || !oStreamFormat) { - return UNKNOWN_ERROR; - } - } else if (err != C2_OK) { - return UNKNOWN_ERROR; - } - - { - Mutexed<ReorderStash>::Locked reorder(mReorderStash); - reorder->clear(); - if (reorderDepth) { - reorder->setDepth(reorderDepth.value); - } - if (reorderKey) { - reorder->setKey(reorderKey.value); - } - } - // TODO: get this from input format - bool secure = mComponent->getName().find(".secure") != std::string::npos; - - std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore(); - int poolMask = property_get_int32( - "debug.stagefright.c2-poolmask", - 1 << C2PlatformAllocatorStore::ION | - 1 << C2PlatformAllocatorStore::BUFFERQUEUE); - - if (inputFormat != nullptr) { - bool graphic = (iStreamFormat.value == C2FormatVideo); - std::shared_ptr<C2BlockPool> pool; - { - Mutexed<BlockPools>::Locked pools(mBlockPools); - - // set default allocator ID. - pools->inputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC - : C2PlatformAllocatorStore::ION; - - // query C2PortAllocatorsTuning::input from component. If an allocator ID is obtained - // from component, create the input block pool with given ID. Otherwise, use default IDs. - std::vector<std::unique_ptr<C2Param>> params; - err = mComponent->query({ }, - { C2PortAllocatorsTuning::input::PARAM_TYPE }, - C2_DONT_BLOCK, - ¶ms); - if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) { - ALOGD("[%s] Query input allocators returned %zu params => %s (%u)", - mName, params.size(), asString(err), err); - } else if (err == C2_OK && params.size() == 1) { - C2PortAllocatorsTuning::input *inputAllocators = - C2PortAllocatorsTuning::input::From(params[0].get()); - if (inputAllocators && inputAllocators->flexCount() > 0) { - std::shared_ptr<C2Allocator> allocator; - // verify allocator IDs and resolve default allocator - allocatorStore->fetchAllocator(inputAllocators->m.values[0], &allocator); - if (allocator) { - pools->inputAllocatorId = allocator->getId(); - } else { - ALOGD("[%s] component requested invalid input allocator ID %u", - mName, inputAllocators->m.values[0]); - } - } - } - - // TODO: use C2Component wrapper to associate this pool with ourselves - if ((poolMask >> pools->inputAllocatorId) & 1) { - err = CreateCodec2BlockPool(pools->inputAllocatorId, nullptr, &pool); - ALOGD("[%s] Created input block pool with allocatorID %u => poolID %llu - %s (%d)", - mName, pools->inputAllocatorId, - (unsigned long long)(pool ? pool->getLocalId() : 111000111), - asString(err), err); - } else { - err = C2_NOT_FOUND; - } - if (err != C2_OK) { - C2BlockPool::local_id_t inputPoolId = - graphic ? C2BlockPool::BASIC_GRAPHIC : C2BlockPool::BASIC_LINEAR; - err = GetCodec2BlockPool(inputPoolId, nullptr, &pool); - ALOGD("[%s] Using basic input block pool with poolID %llu => got %llu - %s (%d)", - mName, (unsigned long long)inputPoolId, - (unsigned long long)(pool ? pool->getLocalId() : 111000111), - asString(err), err); - if (err != C2_OK) { - return NO_MEMORY; - } - } - pools->inputPool = pool; - } - - bool forceArrayMode = false; - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - if (graphic) { - if (mInputSurface) { - buffers->reset(new DummyInputBuffers(mName)); - } else if (mMetaMode == MODE_ANW) { - buffers->reset(new GraphicMetadataInputBuffers(mName)); - } else { - buffers->reset(new GraphicInputBuffers(mName)); - } - } else { - if (hasCryptoOrDescrambler()) { - int32_t capacity = kLinearBufferSize; - (void)inputFormat->findInt32(KEY_MAX_INPUT_SIZE, &capacity); - if ((size_t)capacity > kMaxLinearBufferSize) { - ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize); - capacity = kMaxLinearBufferSize; - } - if (mDealer == nullptr) { - mDealer = new MemoryDealer( - align(capacity, MemoryDealer::getAllocationAlignment()) - * (kMinInputBufferArraySize + 1), - "EncryptedLinearInputBuffers"); - mDecryptDestination = mDealer->allocate((size_t)capacity); - } - if (mCrypto != nullptr && mHeapSeqNum < 0) { - mHeapSeqNum = mCrypto->setHeap(mDealer->getMemoryHeap()); - } else { - mHeapSeqNum = -1; - } - buffers->reset(new EncryptedLinearInputBuffers( - secure, mDealer, mCrypto, mHeapSeqNum, (size_t)capacity, mName)); - forceArrayMode = true; - } else { - buffers->reset(new LinearInputBuffers(mName)); - } - } - (*buffers)->setFormat(inputFormat); - - if (err == C2_OK) { - (*buffers)->setPool(pool); - } else { - // TODO: error - } - - if (forceArrayMode) { - *buffers = (*buffers)->toArrayMode(kMinInputBufferArraySize); - } - } - - if (outputFormat != nullptr) { - sp<IGraphicBufferProducer> outputSurface; - uint32_t outputGeneration; - { - Mutexed<OutputSurface>::Locked output(mOutputSurface); - outputSurface = output->surface ? - output->surface->getIGraphicBufferProducer() : nullptr; - outputGeneration = output->generation; - } - - bool graphic = (oStreamFormat.value == C2FormatVideo); - C2BlockPool::local_id_t outputPoolId_; - - { - Mutexed<BlockPools>::Locked pools(mBlockPools); - - // set default allocator ID. - pools->outputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC - : C2PlatformAllocatorStore::ION; - - // query C2PortAllocatorsTuning::output from component, or use default allocator if - // unsuccessful. - std::vector<std::unique_ptr<C2Param>> params; - err = mComponent->query({ }, - { C2PortAllocatorsTuning::output::PARAM_TYPE }, - C2_DONT_BLOCK, - ¶ms); - if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) { - ALOGD("[%s] Query output allocators returned %zu params => %s (%u)", - mName, params.size(), asString(err), err); - } else if (err == C2_OK && params.size() == 1) { - C2PortAllocatorsTuning::output *outputAllocators = - C2PortAllocatorsTuning::output::From(params[0].get()); - if (outputAllocators && outputAllocators->flexCount() > 0) { - std::shared_ptr<C2Allocator> allocator; - // verify allocator IDs and resolve default allocator - allocatorStore->fetchAllocator(outputAllocators->m.values[0], &allocator); - if (allocator) { - pools->outputAllocatorId = allocator->getId(); - } else { - ALOGD("[%s] component requested invalid output allocator ID %u", - mName, outputAllocators->m.values[0]); - } - } - } - - // use bufferqueue if outputting to a surface. - // query C2PortSurfaceAllocatorTuning::output from component, or use default allocator - // if unsuccessful. - if (outputSurface) { - params.clear(); - err = mComponent->query({ }, - { C2PortSurfaceAllocatorTuning::output::PARAM_TYPE }, - C2_DONT_BLOCK, - ¶ms); - if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) { - ALOGD("[%s] Query output surface allocator returned %zu params => %s (%u)", - mName, params.size(), asString(err), err); - } else if (err == C2_OK && params.size() == 1) { - C2PortSurfaceAllocatorTuning::output *surfaceAllocator = - C2PortSurfaceAllocatorTuning::output::From(params[0].get()); - if (surfaceAllocator) { - std::shared_ptr<C2Allocator> allocator; - // verify allocator IDs and resolve default allocator - allocatorStore->fetchAllocator(surfaceAllocator->value, &allocator); - if (allocator) { - pools->outputAllocatorId = allocator->getId(); - } else { - ALOGD("[%s] component requested invalid surface output allocator ID %u", - mName, surfaceAllocator->value); - err = C2_BAD_VALUE; - } - } - } - if (pools->outputAllocatorId == C2PlatformAllocatorStore::GRALLOC - && err != C2_OK - && ((poolMask >> C2PlatformAllocatorStore::BUFFERQUEUE) & 1)) { - pools->outputAllocatorId = C2PlatformAllocatorStore::BUFFERQUEUE; - } - } - - if ((poolMask >> pools->outputAllocatorId) & 1) { - err = mComponent->createBlockPool( - pools->outputAllocatorId, &pools->outputPoolId, &pools->outputPoolIntf); - ALOGI("[%s] Created output block pool with allocatorID %u => poolID %llu - %s", - mName, pools->outputAllocatorId, - (unsigned long long)pools->outputPoolId, - asString(err)); - } else { - err = C2_NOT_FOUND; - } - if (err != C2_OK) { - // use basic pool instead - pools->outputPoolId = - graphic ? C2BlockPool::BASIC_GRAPHIC : C2BlockPool::BASIC_LINEAR; - } - - // Configure output block pool ID as parameter C2PortBlockPoolsTuning::output to - // component. - std::unique_ptr<C2PortBlockPoolsTuning::output> poolIdsTuning = - C2PortBlockPoolsTuning::output::AllocUnique({ pools->outputPoolId }); - - std::vector<std::unique_ptr<C2SettingResult>> failures; - err = mComponent->config({ poolIdsTuning.get() }, C2_MAY_BLOCK, &failures); - ALOGD("[%s] Configured output block pool ids %llu => %s", - mName, (unsigned long long)poolIdsTuning->m.values[0], asString(err)); - outputPoolId_ = pools->outputPoolId; - } - - Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers); - - if (graphic) { - if (outputSurface) { - buffers->reset(new GraphicOutputBuffers(mName)); - } else { - buffers->reset(new RawGraphicOutputBuffers(mName)); - } - } else { - buffers->reset(new LinearOutputBuffers(mName)); - } - (*buffers)->setFormat(outputFormat->dup()); - - - // Try to set output surface to created block pool if given. - if (outputSurface) { - mComponent->setOutputSurface( - outputPoolId_, - outputSurface, - outputGeneration); - } - - if (oStreamFormat.value == C2BufferData::LINEAR - && mComponentName.find("c2.qti.") == std::string::npos) { - // 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(kMinOutputBufferArraySize); - - int32_t channelCount; - int32_t sampleRate; - if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount) - && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) { - int32_t delay = 0; - int32_t padding = 0;; - if (!outputFormat->findInt32("encoder-delay", &delay)) { - delay = 0; - } - if (!outputFormat->findInt32("encoder-padding", &padding)) { - padding = 0; - } - if (delay || padding) { - // We need write access to the buffers, and we're already in - // array mode. - (*buffers)->initSkipCutBuffer(delay, padding, sampleRate, channelCount); - } - } - } - } - - // Set up pipeline control. This has to be done after mInputBuffers and - // mOutputBuffers are initialized to make sure that lingering callbacks - // about buffers from the previous generation do not interfere with the - // newly initialized pipeline capacity. - - // Query delays - C2PortRequestedDelayTuning::input inputDelay; - C2PortRequestedDelayTuning::output outputDelay; - C2RequestedPipelineDelayTuning pipelineDelay; -#if 0 - err = mComponent->query( - { &inputDelay, &pipelineDelay, &outputDelay }, - {}, - C2_DONT_BLOCK, - nullptr); - mAvailablePipelineCapacity.initialize( - inputDelay, - inputDelay + pipelineDelay, - inputDelay + pipelineDelay + outputDelay, - mName); -#else - mAvailablePipelineCapacity.initialize( - kMinInputBufferArraySize, - kMaxPipelineCapacity, - mName); -#endif - - mInputMetEos = false; - mSync.start(); - return OK; -} - -status_t CCodecBufferChannel::requestInitialInputBuffers() { - if (mInputSurface) { - return OK; - } - - C2StreamFormatConfig::output oStreamFormat(0u); - c2_status_t err = mComponent->query({ &oStreamFormat }, {}, C2_DONT_BLOCK, nullptr); - if (err != C2_OK) { - return UNKNOWN_ERROR; - } - std::vector<sp<MediaCodecBuffer>> toBeQueued; - // TODO: use proper buffer depth instead of this random value - for (size_t i = 0; i < kMinInputBufferArraySize; ++i) { - size_t index; - sp<MediaCodecBuffer> buffer; - { - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - if (!(*buffers)->requestNewBuffer(&index, &buffer)) { - if (i == 0) { - ALOGW("[%s] start: cannot allocate memory at all", mName); - return NO_MEMORY; - } else { - ALOGV("[%s] start: cannot allocate memory, only %zu buffers allocated", - mName, i); - } - break; - } - } - if (buffer) { - Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs); - ALOGV("[%s] input buffer %zu available", mName, index); - bool post = true; - if (!configs->empty()) { - sp<ABuffer> config = configs->front(); - if (buffer->capacity() >= config->size()) { - memcpy(buffer->base(), config->data(), config->size()); - buffer->setRange(0, config->size()); - buffer->meta()->clear(); - buffer->meta()->setInt64("timeUs", 0); - buffer->meta()->setInt32("csd", 1); - post = false; - } else { - ALOGD("[%s] buffer capacity too small for the config (%zu < %zu)", - mName, buffer->capacity(), config->size()); - } - } else if (oStreamFormat.value == C2BufferData::LINEAR && i == 0 - && mComponentName.find("c2.qti.") == std::string::npos) { - // WORKAROUND: Some apps expect CSD available without queueing - // any input. Queue an empty buffer to get the CSD. - buffer->setRange(0, 0); - buffer->meta()->clear(); - buffer->meta()->setInt64("timeUs", 0); - post = false; - } - if (mAvailablePipelineCapacity.allocate("requestInitialInputBuffers")) { - if (post) { - mCallback->onInputBufferAvailable(index, buffer); - } else { - toBeQueued.emplace_back(buffer); - } - } else { - ALOGD("[%s] pipeline is full while requesting %zu-th input buffer", - mName, i); - } - } - } - for (const sp<MediaCodecBuffer> &buffer : toBeQueued) { - if (queueInputBufferInternal(buffer) != OK) { - mAvailablePipelineCapacity.freeComponentSlot("requestInitialInputBuffers"); - } - } - return OK; -} - -void CCodecBufferChannel::stop() { - mSync.stop(); - mFirstValidFrameIndex = mFrameIndex.load(std::memory_order_relaxed); - if (mInputSurface != nullptr) { - mInputSurface.reset(); - } -} - -void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) { - ALOGV("[%s] flush", mName); - { - Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs); - for (const std::unique_ptr<C2Work> &work : flushedWork) { - if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) { - continue; - } - if (work->input.buffers.empty() - || work->input.buffers.front()->data().linearBlocks().empty()) { - ALOGD("[%s] no linear codec config data found", mName); - continue; - } - C2ReadView view = - work->input.buffers.front()->data().linearBlocks().front().map().get(); - if (view.error() != C2_OK) { - ALOGD("[%s] failed to map flushed codec config data: %d", mName, view.error()); - continue; - } - configs->push_back(ABuffer::CreateAsCopy(view.data(), view.capacity())); - ALOGV("[%s] stashed flushed codec config data (size=%u)", mName, view.capacity()); - } - } - { - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - (*buffers)->flush(); - } - { - Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers); - (*buffers)->flush(flushedWork); - } -} - -void CCodecBufferChannel::onWorkDone( - std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat, - const C2StreamInitDataInfo::output *initData, - size_t numDiscardedInputBuffers) { - if (handleWork(std::move(work), outputFormat, initData)) { - mAvailablePipelineCapacity.freeInputSlots(numDiscardedInputBuffers, - "onWorkDone"); - feedInputBufferIfAvailable(); - } -} - -void CCodecBufferChannel::onInputBufferDone( - const std::shared_ptr<C2Buffer>& buffer) { - bool newInputSlotAvailable; - { - Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers); - newInputSlotAvailable = (*buffers)->expireComponentBuffer(buffer); - if (newInputSlotAvailable) { - mAvailablePipelineCapacity.freeInputSlots(1, "onInputBufferDone"); - } - } - if (newInputSlotAvailable) { - feedInputBufferIfAvailable(); - } -} - -bool CCodecBufferChannel::handleWork( - std::unique_ptr<C2Work> work, - const sp<AMessage> &outputFormat, - const C2StreamInitDataInfo::output *initData) { - if ((work->input.ordinal.frameIndex - mFirstValidFrameIndex.load()).peek() < 0) { - // Discard frames from previous generation. - ALOGD("[%s] Discard frames from previous generation.", mName); - return false; - } - - if (work->worklets.size() != 1u - || !work->worklets.front() - || !(work->worklets.front()->output.flags & C2FrameData::FLAG_INCOMPLETE)) { - mAvailablePipelineCapacity.freeComponentSlot("handleWork"); - } - - if (work->result == C2_NOT_FOUND) { - ALOGD("[%s] flushed work; ignored.", mName); - return true; - } - - if (work->result != C2_OK) { - ALOGD("[%s] work failed to complete: %d", mName, work->result); - mCCodecCallback->onError(work->result, ACTION_CODE_FATAL); - return false; - } - - // NOTE: MediaCodec usage supposedly have only one worklet - if (work->worklets.size() != 1u) { - ALOGI("[%s] onWorkDone: incorrect number of worklets: %zu", - mName, work->worklets.size()); - mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); - return false; - } - - const std::unique_ptr<C2Worklet> &worklet = work->worklets.front(); - - std::shared_ptr<C2Buffer> buffer; - // NOTE: MediaCodec usage supposedly have only one output stream. - if (worklet->output.buffers.size() > 1u) { - ALOGI("[%s] onWorkDone: incorrect number of output buffers: %zu", - mName, worklet->output.buffers.size()); - mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); - return false; - } else if (worklet->output.buffers.size() == 1u) { - buffer = worklet->output.buffers[0]; - if (!buffer) { - ALOGD("[%s] onWorkDone: nullptr found in buffers; ignored.", mName); - } - } - - while (!worklet->output.configUpdate.empty()) { - std::unique_ptr<C2Param> param; - worklet->output.configUpdate.back().swap(param); - worklet->output.configUpdate.pop_back(); - switch (param->coreIndex().coreIndex()) { - case C2PortReorderBufferDepthTuning::CORE_INDEX: { - C2PortReorderBufferDepthTuning::output reorderDepth; - if (reorderDepth.updateFrom(*param)) { - mReorderStash.lock()->setDepth(reorderDepth.value); - ALOGV("[%s] onWorkDone: updated reorder depth to %u", - mName, reorderDepth.value); - } else { - ALOGD("[%s] onWorkDone: failed to read reorder depth", mName); - } - break; - } - case C2PortReorderKeySetting::CORE_INDEX: { - C2PortReorderKeySetting::output reorderKey; - if (reorderKey.updateFrom(*param)) { - mReorderStash.lock()->setKey(reorderKey.value); - ALOGV("[%s] onWorkDone: updated reorder key to %u", - mName, reorderKey.value); - } else { - ALOGD("[%s] onWorkDone: failed to read reorder key", mName); - } - break; - } - default: - ALOGV("[%s] onWorkDone: unrecognized config update (%08X)", - mName, param->index()); - break; - } - } - - if (outputFormat != nullptr) { - Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers); - ALOGD("[%s] onWorkDone: output format changed to %s", - mName, outputFormat->debugString().c_str()); - (*buffers)->setFormat(outputFormat); - - AString mediaType; - if (outputFormat->findString(KEY_MIME, &mediaType) - && mediaType == MIMETYPE_AUDIO_RAW) { - int32_t channelCount; - int32_t sampleRate; - if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount) - && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) { - (*buffers)->updateSkipCutBuffer(sampleRate, channelCount); - } - } - } - - int32_t flags = 0; - if (worklet->output.flags & C2FrameData::FLAG_END_OF_STREAM) { - flags |= MediaCodec::BUFFER_FLAG_EOS; - ALOGV("[%s] onWorkDone: output EOS", mName); - } - - sp<MediaCodecBuffer> outBuffer; - size_t index; - - // WORKAROUND: adjust output timestamp based on client input timestamp and codec - // input timestamp. Codec output timestamp (in the timestamp field) shall correspond to - // the codec input timestamp, but client output timestamp should (reported in timeUs) - // shall correspond to the client input timesamp (in customOrdinal). By using the - // delta between the two, this allows for some timestamp deviation - e.g. if one input - // produces multiple output. - c2_cntr64_t timestamp = - worklet->output.ordinal.timestamp + work->input.ordinal.customOrdinal - - work->input.ordinal.timestamp; - ALOGV("[%s] onWorkDone: input %lld, codec %lld => output %lld => %lld", - mName, - work->input.ordinal.customOrdinal.peekll(), - work->input.ordinal.timestamp.peekll(), - worklet->output.ordinal.timestamp.peekll(), - timestamp.peekll()); - - if (initData != nullptr) { - Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers); - if ((*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(); - mCallback->onOutputBufferAvailable(index, outBuffer); - buffers.lock(); - } else { - ALOGD("[%s] onWorkDone: unable to register csd", mName); - buffers.unlock(); - mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); - buffers.lock(); - return false; - } - } - - if (!buffer && !flags) { - ALOGV("[%s] onWorkDone: Not reporting output buffer (%lld)", - mName, work->input.ordinal.frameIndex.peekull()); - return true; - } - - 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<ReorderStash>::Locked reorder(mReorderStash); - reorder->emplace(buffer, timestamp.peek(), flags, worklet->output.ordinal); - if (flags & MediaCodec::BUFFER_FLAG_EOS) { - // Flush reorder stash - reorder->setDepth(0); - } - } - sendOutputBuffers(); - return true; -} - -void CCodecBufferChannel::sendOutputBuffers() { - ReorderStash::Entry entry; - sp<MediaCodecBuffer> outBuffer; - size_t index; - - while (true) { - { - Mutexed<ReorderStash>::Locked reorder(mReorderStash); - if (!reorder->hasPending()) { - break; - } - if (!reorder->pop(&entry)) { - break; - } - } - Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers); - status_t err = (*buffers)->registerBuffer(entry.buffer, &index, &outBuffer); - if (err != OK) { - if (err != WOULD_BLOCK) { - OutputBuffersArray *array = (OutputBuffersArray *)buffers->get(); - array->realloc(entry.buffer); - mCCodecCallback->onOutputBuffersChanged(); - } - buffers.unlock(); - ALOGV("[%s] sendOutputBuffers: unable to register output buffer", mName); - mReorderStash.lock()->defer(entry); - return; - } - buffers.unlock(); - - outBuffer->meta()->setInt64("timeUs", entry.timestamp); - outBuffer->meta()->setInt32("flags", entry.flags); - ALOGV("[%s] sendOutputBuffers: out buffer index = %zu [%p] => %p + %zu", - mName, index, outBuffer.get(), outBuffer->data(), outBuffer->size()); - mCallback->onOutputBufferAvailable(index, outBuffer); - } -} - -status_t CCodecBufferChannel::setSurface(const sp<Surface> &newSurface) { - static std::atomic_uint32_t surfaceGeneration{0}; - uint32_t generation = (getpid() << 10) | - ((surfaceGeneration.fetch_add(1, std::memory_order_relaxed) + 1) - & ((1 << 10) - 1)); - - sp<IGraphicBufferProducer> producer; - if (newSurface) { - newSurface->setScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - newSurface->setMaxDequeuedBufferCount(kMinOutputBufferArraySize); - producer = newSurface->getIGraphicBufferProducer(); - producer->setGenerationNumber(generation); - } else { - ALOGE("[%s] setting output surface to null", mName); - return INVALID_OPERATION; - } - - std::shared_ptr<Codec2Client::Configurable> outputPoolIntf; - C2BlockPool::local_id_t outputPoolId; - { - Mutexed<BlockPools>::Locked pools(mBlockPools); - outputPoolId = pools->outputPoolId; - outputPoolIntf = pools->outputPoolIntf; - } - - if (outputPoolIntf) { - if (mComponent->setOutputSurface( - outputPoolId, - producer, - generation) != C2_OK) { - ALOGI("[%s] setSurface: component setOutputSurface failed", mName); - return INVALID_OPERATION; - } - } - - { - Mutexed<OutputSurface>::Locked output(mOutputSurface); - output->surface = newSurface; - output->generation = generation; - } - - return OK; -} - -void CCodecBufferChannel::setMetaMode(MetaMode mode) { - mMetaMode = mode; -} - -status_t toStatusT(c2_status_t c2s, c2_operation_t c2op) { - // C2_OK is always translated to OK. - if (c2s == C2_OK) { - return OK; - } - - // Operation-dependent translation - // TODO: Add as necessary - switch (c2op) { - case C2_OPERATION_Component_start: - switch (c2s) { - case C2_NO_MEMORY: - return NO_MEMORY; - default: - return UNKNOWN_ERROR; - } - default: - break; - } - - // Backup operation-agnostic translation - switch (c2s) { - case C2_BAD_INDEX: - return BAD_INDEX; - case C2_BAD_VALUE: - return BAD_VALUE; - case C2_BLOCKING: - return WOULD_BLOCK; - case C2_DUPLICATE: - return ALREADY_EXISTS; - case C2_NO_INIT: - return NO_INIT; - case C2_NO_MEMORY: - return NO_MEMORY; - case C2_NOT_FOUND: - return NAME_NOT_FOUND; - case C2_TIMED_OUT: - return TIMED_OUT; - case C2_BAD_STATE: - case C2_CANCELED: - case C2_CANNOT_DO: - case C2_CORRUPTED: - case C2_OMITTED: - case C2_REFUSED: - return UNKNOWN_ERROR; - default: - return -static_cast<status_t>(c2s); - } -} - -} // namespace android diff --git a/media/sfplugin/CCodecBufferChannel.h b/media/sfplugin/CCodecBufferChannel.h deleted file mode 100644 index 1b3b605..0000000 --- a/media/sfplugin/CCodecBufferChannel.h +++ /dev/null @@ -1,416 +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 <vector> - -#include <C2Buffer.h> -#include <C2Component.h> -#include <Codec2Mapper.h> - -#include <codec2/hidl/client.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 "InputSurfaceWrapper.h" - -namespace android { - -class CCodecCallback { -public: - virtual ~CCodecCallback() = default; - virtual void onError(status_t err, enum ActionCode actionCode) = 0; - virtual void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) = 0; - virtual void onWorkQueued(bool eos) = 0; - virtual void onOutputBuffersChanged() = 0; -}; - -/** - * BufferChannelBase implementation for CCodec. - */ -class CCodecBufferChannel - : public BufferChannelBase, public std::enable_shared_from_this<CCodecBufferChannel> { -public: - explicit CCodecBufferChannel(const std::shared_ptr<CCodecCallback> &callback); - 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<Codec2Client::Component> &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); - - /** - * Signal EOS to input surface. - */ - status_t signalEndOfInputStream(); - - /** - * Set parameters. - */ - status_t setParameters(std::vector<std::unique_ptr<C2Param>> ¶ms); - - /** - * Start queueing buffers to the component. This object should never queue - * buffers before this call has completed. - */ - status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat); - - /** - * Request initial input buffers to be filled by client. - */ - status_t requestInitialInputBuffers(); - - /** - * 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. - * @param outputFormat new output format if it has changed, otherwise nullptr - * @param initData new init data (CSD) if it has changed, otherwise nullptr - * @param numDiscardedInputBuffers the number of input buffers that are - * returned for the first time (not previously returned by - * onInputBufferDone()). - */ - void onWorkDone( - std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat, - const C2StreamInitDataInfo::output *initData, - size_t numDiscardedInputBuffers); - - /** - * Make an input buffer available for the client as it is no longer needed - * by the codec. - * - * @param buffer The buffer that becomes unused. - */ - void onInputBufferDone(const std::shared_ptr<C2Buffer>& buffer); - - enum MetaMode { - MODE_NONE, - MODE_ANW, - }; - - void setMetaMode(MetaMode mode); - - // 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() {} - ~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: - Mutex mGuardLock; - - struct Counter { - inline Counter() : value(-1) {} - int32_t value; - Condition cond; - }; - Mutexed<Counter> mCount; - - friend class CCodecBufferChannel::QueueGuard; - }; - - class QueueGuard { - public: - QueueGuard(QueueSync &sync); - ~QueueGuard(); - inline bool isRunning() { return mRunning; } - - private: - QueueSync &mSync; - bool mRunning; - }; - - void feedInputBufferIfAvailable(); - void feedInputBufferIfAvailableInternal(); - status_t queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer); - bool handleWork( - std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat, - const C2StreamInitDataInfo::output *initData); - void sendOutputBuffers(); - - QueueSync mSync; - sp<MemoryDealer> mDealer; - sp<IMemory> mDecryptDestination; - int32_t mHeapSeqNum; - - std::shared_ptr<Codec2Client::Component> mComponent; - std::string mComponentName; ///< component name for debugging - const char *mName; ///< C-string version of component name - std::shared_ptr<CCodecCallback> mCCodecCallback; - std::shared_ptr<C2BlockPool> mInputAllocator; - QueueSync mQueueSync; - std::vector<std::unique_ptr<C2Param>> mParamsToBeSet; - - Mutexed<std::unique_ptr<InputBuffers>> mInputBuffers; - Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs; - 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; - uint32_t generation; - }; - Mutexed<OutputSurface> mOutputSurface; - - struct BlockPools { - C2Allocator::id_t inputAllocatorId; - std::shared_ptr<C2BlockPool> inputPool; - C2Allocator::id_t outputAllocatorId; - C2BlockPool::local_id_t outputPoolId; - std::shared_ptr<Codec2Client::Configurable> outputPoolIntf; - }; - Mutexed<BlockPools> mBlockPools; - - std::shared_ptr<InputSurfaceWrapper> mInputSurface; - - MetaMode mMetaMode; - - // PipelineCapacity is used in the input buffer gating logic. - // - // There are three criteria that need to be met before - // onInputBufferAvailable() is called: - // 1. The number of input buffers that have been received by - // CCodecBufferChannel but not returned via onWorkDone() or - // onInputBufferDone() does not exceed a certain limit. (Let us call this - // number the "input" capacity.) - // 2. The number of work items that have been received by - // CCodecBufferChannel whose outputs have not been returned from the - // component (by calling onWorkDone()) does not exceed a certain limit. - // (Let us call this the "component" capacity.) - // - // These three criteria guarantee that a new input buffer that arrives from - // the invocation of onInputBufferAvailable() will not - // 1. overload CCodecBufferChannel's input buffers; - // 2. overload the component; or - // - struct PipelineCapacity { - // The number of available input capacity. - std::atomic_int input; - // The number of available component capacity. - std::atomic_int component; - - PipelineCapacity(); - // Set the values of #input and #component. - void initialize(int newInput, int newComponent, - const char* newName = "<UNKNOWN COMPONENT>", - const char* callerTag = nullptr); - - // Return true and decrease #input and #component by one if - // they are all greater than zero; return false otherwise. - // - // callerTag is used for logging only. - // - // allocate() is called by CCodecBufferChannel to check whether it can - // receive another input buffer. If the return value is true, - // onInputBufferAvailable() and onOutputBufferAvailable() can be called - // afterwards. - bool allocate(const char* callerTag = nullptr); - - // Increase #input and #component by one. - // - // callerTag is used for logging only. - // - // free() is called by CCodecBufferChannel after allocate() returns true - // but onInputBufferAvailable() cannot be called for any reasons. It - // essentially undoes an allocate() call. - void free(const char* callerTag = nullptr); - - // Increase #input by @p numDiscardedInputBuffers. - // - // callerTag is used for logging only. - // - // freeInputSlots() is called by CCodecBufferChannel when onWorkDone() - // or onInputBufferDone() is called. @p numDiscardedInputBuffers is - // provided in onWorkDone(), and is 1 in onInputBufferDone(). - int freeInputSlots(size_t numDiscardedInputBuffers, - const char* callerTag = nullptr); - - // Increase #component by one and return the updated value. - // - // callerTag is used for logging only. - // - // freeComponentSlot() is called by CCodecBufferChannel when - // onWorkDone() is called. - int freeComponentSlot(const char* callerTag = nullptr); - - private: - // Component name. Used for logging. - const char* mName; - }; - PipelineCapacity mAvailablePipelineCapacity; - - class ReorderStash { - public: - struct Entry { - inline Entry() : buffer(nullptr), timestamp(0), flags(0), ordinal({0, 0, 0}) {} - inline Entry( - const std::shared_ptr<C2Buffer> &b, - int64_t t, - int32_t f, - const C2WorkOrdinalStruct &o) - : buffer(b), timestamp(t), flags(f), ordinal(o) {} - std::shared_ptr<C2Buffer> buffer; - int64_t timestamp; - int32_t flags; - C2WorkOrdinalStruct ordinal; - }; - - ReorderStash(); - - void clear(); - void setDepth(uint32_t depth); - void setKey(C2Config::ordinal_key_t key); - bool pop(Entry *entry); - void emplace( - const std::shared_ptr<C2Buffer> &buffer, - int64_t timestamp, - int32_t flags, - const C2WorkOrdinalStruct &ordinal); - void defer(const Entry &entry); - bool hasPending() const; - - private: - std::list<Entry> mPending; - std::list<Entry> mStash; - uint32_t mDepth; - C2Config::ordinal_key_t mKey; - - bool less(const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2); - }; - Mutexed<ReorderStash> mReorderStash; - - std::atomic_bool mInputMetEos; - - inline bool hasCryptoOrDescrambler() { - return mCrypto != nullptr || mDescrambler != nullptr; - } -}; - -// Conversion of a c2_status_t value to a status_t value may depend on the -// operation that returns the c2_status_t value. -enum c2_operation_t { - C2_OPERATION_NONE, - C2_OPERATION_Component_connectToOmxInputSurface, - C2_OPERATION_Component_createBlockPool, - C2_OPERATION_Component_destroyBlockPool, - C2_OPERATION_Component_disconnectFromInputSurface, - C2_OPERATION_Component_drain, - C2_OPERATION_Component_flush, - C2_OPERATION_Component_queue, - C2_OPERATION_Component_release, - C2_OPERATION_Component_reset, - C2_OPERATION_Component_setOutputSurface, - C2_OPERATION_Component_start, - C2_OPERATION_Component_stop, - C2_OPERATION_ComponentStore_copyBuffer, - C2_OPERATION_ComponentStore_createComponent, - C2_OPERATION_ComponentStore_createInputSurface, - C2_OPERATION_ComponentStore_createInterface, - C2_OPERATION_Configurable_config, - C2_OPERATION_Configurable_query, - C2_OPERATION_Configurable_querySupportedParams, - C2_OPERATION_Configurable_querySupportedValues, - C2_OPERATION_InputSurface_connectToComponent, - C2_OPERATION_InputSurfaceConnection_disconnect, -}; - -status_t toStatusT(c2_status_t c2s, c2_operation_t c2op = C2_OPERATION_NONE); - -} // namespace android - -#endif // CCODEC_BUFFER_CHANNEL_H_ diff --git a/media/sfplugin/CCodecConfig.cpp b/media/sfplugin/CCodecConfig.cpp deleted file mode 100644 index ef02e74..0000000 --- a/media/sfplugin/CCodecConfig.cpp +++ /dev/null @@ -1,1610 +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 "CCodecConfig" -#include <cutils/properties.h> -#include <log/log.h> - -#include <C2Component.h> -#include <C2Debug.h> -#include <C2Param.h> -#include <util/C2InterfaceHelper.h> - -#include <media/stagefright/MediaCodecConstants.h> - -#include "CCodecConfig.h" -#include "Codec2Mapper.h" - -#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_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */ -#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) */ -// 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" -#define PROP_DRC_OVERRIDE_EFFECT "ro.aac_drc_effect_type" - -namespace android { - -// CCodecConfig - -namespace { - -/** - * mapping between SDK and Codec 2.0 configurations. - */ -struct ConfigMapper { - /** - * Value mapper (C2Value => C2Value) - */ - typedef std::function<C2Value(C2Value)> Mapper; - - /// shorthand - typedef CCodecConfig::Domain Domain; - - ConfigMapper(std::string mediaKey, C2String c2struct, C2String c2field) - : mDomain(Domain::ALL), mMediaKey(mediaKey), mStruct(c2struct), mField(c2field) { } - - /// Limits this parameter to the given domain - ConfigMapper &limitTo(uint32_t domain) { - C2_CHECK(domain & Domain::GUARD_BIT); - mDomain = Domain(mDomain & domain); - return *this; - } - - /// Adds SDK => Codec 2.0 mapper (should not be in the SDK format) - ConfigMapper &withMapper(Mapper mapper) { - C2_CHECK(!mMapper); - C2_CHECK(!mReverse); - mMapper = mapper; - return *this; - } - - /// Adds SDK <=> Codec 2.0 value mappers - ConfigMapper &withMappers(Mapper mapper, Mapper reverse) { - C2_CHECK(!mMapper); - C2_CHECK(!mReverse); - mMapper = mapper; - mReverse = reverse; - return *this; - } - - /// Adds SDK <=> Codec 2.0 value mappers based on C2Mapper - template<typename C2Type, typename SdkType=int32_t> - ConfigMapper &withC2Mappers() { - C2_CHECK(!mMapper); - C2_CHECK(!mReverse); - mMapper = [](C2Value v) -> C2Value { - SdkType sdkValue; - C2Type c2Value; - if (v.get(&sdkValue) && C2Mapper::map(sdkValue, &c2Value)) { - return c2Value; - } - return C2Value(); - }; - mReverse = [](C2Value v) -> C2Value { - SdkType sdkValue; - C2Type c2Value; - using C2ValueType=typename _c2_reduce_enum_to_underlying_type<C2Type>::type; - if (v.get((C2ValueType*)&c2Value) && C2Mapper::map(c2Value, &sdkValue)) { - return sdkValue; - } - return C2Value(); - }; - return *this; - } - - /// Maps from SDK values in an AMessage to a suitable C2Value. - C2Value mapFromMessage(const AMessage::ItemData &item) const { - C2Value value; - int32_t int32Value; - int64_t int64Value; - float floatValue; - double doubleValue; - if (item.find(&int32Value)) { - value = int32Value; - } else if (item.find(&int64Value)) { - value = int64Value; - } else if (item.find(&floatValue)) { - value = floatValue; - } else if (item.find(&doubleValue)) { - value = (float)doubleValue; - } - if (value.type() != C2Value::NO_INIT && mMapper) { - value = mMapper(value); - } - return value; - } - - /// Maps from a C2Value to an SDK value in an AMessage. - AMessage::ItemData mapToMessage(C2Value value) const { - AMessage::ItemData item; - int32_t int32Value; - uint32_t uint32Value; - int64_t int64Value; - uint64_t uint64Value; - float floatValue; - if (value.type() != C2Value::NO_INIT && mReverse) { - value = mReverse(value); - } - if (value.get(&int32Value)) { - item.set(int32Value); - } else if (value.get(&uint32Value) && uint32Value <= uint32_t(INT32_MAX)) { - // SDK does not support unsigned values - item.set((int32_t)uint32Value); - } else if (value.get(&int64Value)) { - item.set(int64Value); - } else if (value.get(&uint64Value) && uint64Value <= uint64_t(INT64_MAX)) { - // SDK does not support unsigned values - item.set((int64_t)uint64Value); - } else if (value.get(&floatValue)) { - item.set(floatValue); - } - return item; - } - - Domain domain() const { return mDomain; } - std::string mediaKey() const { return mMediaKey; } - std::string path() const { return mField.size() ? mStruct + '.' + mField : mStruct; } - Mapper mapper() const { return mMapper; } - Mapper reverse() const { return mReverse; } - -private: - Domain mDomain; ///< parameter domain (mask) containing port, kind and config domains - std::string mMediaKey; ///< SDK key - C2String mStruct; ///< Codec 2.0 struct name - C2String mField; ///< Codec 2.0 field name - Mapper mMapper; ///< optional SDK => Codec 2.0 value mapper - Mapper mReverse; ///< optional Codec 2.0 => SDK value mapper -}; - -template <typename PORT, typename STREAM> -AString QueryMediaTypeImpl( - const std::shared_ptr<Codec2Client::Component> &component) { - AString mediaType; - std::vector<std::unique_ptr<C2Param>> queried; - c2_status_t c2err = component->query( - {}, { PORT::PARAM_TYPE, STREAM::PARAM_TYPE }, C2_DONT_BLOCK, &queried); - if (c2err != C2_OK && queried.size() == 0) { - ALOGD("Query media type failed => %s", asString(c2err)); - } else { - PORT *portMediaType = - PORT::From(queried[0].get()); - if (portMediaType) { - mediaType = AString( - portMediaType->m.value, - strnlen(portMediaType->m.value, portMediaType->flexCount())); - } else { - STREAM *streamMediaType = STREAM::From(queried[0].get()); - if (streamMediaType) { - mediaType = AString( - streamMediaType->m.value, - strnlen(streamMediaType->m.value, streamMediaType->flexCount())); - } - } - ALOGD("read media type: %s", mediaType.c_str()); - } - return mediaType; -} - -AString QueryMediaType( - bool input, const std::shared_ptr<Codec2Client::Component> &component) { - typedef C2PortMediaTypeSetting P; - typedef C2StreamMediaTypeSetting S; - if (input) { - return QueryMediaTypeImpl<P::input, S::input>(component); - } else { - return QueryMediaTypeImpl<P::output, S::output>(component); - } -} - -} // namespace - -/** - * Set of standard parameters used by CCodec that are exposed to MediaCodec. - */ -struct StandardParams { - typedef CCodecConfig::Domain Domain; - - // standard (MediaCodec) params are keyed by media format key - typedef std::string SdkKey; - - /// used to return reference to no config mappers in getConfigMappersForSdkKey - static const std::vector<ConfigMapper> NO_MAPPERS; - - /// Returns Codec 2.0 equivalent parameters for an SDK format key. - const std::vector<ConfigMapper> &getConfigMappersForSdkKey(std::string key) const { - auto it = mConfigMappers.find(key); - if (it == mConfigMappers.end()) { - ALOGD("no c2 equivalents for %s", key.c_str()); - return NO_MAPPERS; - } - ALOGV("found %zu eqs for %s", it->second.size(), key.c_str()); - return it->second; - } - - /** - * Adds a SDK <=> Codec 2.0 parameter mapping. Multiple Codec 2.0 parameters may map to a - * single SDK key, in which case they shall be ordered from least authoritative to most - * authoritative. When constructing SDK formats, the last mapped Codec 2.0 parameter that - * is supported by the component will determine the exposed value. (TODO: perhaps restrict this - * by domain.) - */ - void add(const ConfigMapper &cm) { - auto it = mConfigMappers.find(cm.mediaKey()); - ALOGV("%c%c%c%c %c%c%c %04x %9s %s => %s", - ((cm.domain() & Domain::IS_INPUT) ? 'I' : ' '), - ((cm.domain() & Domain::IS_OUTPUT) ? 'O' : ' '), - ((cm.domain() & Domain::IS_CODED) ? 'C' : ' '), - ((cm.domain() & Domain::IS_RAW) ? 'R' : ' '), - ((cm.domain() & Domain::IS_CONFIG) ? 'c' : ' '), - ((cm.domain() & Domain::IS_PARAM) ? 'p' : ' '), - ((cm.domain() & Domain::IS_READ) ? 'r' : ' '), - cm.domain(), - it == mConfigMappers.end() ? "adding" : "extending", - cm.mediaKey().c_str(), cm.path().c_str()); - if (it == mConfigMappers.end()) { - std::vector<ConfigMapper> eqs = { cm }; - mConfigMappers.emplace(cm.mediaKey(), eqs); - } else { - it->second.push_back(cm); - } - } - - /** - * Returns all paths for a specific domain. - * - * \param any maximum domain mask. Returned parameters must match at least one of the domains - * in the mask. - * \param all minimum domain mask. Returned parameters must match all of the domains in the - * mask. This is restricted to the bits of the maximum mask. - */ - std::vector<std::string> getPathsForDomain( - Domain any, Domain all = Domain::ALL) const { - std::vector<std::string> res; - for (const std::pair<std::string, std::vector<ConfigMapper>> &el : mConfigMappers) { - for (const ConfigMapper &cm : el.second) { - ALOGV("filtering %s %x %x %x %x", cm.path().c_str(), cm.domain(), any, - (cm.domain() & any), (cm.domain() & any & all)); - if ((cm.domain() & any) && ((cm.domain() & any & all) == (any & all))) { - res.push_back(cm.path()); - } - } - } - return res; - } - - /** - * Returns SDK <=> Codec 2.0 mappings. - * - * TODO: replace these with better methods as this exposes the inner structure. - */ - const std::map<SdkKey, std::vector<ConfigMapper>> getKeys() const { - return mConfigMappers; - } - -private: - std::map<SdkKey, std::vector<ConfigMapper>> mConfigMappers; -}; - -const std::vector<ConfigMapper> StandardParams::NO_MAPPERS; - - -CCodecConfig::CCodecConfig() - : mInputFormat(new AMessage), - mOutputFormat(new AMessage), - mUsingSurface(false) { } - -void CCodecConfig::initializeStandardParams() { - typedef Domain D; - mStandardParams = std::make_shared<StandardParams>(); - std::function<void(const ConfigMapper &)> add = - [params = mStandardParams](const ConfigMapper &cm) { - params->add(cm); - }; - std::function<void(const ConfigMapper &)> deprecated = add; - - // allow int32 or float SDK values and represent them as float - ConfigMapper::Mapper makeFloat = [](C2Value v) -> C2Value { - // convert from i32 to float - int32_t i32Value; - float fpValue; - if (v.get(&i32Value)) { - return (float)i32Value; - } else if (v.get(&fpValue)) { - return fpValue; - } - return C2Value(); - }; - - ConfigMapper::Mapper negate = [](C2Value v) -> C2Value { - int32_t value; - if (v.get(&value)) { - return -value; - } - return C2Value(); - }; - - add(ConfigMapper(KEY_MIME, C2_PARAMKEY_INPUT_MEDIA_TYPE, "value") - .limitTo(D::INPUT & D::READ)); - add(ConfigMapper(KEY_MIME, C2_PARAMKEY_OUTPUT_MEDIA_TYPE, "value") - .limitTo(D::OUTPUT & D::READ)); - - add(ConfigMapper(KEY_BIT_RATE, C2_PARAMKEY_BITRATE, "value") - .limitTo(D::ENCODER & D::OUTPUT)); - // we also need to put the bitrate in the max bitrate field - add(ConfigMapper(KEY_MAX_BIT_RATE, C2_PARAMKEY_BITRATE, "value") - .limitTo(D::ENCODER & D::READ & D::OUTPUT)); - add(ConfigMapper(PARAMETER_KEY_VIDEO_BITRATE, C2_PARAMKEY_BITRATE, "value") - .limitTo(D::ENCODER & D::VIDEO & D::PARAM)); - add(ConfigMapper(KEY_BITRATE_MODE, C2_PARAMKEY_BITRATE_MODE, "value") - .limitTo(D::ENCODER & D::CODED) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - C2Config::bitrate_mode_t mode; - if (v.get(&value) && C2Mapper::map(value, &mode)) { - return mode; - } - return C2Value(); - })); - // remove when codecs switch to PARAMKEY and new modes - deprecated(ConfigMapper(KEY_BITRATE_MODE, "coded.bitrate-mode", "value") - .limitTo(D::ENCODER)); - add(ConfigMapper(KEY_FRAME_RATE, C2_PARAMKEY_FRAME_RATE, "value") - .limitTo(D::VIDEO) - .withMappers(makeFloat, [](C2Value v) -> C2Value { - // read back always as int - float value; - if (v.get(&value)) { - return (int32_t)value; - } - return C2Value(); - })); - - add(ConfigMapper(KEY_MAX_INPUT_SIZE, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE, "value") - .limitTo(D::INPUT)); - // remove when codecs switch to PARAMKEY - deprecated(ConfigMapper(KEY_MAX_INPUT_SIZE, "coded.max-frame-size", "value") - .limitTo(D::INPUT)); - - // Rotation - // Note: SDK rotation is clock-wise, while C2 rotation is counter-clock-wise - add(ConfigMapper(KEY_ROTATION, C2_PARAMKEY_VUI_ROTATION, "value") - .limitTo(D::VIDEO & D::CODED) - .withMappers(negate, negate)); - add(ConfigMapper(KEY_ROTATION, C2_PARAMKEY_ROTATION, "value") - .limitTo(D::VIDEO & D::RAW) - .withMappers(negate, negate)); - - // android 'video-scaling' - add(ConfigMapper("android._video-scaling", C2_PARAMKEY_SURFACE_SCALING_MODE, "value") - .limitTo(D::VIDEO & D::DECODER & D::RAW)); - - // Color Aspects - // - // configure default for decoders - add(ConfigMapper(KEY_COLOR_RANGE, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "range") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & (D::CONFIG | D::PARAM)) - .withC2Mappers<C2Color::range_t>()); - add(ConfigMapper(KEY_COLOR_TRANSFER, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "transfer") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & (D::CONFIG | D::PARAM)) - .withC2Mappers<C2Color::transfer_t>()); - add(ConfigMapper("color-primaries", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "primaries") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & (D::CONFIG | D::PARAM))); - add(ConfigMapper("color-matrix", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "matrix") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & (D::CONFIG | D::PARAM))); - - // read back final for decoder output (also, configure final aspects as well. This should be - // overwritten based on coded/default values if component supports color aspects, but is used - // as final values if component does not support aspects at all) - add(ConfigMapper(KEY_COLOR_RANGE, C2_PARAMKEY_COLOR_ASPECTS, "range") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW) - .withC2Mappers<C2Color::range_t>()); - add(ConfigMapper(KEY_COLOR_TRANSFER, C2_PARAMKEY_COLOR_ASPECTS, "transfer") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW) - .withC2Mappers<C2Color::transfer_t>()); - add(ConfigMapper("color-primaries", C2_PARAMKEY_COLOR_ASPECTS, "primaries") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW)); - add(ConfigMapper("color-matrix", C2_PARAMKEY_COLOR_ASPECTS, "matrix") - .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW)); - - // configure source aspects for encoders and read them back on the coded(!) port. - // This is to ensure muxing the desired aspects into the container. - add(ConfigMapper(KEY_COLOR_RANGE, C2_PARAMKEY_COLOR_ASPECTS, "range") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::CODED) - .withC2Mappers<C2Color::range_t>()); - add(ConfigMapper(KEY_COLOR_TRANSFER, C2_PARAMKEY_COLOR_ASPECTS, "transfer") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::CODED) - .withC2Mappers<C2Color::transfer_t>()); - add(ConfigMapper("color-primaries", C2_PARAMKEY_COLOR_ASPECTS, "primaries") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::CODED)); - add(ConfigMapper("color-matrix", C2_PARAMKEY_COLOR_ASPECTS, "matrix") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::CODED)); - - // read back coded aspects for encoders (on the raw port), but also configure - // desired aspects here. - add(ConfigMapper(KEY_COLOR_RANGE, C2_PARAMKEY_VUI_COLOR_ASPECTS, "range") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::RAW) - .withC2Mappers<C2Color::range_t>()); - add(ConfigMapper(KEY_COLOR_TRANSFER, C2_PARAMKEY_VUI_COLOR_ASPECTS, "transfer") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::RAW) - .withC2Mappers<C2Color::transfer_t>()); - add(ConfigMapper("color-primaries", C2_PARAMKEY_VUI_COLOR_ASPECTS, "primaries") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::RAW)); - add(ConfigMapper("color-matrix", C2_PARAMKEY_VUI_COLOR_ASPECTS, "matrix") - .limitTo((D::VIDEO | D::IMAGE) & D::ENCODER & D::RAW)); - - // Dataspace - add(ConfigMapper("android._dataspace", C2_PARAMKEY_DATA_SPACE, "value") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - - // HDR - add(ConfigMapper("smpte2086.red.x", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.red.x") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.red.y", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.red.y") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.green.x", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.green.x") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.green.y", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.green.y") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.blue.x", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.blue.x") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.blue.y", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.blue.y") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.white.x", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.white.x") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.white.y", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.white.y") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.max-luminance", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.max-luminance") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("smpte2086.min-luminance", C2_PARAMKEY_HDR_STATIC_INFO, "mastering.min-luminance") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("cta861.max-cll", C2_PARAMKEY_HDR_STATIC_INFO, "max-cll") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper("cta861.max-fall", C2_PARAMKEY_HDR_STATIC_INFO, "max-fall") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - - add(ConfigMapper(std::string(KEY_FEATURE_) + FEATURE_SecurePlayback, - C2_PARAMKEY_SECURE_MODE, "value")); - - add(ConfigMapper("prepend-sps-pps-to-idr-frames", - C2_PARAMKEY_PREPEND_HEADER_MODE, "value") - .limitTo(D::ENCODER & D::VIDEO) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (v.get(&value) && value) { - return C2Value(C2Config::PREPEND_HEADER_TO_ALL_SYNC); - } else { - return C2Value(C2Config::PREPEND_HEADER_TO_NONE); - } - })); - // remove when codecs switch to PARAMKEY - deprecated(ConfigMapper("prepend-sps-pps-to-idr-frames", - "coding.add-csd-to-sync-frames", "value") - .limitTo(D::ENCODER & D::VIDEO)); - // convert to timestamp base - add(ConfigMapper(KEY_I_FRAME_INTERVAL, C2_PARAMKEY_SYNC_FRAME_INTERVAL, "value") - .withMapper([](C2Value v) -> C2Value { - // convert from i32 to float - int32_t i32Value; - float fpValue; - if (v.get(&i32Value)) { - return int64_t(1000000) * i32Value; - } else if (v.get(&fpValue)) { - return int64_t(c2_min(1000000 * fpValue + 0.5, (double)INT64_MAX)); - } - return C2Value(); - })); - // remove when codecs switch to proper coding.gop (add support for calculating gop) - deprecated(ConfigMapper("i-frame-period", "coding.gop", "intra-period") - .limitTo(D::ENCODER & D::VIDEO)); - add(ConfigMapper(KEY_INTRA_REFRESH_PERIOD, C2_PARAMKEY_INTRA_REFRESH, "period") - .limitTo(D::VIDEO & D::ENCODER) - .withMappers(makeFloat, [](C2Value v) -> C2Value { - // read back always as int - float value; - if (v.get(&value)) { - return (int32_t)value; - } - 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) - .withMapper([](C2Value) -> C2Value { return uint32_t(1); })); - add(ConfigMapper(PARAMETER_KEY_REQUEST_SYNC_FRAME, - C2_PARAMKEY_REQUEST_SYNC_FRAME, "value") - .limitTo(D::PARAM & D::ENCODER) - .withMapper([](C2Value) -> C2Value { return uint32_t(1); })); - - add(ConfigMapper(KEY_OPERATING_RATE, C2_PARAMKEY_OPERATING_RATE, "value") - .limitTo(D::PARAM | D::CONFIG) // write-only - .withMapper(makeFloat)); - // C2 priorities are inverted - add(ConfigMapper(KEY_PRIORITY, C2_PARAMKEY_PRIORITY, "value") - .withMappers(negate, negate)); - // remove when codecs switch to PARAMKEY - deprecated(ConfigMapper(KEY_OPERATING_RATE, "ctrl.operating-rate", "value") - .withMapper(makeFloat)); - deprecated(ConfigMapper(KEY_PRIORITY, "ctrl.priority", "value")); - - add(ConfigMapper(KEY_WIDTH, C2_PARAMKEY_PICTURE_SIZE, "width") - .limitTo(D::VIDEO | D::IMAGE)); - add(ConfigMapper(KEY_HEIGHT, C2_PARAMKEY_PICTURE_SIZE, "height") - .limitTo(D::VIDEO | D::IMAGE)); - - add(ConfigMapper("crop-left", C2_PARAMKEY_CROP_RECT, "left") - .limitTo(D::VIDEO | D::IMAGE)); - add(ConfigMapper("crop-top", C2_PARAMKEY_CROP_RECT, "top") - .limitTo(D::VIDEO | D::IMAGE)); - add(ConfigMapper("crop-width", C2_PARAMKEY_CROP_RECT, "width") - .limitTo(D::VIDEO | D::IMAGE)); - add(ConfigMapper("crop-height", C2_PARAMKEY_CROP_RECT, "height") - .limitTo(D::VIDEO | D::IMAGE)); - - add(ConfigMapper(KEY_MAX_WIDTH, C2_PARAMKEY_MAX_PICTURE_SIZE, "width") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - add(ConfigMapper(KEY_MAX_HEIGHT, C2_PARAMKEY_MAX_PICTURE_SIZE, "height") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); - - add(ConfigMapper("csd-0", C2_PARAMKEY_INIT_DATA, "value") - .limitTo(D::OUTPUT & D::READ)); - - add(ConfigMapper(KEY_HDR10_PLUS_INFO, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO, "value") - .limitTo(D::VIDEO & D::PARAM & D::INPUT)); - - add(ConfigMapper(KEY_HDR10_PLUS_INFO, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO, "value") - .limitTo(D::VIDEO & D::OUTPUT)); - - add(ConfigMapper(C2_PARAMKEY_TEMPORAL_LAYERING, C2_PARAMKEY_TEMPORAL_LAYERING, "") - .limitTo(D::ENCODER & D::VIDEO & D::OUTPUT)); - - // Pixel Format (use local key for actual pixel format as we don't distinguish between - // SDK layouts for flexible format and we need the actual SDK color format in the media format) - add(ConfigMapper("android._color-format", C2_PARAMKEY_PIXEL_FORMAT, "value") - .limitTo((D::VIDEO | D::IMAGE) & D::RAW) - .withMappers([](C2Value v) -> C2Value { - int32_t value; - if (v.get(&value)) { - switch (value) { - case COLOR_FormatSurface: - return (uint32_t)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; - case COLOR_FormatYUV420Flexible: - return (uint32_t)HAL_PIXEL_FORMAT_YCBCR_420_888; - case COLOR_FormatYUV420Planar: - case COLOR_FormatYUV420SemiPlanar: - case COLOR_FormatYUV420PackedPlanar: - case COLOR_FormatYUV420PackedSemiPlanar: - return (uint32_t)HAL_PIXEL_FORMAT_YV12; - default: - // TODO: support some sort of passthrough - break; - } - } - return C2Value(); - }, [](C2Value v) -> C2Value { - uint32_t value; - if (v.get(&value)) { - switch (value) { - case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: - return COLOR_FormatSurface; - case HAL_PIXEL_FORMAT_YV12: - case HAL_PIXEL_FORMAT_YCBCR_420_888: - return COLOR_FormatYUV420Flexible; - default: - // TODO: support some sort of passthrough - break; - } - } - return C2Value(); - })); - - add(ConfigMapper(KEY_CHANNEL_COUNT, C2_PARAMKEY_CHANNEL_COUNT, "value") - .limitTo(D::AUDIO)); // read back to both formats - add(ConfigMapper(KEY_CHANNEL_COUNT, C2_PARAMKEY_CODED_CHANNEL_COUNT, "value") - .limitTo(D::AUDIO & D::CODED)); - - add(ConfigMapper(KEY_SAMPLE_RATE, C2_PARAMKEY_SAMPLE_RATE, "value") - .limitTo(D::AUDIO)); // read back to both port formats - 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") - .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(); - })); - - add(ConfigMapper(KEY_IS_ADTS, C2_PARAMKEY_AAC_PACKAGING, "value") - .limitTo(D::AUDIO & D::CODED) - .withMappers([](C2Value v) -> C2Value { - int32_t value; - if (v.get(&value) && value) { - return C2Config::AAC_PACKAGING_ADTS; - } - return C2Value(); - }, [](C2Value v) -> C2Value { - uint32_t value; - if (v.get(&value) && value == C2Config::AAC_PACKAGING_ADTS) { - return (int32_t)1; - } - return C2Value(); - })); - - std::shared_ptr<C2Mapper::ProfileLevelMapper> mapper = - C2Mapper::GetProfileLevelMapper(mCodingMediaType); - - add(ConfigMapper(KEY_PROFILE, C2_PARAMKEY_PROFILE_LEVEL, "profile") - .limitTo(D::CODED) - .withMappers([mapper](C2Value v) -> C2Value { - C2Config::profile_t c2 = PROFILE_UNUSED; - int32_t sdk; - if (mapper && v.get(&sdk) && mapper->mapProfile(sdk, &c2)) { - return c2; - } - return PROFILE_UNUSED; - }, [mapper](C2Value v) -> C2Value { - C2Config::profile_t c2; - int32_t sdk; - using C2ValueType=typename _c2_reduce_enum_to_underlying_type<decltype(c2)>::type; - if (mapper && v.get((C2ValueType*)&c2) && mapper->mapProfile(c2, &sdk)) { - return sdk; - } - return C2Value(); - })); - - add(ConfigMapper(KEY_LEVEL, C2_PARAMKEY_PROFILE_LEVEL, "level") - .limitTo(D::CODED) - .withMappers([mapper](C2Value v) -> C2Value { - C2Config::level_t c2 = LEVEL_UNUSED; - int32_t sdk; - if (mapper && v.get(&sdk) && mapper->mapLevel(sdk, &c2)) { - return c2; - } - return LEVEL_UNUSED; - }, [mapper](C2Value v) -> C2Value { - C2Config::level_t c2; - int32_t sdk; - using C2ValueType=typename _c2_reduce_enum_to_underlying_type<decltype(c2)>::type; - if (mapper && v.get((C2ValueType*)&c2) && mapper->mapLevel(c2, &sdk)) { - return sdk; - } - return C2Value(); - })); - - // convert to dBFS and add default - add(ConfigMapper(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL, "value") - .limitTo(D::AUDIO & D::DECODER) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (!v.get(&value) || value < 0) { - value = property_get_int32(PROP_DRC_OVERRIDE_REF_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL); - } - return float(-0.25 * c2_min(value, 127)); - })); - - // convert to 0-1 (%) and add default - add(ConfigMapper(KEY_AAC_DRC_ATTENUATION_FACTOR, C2_PARAMKEY_DRC_ATTENUATION_FACTOR, "value") - .limitTo(D::AUDIO & D::DECODER) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (!v.get(&value) || value < 0) { - value = property_get_int32(PROP_DRC_OVERRIDE_CUT, DRC_DEFAULT_MOBILE_DRC_CUT); - } - return float(c2_min(value, 127) / 127.); - })); - - // convert to 0-1 (%) and add default - add(ConfigMapper(KEY_AAC_DRC_BOOST_FACTOR, C2_PARAMKEY_DRC_BOOST_FACTOR, "value") - .limitTo(D::AUDIO & D::DECODER) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (!v.get(&value) || value < 0) { - value = property_get_int32(PROP_DRC_OVERRIDE_BOOST, DRC_DEFAULT_MOBILE_DRC_BOOST); - } - return float(c2_min(value, 127) / 127.); - })); - - // convert to compression type and add default - add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value") - .limitTo(D::AUDIO & D::DECODER) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (!v.get(&value) || value < 0) { - value = property_get_int32(PROP_DRC_OVERRIDE_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY); - } - return value == 1 ? C2Config::DRC_COMPRESSION_HEAVY : C2Config::DRC_COMPRESSION_LIGHT; - })); - - // convert to dBFS and add default - add(ConfigMapper(KEY_AAC_ENCODED_TARGET_LEVEL, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL, "value") - .limitTo(D::AUDIO & D::DECODER) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (!v.get(&value) || value < 0) { - value = property_get_int32(PROP_DRC_OVERRIDE_ENC_LEVEL, DRC_DEFAULT_MOBILE_ENC_LEVEL); - } - return float(-0.25 * c2_min(value, 127)); - })); - - // convert to effect type (these map to SDK values) and add default - add(ConfigMapper(KEY_AAC_DRC_EFFECT_TYPE, C2_PARAMKEY_DRC_EFFECT_TYPE, "value") - .limitTo(D::AUDIO & D::DECODER) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (!v.get(&value) || value < -1 || value > 8) { - value = property_get_int32(PROP_DRC_OVERRIDE_EFFECT, DRC_DEFAULT_MOBILE_DRC_EFFECT); - // ensure value is within range - if (value < -1 || value > 8) { - value = DRC_DEFAULT_MOBILE_DRC_EFFECT; - } - } - return value; - })); - - add(ConfigMapper(KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT, C2_PARAMKEY_MAX_CHANNEL_COUNT, "value") - .limitTo(D::AUDIO)); - - add(ConfigMapper(KEY_AAC_SBR_MODE, C2_PARAMKEY_AAC_SBR_MODE, "value") - .limitTo(D::AUDIO & D::ENCODER & D::CONFIG) - .withMapper([](C2Value v) -> C2Value { - int32_t value; - if (!v.get(&value) || value < 0) { - return C2Config::AAC_SBR_AUTO; - } - switch (value) { - case 0: return C2Config::AAC_SBR_OFF; - case 1: return C2Config::AAC_SBR_SINGLE_RATE; - case 2: return C2Config::AAC_SBR_DUAL_RATE; - default: return C2Config::AAC_SBR_AUTO + 1; // invalid value - } - })); - - add(ConfigMapper(KEY_QUALITY, C2_PARAMKEY_QUALITY, "value")); - 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)); - - add(ConfigMapper(KEY_GRID_COLUMNS, C2_PARAMKEY_TILE_LAYOUT, "columns") - .limitTo(D::IMAGE)); - add(ConfigMapper(KEY_GRID_ROWS, C2_PARAMKEY_TILE_LAYOUT, "rows") - .limitTo(D::IMAGE)); - add(ConfigMapper(KEY_TILE_WIDTH, C2_PARAMKEY_TILE_LAYOUT, "tile.width") - .limitTo(D::IMAGE)); - add(ConfigMapper(KEY_TILE_HEIGHT, C2_PARAMKEY_TILE_LAYOUT, "tile.height") - .limitTo(D::IMAGE)); - - add(ConfigMapper(KEY_LATENCY, C2_PARAMKEY_PIPELINE_DELAY_REQUEST, "value") - .limitTo(D::VIDEO & D::ENCODER)); - - add(ConfigMapper(C2_PARAMKEY_INPUT_TIME_STRETCH, C2_PARAMKEY_INPUT_TIME_STRETCH, "value")); - - /* still to do - constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown"; - - not yet used by MediaCodec, but defined as MediaFormat - KEY_AUDIO_SESSION_ID // we use "audio-hw-sync" - KEY_OUTPUT_REORDER_DEPTH - */ -} - -status_t CCodecConfig::initialize( - const std::shared_ptr<Codec2Client> &client, - const std::shared_ptr<Codec2Client::Component> &component) { - C2ComponentDomainSetting domain(C2Component::DOMAIN_OTHER); - C2ComponentKindSetting kind(C2Component::KIND_OTHER); - - std::vector<std::unique_ptr<C2Param>> queried; - c2_status_t c2err = component->query({ &domain, &kind }, {}, C2_DONT_BLOCK, &queried); - if (c2err != C2_OK) { - ALOGD("Query domain & kind failed => %s", asString(c2err)); - // TEMP: determine kind from component name - if (kind.value == C2Component::KIND_OTHER) { - if (component->getName().find("encoder") != std::string::npos) { - kind.value = C2Component::KIND_ENCODER; - } else if (component->getName().find("decoder") != std::string::npos) { - kind.value = C2Component::KIND_DECODER; - } - } - - // TEMP: determine domain from media type (port (preferred) or stream #0) - if (domain.value == C2Component::DOMAIN_OTHER) { - AString mediaType = QueryMediaType(true /* input */, component); - if (mediaType.startsWith("audio/")) { - domain.value = C2Component::DOMAIN_AUDIO; - } else if (mediaType.startsWith("video/")) { - domain.value = C2Component::DOMAIN_VIDEO; - } else if (mediaType.startsWith("image/")) { - domain.value = C2Component::DOMAIN_IMAGE; - } - } - } - - mDomain = (domain.value == C2Component::DOMAIN_VIDEO ? Domain::IS_VIDEO : - domain.value == C2Component::DOMAIN_IMAGE ? Domain::IS_IMAGE : - domain.value == C2Component::DOMAIN_AUDIO ? Domain::IS_AUDIO : Domain::OTHER_DOMAIN) - | (kind.value == C2Component::KIND_DECODER ? Domain::IS_DECODER : - kind.value == C2Component::KIND_ENCODER ? Domain::IS_ENCODER : Domain::OTHER_KIND); - - mInputDomain = Domain(((mDomain & IS_DECODER) ? IS_CODED : IS_RAW) | IS_INPUT); - mOutputDomain = Domain(((mDomain & IS_ENCODER) ? IS_CODED : IS_RAW) | IS_OUTPUT); - - ALOGV("domain is %#x (%u %u)", mDomain, domain.value, kind.value); - - std::vector<C2Param::Index> paramIndices; - switch (kind.value) { - case C2Component::KIND_DECODER: - mCodingMediaType = QueryMediaType(true /* input */, component).c_str(); - break; - case C2Component::KIND_ENCODER: - mCodingMediaType = QueryMediaType(false /* input */, component).c_str(); - break; - default: - mCodingMediaType = ""; - } - - c2err = component->querySupportedParams(&mParamDescs); - if (c2err != C2_OK) { - ALOGD("Query supported params failed after returning %zu values => %s", - mParamDescs.size(), asString(c2err)); - return UNKNOWN_ERROR; - } - for (const std::shared_ptr<C2ParamDescriptor> &desc : mParamDescs) { - mSupportedIndices.emplace(desc->index()); - } - - mReflector = client->getParamReflector(); - if (mReflector == nullptr) { - ALOGE("Failed to get param reflector"); - return UNKNOWN_ERROR; - } - - // enumerate all fields - mParamUpdater = std::make_shared<ReflectedParamUpdater>(); - mParamUpdater->clear(); - mParamUpdater->supportWholeParam( - C2_PARAMKEY_TEMPORAL_LAYERING, C2StreamTemporalLayeringTuning::CORE_INDEX); - mParamUpdater->addParamDesc(mReflector, mParamDescs); - - // TEMP: add some standard fields even if not reflected - if (kind.value == C2Component::KIND_ENCODER) { - mParamUpdater->addStandardParam<C2StreamInitDataInfo::output>(C2_PARAMKEY_INIT_DATA); - } - if (domain.value == C2Component::DOMAIN_IMAGE || domain.value == C2Component::DOMAIN_VIDEO) { - if (kind.value != C2Component::KIND_ENCODER) { - addLocalParam<C2StreamPictureSizeInfo::output>(C2_PARAMKEY_PICTURE_SIZE); - addLocalParam<C2StreamCropRectInfo::output>(C2_PARAMKEY_CROP_RECT); - addLocalParam( - new C2StreamPixelAspectRatioInfo::output(0u, 1u, 1u), - C2_PARAMKEY_PIXEL_ASPECT_RATIO); - addLocalParam(new C2StreamRotationInfo::output(0u, 0), C2_PARAMKEY_ROTATION); - addLocalParam(new C2StreamColorAspectsInfo::output(0u), C2_PARAMKEY_COLOR_ASPECTS); - addLocalParam<C2StreamDataSpaceInfo::output>(C2_PARAMKEY_DATA_SPACE); - addLocalParam<C2StreamHdrStaticInfo::output>(C2_PARAMKEY_HDR_STATIC_INFO); - addLocalParam(new C2StreamSurfaceScalingInfo::output(0u, VIDEO_SCALING_MODE_SCALE_TO_FIT), - C2_PARAMKEY_SURFACE_SCALING_MODE); - } else { - addLocalParam(new C2StreamColorAspectsInfo::input(0u), C2_PARAMKEY_COLOR_ASPECTS); - } - } - - initializeStandardParams(); - - // subscribe to all supported standard (exposed) params - // TODO: limit this to params that are actually in the domain - std::vector<std::string> formatKeys = mStandardParams->getPathsForDomain(Domain(1 << 30)); - std::vector<C2Param::Index> indices; - mParamUpdater->getParamIndicesForKeys(formatKeys, &indices); - mSubscribedIndices.insert(indices.begin(), indices.end()); - - // also subscribe to some non-SDK standard parameters - // for number of input/output buffers - mSubscribedIndices.emplace(C2PortSuggestedBufferCountTuning::input::PARAM_TYPE); - mSubscribedIndices.emplace(C2PortSuggestedBufferCountTuning::output::PARAM_TYPE); - mSubscribedIndices.emplace(C2ActualPipelineDelayTuning::PARAM_TYPE); - mSubscribedIndices.emplace(C2PortActualDelayTuning::input::PARAM_TYPE); - mSubscribedIndices.emplace(C2PortActualDelayTuning::output::PARAM_TYPE); - // for output buffer array allocation - mSubscribedIndices.emplace(C2StreamMaxBufferSizeInfo::output::PARAM_TYPE); - // init data (CSD) - mSubscribedIndices.emplace(C2StreamInitDataInfo::output::PARAM_TYPE); - - return OK; -} - -status_t CCodecConfig::subscribeToConfigUpdate( - const std::shared_ptr<Codec2Client::Component> &component, - const std::vector<C2Param::Index> &indices, - c2_blocking_t blocking) { - mSubscribedIndices.insert(indices.begin(), indices.end()); - // TODO: enable this when components no longer crash on this config - if (mSubscribedIndices.size() != mSubscribedIndicesSize && false) { - std::vector<uint32_t> indices; - for (C2Param::Index ix : mSubscribedIndices) { - indices.push_back(ix); - } - std::unique_ptr<C2SubscribedParamIndicesTuning> subscribeTuning = - C2SubscribedParamIndicesTuning::AllocUnique(indices); - std::vector<std::unique_ptr<C2SettingResult>> results; - c2_status_t c2Err = component->config({ subscribeTuning.get() }, blocking, &results); - if (c2Err != C2_OK && c2Err != C2_BAD_INDEX) { - ALOGD("Failed to subscribe to parameters => %s", asString(c2Err)); - // TODO: error - } - ALOGV("Subscribed to %zu params", mSubscribedIndices.size()); - mSubscribedIndicesSize = mSubscribedIndices.size(); - } - return OK; -} - -status_t CCodecConfig::queryConfiguration( - const std::shared_ptr<Codec2Client::Component> &component) { - // query all subscribed parameters - std::vector<C2Param::Index> indices(mSubscribedIndices.begin(), mSubscribedIndices.end()); - std::vector<std::unique_ptr<C2Param>> queried; - c2_status_t c2Err = component->query({}, indices, C2_MAY_BLOCK, &queried); - if (c2Err != OK) { - ALOGI("query failed after returning %zu values (%s)", queried.size(), asString(c2Err)); - // TODO: error - } - - updateConfiguration(queried, ALL); - return OK; -} - -bool CCodecConfig::updateConfiguration( - std::vector<std::unique_ptr<C2Param>> &configUpdate, Domain domain) { - ALOGV("updating configuration with %zu params", configUpdate.size()); - bool changed = false; - for (std::unique_ptr<C2Param> &p : configUpdate) { - if (p && *p) { - auto insertion = mCurrentConfig.emplace(p->index(), nullptr); - if (insertion.second || *insertion.first->second != *p) { - if (mSupportedIndices.count(p->index()) || mLocalParams.count(p->index())) { - // only track changes in supported (reflected or local) indices - changed = true; - } else { - ALOGV("an unlisted config was %s: %#x", - insertion.second ? "added" : "updated", p->index()); - } - } - insertion.first->second = std::move(p); - } - } - - ALOGV("updated configuration has %zu params (%s)", mCurrentConfig.size(), - changed ? "CHANGED" : "no change"); - if (changed) { - return updateFormats(domain); - } - return false; -} - -bool CCodecConfig::updateFormats(Domain domain) { - // get addresses of params in the current config - std::vector<C2Param*> paramPointers; - for (const auto &it : mCurrentConfig) { - paramPointers.push_back(it.second.get()); - } - - ReflectedParamUpdater::Dict reflected = mParamUpdater->getParams(paramPointers); - ALOGD("c2 config is %s", reflected.debugString().c_str()); - - bool changed = false; - if (domain & mInputDomain) { - sp<AMessage> oldFormat = mInputFormat; - mInputFormat = mInputFormat->dup(); // trigger format changed - mInputFormat->extend(getSdkFormatForDomain(reflected, mInputDomain)); - if (mInputFormat->countEntries() != oldFormat->countEntries() - || mInputFormat->changesFrom(oldFormat)->countEntries() > 0) { - changed = true; - } else { - mInputFormat = oldFormat; // no change - } - } - if (domain & mOutputDomain) { - sp<AMessage> oldFormat = mOutputFormat; - mOutputFormat = mOutputFormat->dup(); // trigger output format changed - mOutputFormat->extend(getSdkFormatForDomain(reflected, mOutputDomain)); - if (mOutputFormat->countEntries() != oldFormat->countEntries() - || mOutputFormat->changesFrom(oldFormat)->countEntries() > 0) { - changed = true; - } else { - mOutputFormat = oldFormat; // no change - } - } - ALOGV_IF(changed, "format(s) changed"); - return changed; -} - -sp<AMessage> CCodecConfig::getSdkFormatForDomain( - const ReflectedParamUpdater::Dict &reflected, Domain portDomain) const { - sp<AMessage> msg = new AMessage; - for (const std::pair<std::string, std::vector<ConfigMapper>> &el : mStandardParams->getKeys()) { - for (const ConfigMapper &cm : el.second) { - if ((cm.domain() & portDomain) == 0 // input-output-coded-raw - || (cm.domain() & mDomain) != mDomain // component domain + kind (these must match) - || (cm.domain() & IS_READ) == 0) { - continue; - } - auto it = reflected.find(cm.path()); - if (it == reflected.end()) { - continue; - } - C2Value c2Value; - sp<ABuffer> bufValue; - AString strValue; - AMessage::ItemData item; - if (it->second.find(&c2Value)) { - item = cm.mapToMessage(c2Value); - } else if (it->second.find(&bufValue)) { - item.set(bufValue); - } else if (it->second.find(&strValue)) { - item.set(strValue); - } else { - ALOGD("unexpected untyped query value for key: %s", cm.path().c_str()); - continue; - } - msg->setItem(el.first.c_str(), item); - } - } - - { // convert from Codec 2.0 rect to MediaFormat rect and add crop rect if not present - int32_t left, top, width, height; - if (msg->findInt32("crop-left", &left) && msg->findInt32("crop-width", &width) - && msg->findInt32("crop-top", &top) && msg->findInt32("crop-height", &height) - && left >= 0 && width >=0 && width <= INT32_MAX - left - && top >= 0 && height >=0 && height <= INT32_MAX - top) { - msg->removeEntryAt(msg->findEntryByName("crop-left")); - msg->removeEntryAt(msg->findEntryByName("crop-top")); - msg->removeEntryAt(msg->findEntryByName("crop-width")); - msg->removeEntryAt(msg->findEntryByName("crop-height")); - msg->setRect("crop", left, top, left + width - 1, top + height - 1); - } else if (msg->findInt32("width", &width) && msg->findInt32("height", &height)) { - msg->setRect("crop", 0, 0, width - 1, height - 1); - } - } - - { // convert temporal layering to schema - sp<ABuffer> tmp; - if (msg->findBuffer(C2_PARAMKEY_TEMPORAL_LAYERING, &tmp) && tmp != nullptr) { - C2StreamTemporalLayeringTuning *layering = - C2StreamTemporalLayeringTuning::From(C2Param::From(tmp->data(), tmp->size())); - if (layering && layering->m.layerCount > 0 - && layering->m.bLayerCount < layering->m.layerCount) { - // check if this is webrtc compatible - AString mime; - if (msg->findString(KEY_MIME, &mime) && - mime.equalsIgnoreCase(MIMETYPE_VIDEO_VP8) && - layering->m.bLayerCount == 0 && - (layering->m.layerCount == 1 - || (layering->m.layerCount == 2 - && layering->flexCount() >= 1 - && layering->m.bitrateRatios[0] == .6f) - || (layering->m.layerCount == 3 - && layering->flexCount() >= 2 - && layering->m.bitrateRatios[0] == .4f - && layering->m.bitrateRatios[1] == .6f) - || (layering->m.layerCount == 4 - && layering->flexCount() >= 3 - && layering->m.bitrateRatios[0] == .25f - && layering->m.bitrateRatios[1] == .4f - && layering->m.bitrateRatios[2] == .6f))) { - msg->setString(KEY_TEMPORAL_LAYERING, AStringPrintf( - "webrtc.vp8.%u-layer", layering->m.layerCount)); - } else if (layering->m.bLayerCount) { - msg->setString(KEY_TEMPORAL_LAYERING, AStringPrintf( - "android.generic.%u+%u", - layering->m.layerCount - layering->m.bLayerCount, - layering->m.bLayerCount)); - } else if (layering->m.bLayerCount) { - msg->setString(KEY_TEMPORAL_LAYERING, AStringPrintf( - "android.generic.%u", layering->m.layerCount)); - } - } - msg->removeEntryAt(msg->findEntryByName(C2_PARAMKEY_TEMPORAL_LAYERING)); - } - } - - { // convert color info - C2Color::primaries_t primaries; - C2Color::matrix_t matrix; - if (msg->findInt32("color-primaries", (int32_t*)&primaries) - && msg->findInt32("color-matrix", (int32_t*)&matrix)) { - int32_t standard; - - if (C2Mapper::map(primaries, matrix, &standard)) { - msg->setInt32(KEY_COLOR_STANDARD, standard); - } - - msg->removeEntryAt(msg->findEntryByName("color-primaries")); - msg->removeEntryAt(msg->findEntryByName("color-matrix")); - } - - - // calculate dataspace for raw graphic buffers if not specified by component, or if - // using surface with unspecified aspects (as those must be defaulted which may change - // the dataspace) - if ((portDomain & IS_RAW) && (mDomain & (IS_IMAGE | IS_VIDEO))) { - android_dataspace dataspace; - ColorAspects aspects = { - ColorAspects::RangeUnspecified, ColorAspects::PrimariesUnspecified, - ColorAspects::TransferUnspecified, ColorAspects::MatrixUnspecified - }; - ColorUtils::getColorAspectsFromFormat(msg, aspects); - ColorAspects origAspects = aspects; - if (mUsingSurface) { - // get image size (default to HD) - int32_t width = 1280; - int32_t height = 720; - int32_t left, top, right, bottom; - if (msg->findRect("crop", &left, &top, &right, &bottom)) { - width = right - left + 1; - height = bottom - top + 1; - } else { - (void)msg->findInt32(KEY_WIDTH, &width); - (void)msg->findInt32(KEY_HEIGHT, &height); - } - ColorUtils::setDefaultCodecColorAspectsIfNeeded(aspects, width, height); - ColorUtils::setColorAspectsIntoFormat(aspects, msg); - } - - if (!msg->findInt32("android._dataspace", (int32_t*)&dataspace) - || aspects.mRange != origAspects.mRange - || aspects.mPrimaries != origAspects.mPrimaries - || aspects.mTransfer != origAspects.mTransfer - || aspects.mMatrixCoeffs != origAspects.mMatrixCoeffs) { - dataspace = ColorUtils::getDataSpaceForColorAspects(aspects, true /* mayExpand */); - msg->setInt32("android._dataspace", dataspace); - } - } - - // HDR static info - - C2HdrStaticMetadataStruct hdr; - if (msg->findFloat("smpte2086.red.x", &hdr.mastering.red.x) - && msg->findFloat("smpte2086.red.y", &hdr.mastering.red.y) - && msg->findFloat("smpte2086.green.x", &hdr.mastering.green.x) - && msg->findFloat("smpte2086.green.y", &hdr.mastering.green.y) - && msg->findFloat("smpte2086.blue.x", &hdr.mastering.blue.x) - && msg->findFloat("smpte2086.blue.y", &hdr.mastering.blue.y) - && msg->findFloat("smpte2086.white.x", &hdr.mastering.white.x) - && msg->findFloat("smpte2086.white.y", &hdr.mastering.white.y) - && msg->findFloat("smpte2086.max-luminance", &hdr.mastering.maxLuminance) - && msg->findFloat("smpte2086.min-luminance", &hdr.mastering.minLuminance) - && msg->findFloat("cta861.max-cll", &hdr.maxCll) - && msg->findFloat("cta861.max-fall", &hdr.maxFall)) { - if (hdr.mastering.red.x >= 0 && hdr.mastering.red.x <= 1 - && hdr.mastering.red.y >= 0 && hdr.mastering.red.y <= 1 - && hdr.mastering.green.x >= 0 && hdr.mastering.green.x <= 1 - && hdr.mastering.green.y >= 0 && hdr.mastering.green.y <= 1 - && hdr.mastering.blue.x >= 0 && hdr.mastering.blue.x <= 1 - && hdr.mastering.blue.y >= 0 && hdr.mastering.blue.y <= 1 - && hdr.mastering.white.x >= 0 && hdr.mastering.white.x <= 1 - && hdr.mastering.white.y >= 0 && hdr.mastering.white.y <= 1 - && hdr.mastering.maxLuminance >= 0 && hdr.mastering.maxLuminance <= 65535 - && hdr.mastering.minLuminance >= 0 && hdr.mastering.minLuminance <= 6.5535 - && hdr.maxCll >= 0 && hdr.maxCll <= 65535 - && hdr.maxFall >= 0 && hdr.maxFall <= 65535) { - HDRStaticInfo meta; - meta.mID = meta.kType1; - meta.sType1.mR.x = hdr.mastering.red.x / 0.00002 + 0.5; - meta.sType1.mR.y = hdr.mastering.red.y / 0.00002 + 0.5; - meta.sType1.mG.x = hdr.mastering.green.x / 0.00002 + 0.5; - meta.sType1.mG.y = hdr.mastering.green.y / 0.00002 + 0.5; - meta.sType1.mB.x = hdr.mastering.blue.x / 0.00002 + 0.5; - meta.sType1.mB.y = hdr.mastering.blue.y / 0.00002 + 0.5; - meta.sType1.mW.x = hdr.mastering.white.x / 0.00002 + 0.5; - meta.sType1.mW.y = hdr.mastering.white.y / 0.00002 + 0.5; - meta.sType1.mMaxDisplayLuminance = hdr.mastering.maxLuminance + 0.5; - meta.sType1.mMinDisplayLuminance = hdr.mastering.minLuminance / 0.0001 + 0.5; - meta.sType1.mMaxContentLightLevel = hdr.maxCll + 0.5; - meta.sType1.mMaxFrameAverageLightLevel = hdr.maxFall + 0.5; - msg->removeEntryAt(msg->findEntryByName("smpte2086.red.x")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.red.y")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.green.x")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.green.y")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.blue.x")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.blue.y")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.white.x")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.white.y")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.max-luminance")); - msg->removeEntryAt(msg->findEntryByName("smpte2086.min-luminance")); - msg->removeEntryAt(msg->findEntryByName("cta861.max-cll")); - msg->removeEntryAt(msg->findEntryByName("cta861.max-fall")); - msg->setBuffer(KEY_HDR_STATIC_INFO, ABuffer::CreateAsCopy(&meta, sizeof(meta))); - } else { - ALOGD("found invalid HDR static metadata %s", msg->debugString(8).c_str()); - } - } - } - - ALOGV("converted to SDK values as %s", msg->debugString().c_str()); - return msg; -} - -/// converts an AMessage value to a ParamUpdater value -static void convert(const AMessage::ItemData &from, ReflectedParamUpdater::Value *to) { - int32_t int32Value; - int64_t int64Value; - sp<ABuffer> bufValue; - AString strValue; - float floatValue; - double doubleValue; - - if (from.find(&int32Value)) { - to->set(int32Value); - } else if (from.find(&int64Value)) { - to->set(int64Value); - } else if (from.find(&bufValue)) { - to->set(bufValue); - } else if (from.find(&strValue)) { - to->set(strValue); - } else if (from.find(&floatValue)) { - to->set(C2Value(floatValue)); - } else if (from.find(&doubleValue)) { - // convert double to float - to->set(C2Value((float)doubleValue)); - } - // ignore all other AMessage types -} - -/// relaxes Codec 2.0 specific value types to SDK types (mainly removes signedness and counterness -/// from 32/64-bit values.) -static void relaxValues(ReflectedParamUpdater::Value &item) { - C2Value c2Value; - int32_t int32Value; - int64_t int64Value; - (void)item.find(&c2Value); - if (c2Value.get(&int32Value) || c2Value.get((uint32_t*)&int32Value) - || c2Value.get((c2_cntr32_t*)&int32Value)) { - item.set(int32Value); - } else if (c2Value.get(&int64Value) - || c2Value.get((uint64_t*)&int64Value) - || c2Value.get((c2_cntr64_t*)&int64Value)) { - item.set(int64Value); - } -} - -ReflectedParamUpdater::Dict CCodecConfig::getReflectedFormat( - const sp<AMessage> ¶ms_, Domain configDomain) const { - // create a modifiable copy of params - sp<AMessage> params = params_->dup(); - ALOGV("filtering with config domain %x", configDomain); - - // convert some macro parameters to Codec 2.0 specific expressions - - { // make i-frame-interval frame based - float iFrameInterval; - if (params->findAsFloat(KEY_I_FRAME_INTERVAL, &iFrameInterval)) { - float frameRate; - if (params->findAsFloat(KEY_FRAME_RATE, &frameRate)) { - params->setInt32("i-frame-period", - (frameRate <= 0 || iFrameInterval < 0) - ? -1 /* no sync frames */ - : (int32_t)c2_min(iFrameInterval * frameRate + 0.5, - (float)INT32_MAX)); - } - } - } - - if (mDomain == (IS_VIDEO | IS_ENCODER)) { - // convert capture-rate into input-time-stretch - float frameRate, captureRate; - if (params->findAsFloat(KEY_FRAME_RATE, &frameRate)) { - if (!params->findAsFloat("time-lapse-fps", &captureRate) - && !params->findAsFloat(KEY_CAPTURE_RATE, &captureRate)) { - captureRate = frameRate; - } - if (captureRate > 0 && frameRate > 0) { - params->setFloat(C2_PARAMKEY_INPUT_TIME_STRETCH, captureRate / frameRate); - } - } - } - - { // reflect temporal layering into a binary blob - AString schema; - if (params->findString(KEY_TEMPORAL_LAYERING, &schema)) { - unsigned int numLayers = 0; - unsigned int numBLayers = 0; - int tags; - char dummy; - std::unique_ptr<C2StreamTemporalLayeringTuning::output> layering; - if (sscanf(schema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1 - && numLayers > 0) { - switch (numLayers) { - case 1: - layering = C2StreamTemporalLayeringTuning::output::AllocUnique( - {}, 0u, 1u, 0u); - break; - case 2: - layering = C2StreamTemporalLayeringTuning::output::AllocUnique( - { .6f }, 0u, 2u, 0u); - break; - case 3: - layering = C2StreamTemporalLayeringTuning::output::AllocUnique( - { .4f, .6f }, 0u, 3u, 0u); - break; - default: - layering = C2StreamTemporalLayeringTuning::output::AllocUnique( - { .25f, .4f, .6f }, 0u, 4u, 0u); - break; - } - } else if ((tags = sscanf(schema.c_str(), "android.generic.%u%c%u%c", - &numLayers, &dummy, &numBLayers, &dummy)) - && (tags == 1 || (tags == 3 && dummy == '+')) - && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) { - layering = C2StreamTemporalLayeringTuning::output::AllocUnique( - {}, 0u, numLayers + numBLayers, numBLayers); - } else { - ALOGD("Ignoring unsupported ts-schema [%s]", schema.c_str()); - } - if (layering) { - params->setBuffer(C2_PARAMKEY_TEMPORAL_LAYERING, - ABuffer::CreateAsCopy(layering.get(), layering->size())); - } - } - } - - { // convert from MediaFormat rect to Codec 2.0 rect - int32_t offset; - int32_t end; - AMessage::ItemData item; - if (params->findInt32("crop-left", &offset) && params->findInt32("crop-right", &end) - && offset >= 0 && end >= offset - 1) { - size_t ix = params->findEntryByName("crop-right"); - params->setEntryNameAt(ix, "crop-width"); - item.set(end - offset + 1); - params->setEntryAt(ix, item); - } - if (params->findInt32("crop-top", &offset) && params->findInt32("crop-bottom", &end) - && offset >= 0 && end >= offset - 1) { - size_t ix = params->findEntryByName("crop-bottom"); - params->setEntryNameAt(ix, "crop-height"); - item.set(end - offset + 1); - params->setEntryAt(ix, item); - } - } - - { // convert color info - int32_t standard; - if (params->findInt32(KEY_COLOR_STANDARD, &standard)) { - C2Color::primaries_t primaries; - C2Color::matrix_t matrix; - - if (C2Mapper::map(standard, &primaries, &matrix)) { - params->setInt32("color-primaries", primaries); - params->setInt32("color-matrix", matrix); - } - } - - sp<ABuffer> hdrMeta; - if (params->findBuffer(KEY_HDR_STATIC_INFO, &hdrMeta) - && hdrMeta->size() == sizeof(HDRStaticInfo)) { - HDRStaticInfo *meta = (HDRStaticInfo*)hdrMeta->data(); - if (meta->mID == meta->kType1) { - params->setFloat("smpte2086.red.x", meta->sType1.mR.x * 0.00002); - params->setFloat("smpte2086.red.y", meta->sType1.mR.y * 0.00002); - params->setFloat("smpte2086.green.x", meta->sType1.mG.x * 0.00002); - params->setFloat("smpte2086.green.y", meta->sType1.mG.y * 0.00002); - params->setFloat("smpte2086.blue.x", meta->sType1.mB.x * 0.00002); - params->setFloat("smpte2086.blue.y", meta->sType1.mB.y * 0.00002); - params->setFloat("smpte2086.white.x", meta->sType1.mW.x * 0.00002); - params->setFloat("smpte2086.white.y", meta->sType1.mW.y * 0.00002); - params->setFloat("smpte2086.max-luminance", meta->sType1.mMaxDisplayLuminance); - params->setFloat("smpte2086.min-luminance", meta->sType1.mMinDisplayLuminance * 0.0001); - params->setFloat("cta861.max-cll", meta->sType1.mMaxContentLightLevel); - params->setFloat("cta861.max-fall", meta->sType1.mMaxFrameAverageLightLevel); - } - } - } - - // this is to verify that we set proper signedness for standard parameters - bool beVeryStrict = property_get_bool("debug.stagefright.ccodec_strict_type", false); - // this is to allow vendors to use the wrong signedness for standard parameters - bool beVeryLax = property_get_bool("debug.stagefright.ccodec_lax_type", false); - - ReflectedParamUpdater::Dict filtered; - for (size_t ix = 0; ix < params->countEntries(); ++ix) { - AMessage::Type type; - AString name = params->getEntryNameAt(ix, &type); - AMessage::ItemData msgItem = params->getEntryAt(ix); - ReflectedParamUpdater::Value item; - convert(msgItem, &item); // convert item to param updater item - - if (name.startsWith("vendor.")) { - // vendor params pass through as is - filtered.emplace(name.c_str(), item); - continue; - } - // standard parameters may get modified, filtered or duplicated - for (const ConfigMapper &cm : mStandardParams->getConfigMappersForSdkKey(name.c_str())) { - // note: we ignore port domain for configuration - if ((cm.domain() & configDomain) - // component domain + kind (these must match) - && (cm.domain() & mDomain) == mDomain) { - // map arithmetic values, pass through string or buffer - switch (type) { - case AMessage::kTypeBuffer: - case AMessage::kTypeString: - break; - case AMessage::kTypeInt32: - case AMessage::kTypeInt64: - case AMessage::kTypeFloat: - case AMessage::kTypeDouble: - // for now only map settings with mappers as we are not creating - // signed <=> unsigned mappers - // TODO: be precise about signed unsigned - if (beVeryStrict || cm.mapper()) { - item.set(cm.mapFromMessage(params->getEntryAt(ix))); - // also allow to relax type strictness - if (beVeryLax) { - relaxValues(item); - } - } - break; - default: - continue; - } - filtered.emplace(cm.path(), item); - } - } - } - ALOGV("filtered %s to %s", params->debugString(4).c_str(), - filtered.debugString(4).c_str()); - return filtered; -} - -status_t CCodecConfig::getConfigUpdateFromSdkParams( - std::shared_ptr<Codec2Client::Component> component, - const sp<AMessage> &sdkParams, Domain configDomain, - c2_blocking_t blocking, - std::vector<std::unique_ptr<C2Param>> *configUpdate) const { - ReflectedParamUpdater::Dict params = getReflectedFormat(sdkParams, configDomain); - - std::vector<C2Param::Index> indices; - mParamUpdater->getParamIndicesFromMessage(params, &indices); - if (indices.empty()) { - ALOGD("no recognized params in: %s", params.debugString().c_str()); - return OK; - } - - configUpdate->clear(); - std::vector<C2Param::Index> supportedIndices; - for (C2Param::Index ix : indices) { - if (mSupportedIndices.count(ix)) { - supportedIndices.push_back(ix); - } else if (mLocalParams.count(ix)) { - // query local parameter here - auto it = mCurrentConfig.find(ix); - if (it != mCurrentConfig.end()) { - configUpdate->emplace_back(C2Param::Copy(*it->second)); - } - } - } - - c2_status_t err = component->query({ }, supportedIndices, blocking, configUpdate); - if (err != C2_OK) { - ALOGD("query failed after returning %zu params => %s", configUpdate->size(), asString(err)); - } - - if (configUpdate->size()) { - mParamUpdater->updateParamsFromMessage(params, configUpdate); - } - return OK; -} - -status_t CCodecConfig::setParameters( - std::shared_ptr<Codec2Client::Component> component, - std::vector<std::unique_ptr<C2Param>> &configUpdate, - c2_blocking_t blocking) { - status_t result = OK; - if (configUpdate.empty()) { - return OK; - } - - std::vector<C2Param::Index> indices; - std::vector<C2Param *> paramVector; - for (const std::unique_ptr<C2Param> ¶m : configUpdate) { - if (mSupportedIndices.count(param->index())) { - // component parameter - paramVector.push_back(param.get()); - indices.push_back(param->index()); - } else if (mLocalParams.count(param->index())) { - // handle local parameter here - LocalParamValidator validator = mLocalParams.find(param->index())->second; - c2_status_t err = C2_OK; - std::unique_ptr<C2Param> copy = C2Param::Copy(*param); - if (validator) { - err = validator(copy); - } - if (err == C2_OK) { - ALOGV("updated local parameter value for %s", - mParamUpdater->getParamName(param->index()).c_str()); - - mCurrentConfig[param->index()] = std::move(copy); - } else { - ALOGD("failed to set parameter value for %s => %s", - mParamUpdater->getParamName(param->index()).c_str(), asString(err)); - result = BAD_VALUE; - } - } - } - // update subscribed param indices - subscribeToConfigUpdate(component, indices, blocking); - - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = component->config(paramVector, blocking, &failures); - if (err != C2_OK) { - ALOGD("config failed => %s", asString(err)); - // This is non-fatal. - } - for (const std::unique_ptr<C2SettingResult> &failure : failures) { - switch (failure->failure) { - case C2SettingResult::BAD_VALUE: - ALOGD("Bad parameter value"); - result = BAD_VALUE; - break; - default: - ALOGV("failure = %d", int(failure->failure)); - break; - } - } - - // Re-query parameter values in case config could not update them and update the current - // configuration. - configUpdate.clear(); - err = component->query({}, indices, blocking, &configUpdate); - if (err != C2_OK) { - ALOGD("query failed after returning %zu params => %s", configUpdate.size(), asString(err)); - } - (void)updateConfiguration(configUpdate, ALL); - - // TODO: error value - return result; -} - -const C2Param *CCodecConfig::getConfigParameterValue(C2Param::Index index) const { - auto it = mCurrentConfig.find(index); - if (it == mCurrentConfig.end()) { - return nullptr; - } else { - return it->second.get(); - } -} - -} // namespace android diff --git a/media/sfplugin/CCodecConfig.h b/media/sfplugin/CCodecConfig.h deleted file mode 100644 index 3bafe3f..0000000 --- a/media/sfplugin/CCodecConfig.h +++ /dev/null @@ -1,345 +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 C_CODEC_CONFIG_H_ -#define C_CODEC_CONFIG_H_ - -#include <map> -#include <memory> -#include <set> -#include <vector> - -#include <C2Component.h> -#include <codec2/hidl/client.h> - -#include <utils/RefBase.h> - -#include "InputSurfaceWrapper.h" -#include "ReflectedParamUpdater.h" - -namespace android { - -struct AMessage; -struct StandardParams; - -/** - * Struct managing the codec configuration for CCodec. - */ -struct CCodecConfig { - - /** - * Domain consists of a bitmask divided into fields, and specifiers work by excluding other - * values in those domains. - * - * Component domains are composed by or-ing the individual IS_ constants, e.g. - * IS_DECODER | IS_AUDIO. - * - * Config specifiers are composed by or-ing the individual mask constants, and - * and-ing these groups: e.g. (DECODER | ENCODER) & AUDIO. - * - * The naming of these constants was to limit the length of mask names as these are used more - * commonly as masks. - */ - enum Domain : uint32_t { - // component domain (domain & kind) - GUARD_BIT = (1 << 1), ///< this is to prevent against accidental && or || usage - IS_AUDIO = (1 << 2), ///< for audio codecs - IS_VIDEO = (1 << 3), ///< for video codecs - IS_IMAGE = (1 << 4), ///< for image codecs - OTHER_DOMAIN = (1 << 5), ///< for other domains - - IS_ENCODER = (1 << 6), ///< for encoders - IS_DECODER = (1 << 7), ///< for decoders - OTHER_KIND = (1 << 8), ///< for other domains - - // config domain - IS_PARAM = (1 << 9), ///< for setParameter - IS_CONFIG = (1 << 10), ///< for configure - IS_READ = (1 << 11), ///< for getFormat - - // port domain - IS_INPUT = (1 << 12), ///< for input port (getFormat) - IS_OUTPUT = (1 << 13), ///< for output port (getFormat) - IS_RAW = (1 << 14), ///< for raw port (input-encoder, output-decoder) - IS_CODED = (1 << 15), ///< for coded port (input-decoder, output-encoder) - - ALL = ~0U, - NONE = 0, - - AUDIO = ~(IS_IMAGE | IS_VIDEO | OTHER_DOMAIN), - VIDEO = ~(IS_AUDIO | IS_IMAGE | OTHER_DOMAIN), - IMAGE = ~(IS_AUDIO | IS_VIDEO | OTHER_DOMAIN), - - DECODER = ~(IS_ENCODER | OTHER_KIND), - ENCODER = ~(IS_DECODER | OTHER_KIND), - - PARAM = ~(IS_CONFIG | IS_READ), - CONFIG = ~(IS_PARAM | IS_READ), - READ = ~(IS_CONFIG | IS_PARAM), - - INPUT = ~(IS_OUTPUT | IS_RAW | IS_CODED), - OUTPUT = ~(IS_INPUT | IS_RAW | IS_CODED), - RAW = ~(IS_INPUT | IS_OUTPUT | IS_CODED), - CODED = ~(IS_INPUT | IS_RAW | IS_OUTPUT), - }; - - // things required to manage formats - std::vector<std::shared_ptr<C2ParamDescriptor>> mParamDescs; - std::shared_ptr<C2ParamReflector> mReflector; - - std::shared_ptr<ReflectedParamUpdater> mParamUpdater; - - Domain mDomain; // component domain - Domain mInputDomain; // input port domain - Domain mOutputDomain; // output port domain - std::string mCodingMediaType; // media type of the coded stream - - // standard MediaCodec to Codec 2.0 params mapping - std::shared_ptr<StandardParams> mStandardParams; - - std::set<C2Param::Index> mSupportedIndices; ///< indices supported by the component - std::set<C2Param::Index> mSubscribedIndices; ///< indices to subscribe to - size_t mSubscribedIndicesSize; ///< count of currently subscribed indices - - sp<AMessage> mInputFormat; - sp<AMessage> mOutputFormat; - - bool mUsingSurface; ///< using input or output surface - - std::shared_ptr<InputSurfaceWrapper> mInputSurface; - std::unique_ptr<InputSurfaceWrapper::Config> mISConfig; - - /// the current configuration. Updated after configure() and based on configUpdate in - /// onWorkDone - std::map<C2Param::Index, std::unique_ptr<C2Param>> mCurrentConfig; - - typedef std::function<c2_status_t(std::unique_ptr<C2Param>&)> LocalParamValidator; - - /// Parameter indices tracked in current config that are not supported by the component. - /// these are provided so that optional parameters can remain in the current configuration. - /// as such, these parameters have no dependencies. TODO: use C2InterfaceHelper for this. - /// For now support a validation function. - std::map<C2Param::Index, LocalParamValidator> mLocalParams; - - CCodecConfig(); - - /// initializes the members required to manage the format: descriptors, reflector, - /// reflected param helper, domain, standard params, and subscribes to standard - /// indices. - status_t initialize( - const std::shared_ptr<Codec2Client> &client, - const std::shared_ptr<Codec2Client::Component> &component); - - - /** - * Adds a locally maintained parameter. This is used for output configuration that can be - * appended to the output buffers in case it is not supported by the component. - */ - template<typename T> - bool addLocalParam( - const std::string &name, - C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY, - std::function<c2_status_t(std::unique_ptr<T>&)> validator_ = - std::function<c2_status_t(std::unique_ptr<T>&)>()) { - C2Param::Index index = T::PARAM_TYPE; - if (mSupportedIndices.count(index) || mLocalParams.count(index)) { - if (mSupportedIndices.count(index)) { - mSubscribedIndices.emplace(index); - } - ALOGD("ignoring local param %s (%#x) as it is already %s", - name.c_str(), (uint32_t)index, mSupportedIndices.count(index) ? "supported" : "local"); - return false; // already supported by the component or already added - } - - // wrap typed validator into untyped validator - LocalParamValidator validator; - if (validator_) { - validator = [validator_](std::unique_ptr<C2Param>& p){ - c2_status_t res = C2_BAD_VALUE; - std::unique_ptr<T> typed(static_cast<T*>(p.release())); - // if parameter is correctly typed - if (T::From(typed.get())) { - res = validator_(typed); - p.reset(typed.release()); - } - return res; - }; - } - - mLocalParams.emplace(index, validator); - mParamUpdater->addStandardParam<T>(name, attrib); - return true; - } - - /** - * Adds a locally maintained parameter with a default value. - */ - template<typename T> - bool addLocalParam( - std::unique_ptr<T> default_, - const std::string &name, - C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY, - std::function<c2_status_t(std::unique_ptr<T>&)> validator_ = - std::function<c2_status_t(std::unique_ptr<T>&)>()) { - if (addLocalParam<T>(name, attrib, validator_)) { - if (validator_) { - c2_status_t err = validator_(default_); - if (err != C2_OK) { - ALOGD("default value for %s is invalid => %s", name.c_str(), asString(err)); - return false; - } - } - mCurrentConfig[T::PARAM_TYPE] = std::move(default_); - return true; - } - return false; - } - - template<typename T> - bool addLocalParam( - T *default_, const std::string &name, - C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY, - std::function<c2_status_t(std::unique_ptr<T>&)> validator_ = - std::function<c2_status_t(std::unique_ptr<T>&)>()) { - return addLocalParam(std::unique_ptr<T>(default_), name, attrib, validator_); - } - - /// Applies configuration updates, and updates format in the specific domain. - /// Returns true if formats were updated - /// \param domain input/output bitmask - bool updateConfiguration( - std::vector<std::unique_ptr<C2Param>> &configUpdate, Domain domain); - - /// Updates formats in the specific domain. Returns true if any of the formats have changed. - /// \param domain input/output bitmask - bool updateFormats(Domain domain); - - /** - * Applies SDK configurations in a specific configuration domain. - * Updates relevant input/output formats and subscribes to parameters specified in the - * configuration. - * \param domain config/setParam bitmask - * \param blocking blocking mode to use with the component - */ - status_t getConfigUpdateFromSdkParams( - std::shared_ptr<Codec2Client::Component> component, - const sp<AMessage> &sdkParams, Domain domain, - c2_blocking_t blocking, - std::vector<std::unique_ptr<C2Param>> *configUpdate) const; - - /** - * Applies a configuration update to the component. - * Updates relevant input/output formats and subscribes to parameters specified in the - * configuration. - * \param blocking blocking mode to use with the component - */ - status_t setParameters( - std::shared_ptr<Codec2Client::Component> component, - std::vector<std::unique_ptr<C2Param>> &configUpdate, - c2_blocking_t blocking); - - /// Queries subscribed indices (which contains all SDK-exposed values) and updates - /// input/output formats. - status_t queryConfiguration( - const std::shared_ptr<Codec2Client::Component> &component); - - /// Queries a configuration parameter value. Returns nullptr if the parameter is not - /// part of the current configuration - const C2Param *getConfigParameterValue(C2Param::Index index) const; - - /** - * Object that can be used to access configuration parameters and if they change. - */ - template<typename T> - struct Watcher { - ~Watcher() = default; - - /// returns true if the value of this configuration has changed - bool hasChanged() const { - const C2Param *value = mParent->getConfigParameterValue(mIndex); - if (value && mValue) { - return *value != *mValue; - } else { - return value != mValue.get(); - } - } - - /// updates the current value and returns it - std::shared_ptr<const T> update() { - const C2Param *value = mParent->getConfigParameterValue(mIndex); - if (value) { - mValue = std::shared_ptr<const T>(T::From(C2Param::Copy(*value).release())); - } - return mValue; - } - - private: - Watcher(C2Param::Index index, const CCodecConfig *parent) - : mParent(parent), mIndex(index) { - update(); - } - - friend struct CCodecConfig; - - const CCodecConfig *mParent; - std::shared_ptr<const T> mValue; - C2Param::Index mIndex; - }; - - /** - * Returns a watcher object for a parameter. - */ - template<typename T> - Watcher<T> watch(C2Param::Index index = T::PARAM_TYPE) const { - if (index.type() != T::PARAM_TYPE) { - __builtin_trap(); - } - return Watcher<T>(index, this); - } - -private: - - /// initializes the standard MediaCodec to Codec 2.0 params mapping - void initializeStandardParams(); - - /// Adds indices to the subscribed indices, and updated subscription to component - /// \param blocking blocking mode to use with the component - status_t subscribeToConfigUpdate( - const std::shared_ptr<Codec2Client::Component> &component, - const std::vector<C2Param::Index> &indices, - c2_blocking_t blocking = C2_DONT_BLOCK); - - /// Gets SDK format from codec 2.0 reflected configuration - /// \param domain input/output bitmask - sp<AMessage> getSdkFormatForDomain( - const ReflectedParamUpdater::Dict &reflected, Domain domain) const; - - /** - * Converts a set of configuration parameters in an AMessage to a list of path-based Codec - * 2.0 configuration parameters. - * - * \param domain config/setParam bitmask - */ - ReflectedParamUpdater::Dict getReflectedFormat( - const sp<AMessage> &config, Domain domain) const; -}; - -DEFINE_ENUM_OPERATORS(CCodecConfig::Domain) - -} // namespace android - -#endif // C_CODEC_H_ - diff --git a/media/sfplugin/Codec2Buffer.cpp b/media/sfplugin/Codec2Buffer.cpp deleted file mode 100644 index 597e8f3..0000000 --- a/media/sfplugin/Codec2Buffer.cpp +++ /dev/null @@ -1,812 +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/hardware/HardwareAPI.h> -#include <media/stagefright/MediaCodecConstants.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/foundation/AUtils.h> -#include <nativebase/nativebase.h> - -#include <C2AllocatorGralloc.h> -#include <C2BlockInternal.h> -#include <C2Debug.h> - -#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 - || buffer->data().linearBlocks()[0].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; -} - -void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) { - meta()->setBuffer("image-data", imageData); - format()->setBuffer("image-data", imageData); - MediaImage2 *img = (MediaImage2*)imageData->data(); - if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) { - int32_t stride = img->mPlane[0].mRowInc; - format()->setInt32(KEY_STRIDE, stride); - if (img->mNumPlanes > 1 && stride > 0) { - int32_t vstride = (img->mPlane[1].mOffset - img->mPlane[0].mOffset) / stride; - format()->setInt32(KEY_SLICE_HEIGHT, vstride); - } - } -} - -// 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 - -static uint8_t sDummyByte[1] = { 0 }; - -DummyContainerBuffer::DummyContainerBuffer( - const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) - : Codec2Buffer(format, new ABuffer(sDummyByte, 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: - /** - * Creates a C2GraphicView <=> MediaImage converter - * - * \param view C2GraphicView object - * \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) - */ - GraphicView2MediaImageConverter( - const C2GraphicView &view, int32_t colorFormat) - : mInitCheck(NO_INIT), - mView(view), - mWidth(view.width()), - mHeight(view.height()), - mColorFormat(colorFormat), - 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; - - // 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); - - switch (layout.type) { - case C2PlanarLayout::TYPE_YUV: - mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; - if (layout.numPlanes != 3) { - ALOGD("Converter: %d planes for YUV layout", layout.numPlanes); - mInitCheck = BAD_VALUE; - return; - } - if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y - || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB - || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR - || layout.planes[0].colSampling != 1 - || layout.planes[0].rowSampling != 1 - || layout.planes[1].colSampling != 2 - || layout.planes[1].rowSampling != 2 - || layout.planes[2].colSampling != 2 - || layout.planes[2].rowSampling != 2) { - ALOGD("Converter: not YUV420 for YUV layout"); - mInitCheck = BAD_VALUE; - return; - } - 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 - 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]]; - - 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].mHorizSubsampling = 1; - mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; - - mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride; - mediaImage->mPlane[mediaImage->U].mColInc = 1; - mediaImage->mPlane[mediaImage->U].mRowInc = mStride / 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].mColInc = 1; - mediaImage->mPlane[mediaImage->V].mRowInc = mStride / 2; - mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; - mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; - break; - - case COLOR_FormatYUV420SemiPlanar: - 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].mHorizSubsampling = 1; - mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; - - mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride; - mediaImage->mPlane[mediaImage->U].mColInc = 2; - mediaImage->mPlane[mediaImage->U].mRowInc = mStride; - mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; - mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; - - mediaImage->mPlane[mediaImage->V].mOffset = mStride * mVStride + 1; - mediaImage->mPlane[mediaImage->V].mColInc = 2; - mediaImage->mPlane[mediaImage->V].mRowInc = mStride; - mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; - mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; - break; - - default: - ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat); - mInitCheck = BAD_VALUE; - return; - } - break; - case C2PlanarLayout::TYPE_YUVA: - mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA; - // We don't have an SDK YUVA format - ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat); - mInitCheck = BAD_VALUE; - return; - case C2PlanarLayout::TYPE_RGB: - mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB; - switch (mColorFormat) { - // TODO media image - case COLOR_FormatRGBFlexible: - case COLOR_Format24bitBGR888: - case COLOR_Format24bitRGB888: - break; - default: - ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat); - mInitCheck = BAD_VALUE; - return; - } - if (layout.numPlanes != 3) { - ALOGD("Converter: %d planes for RGB layout", layout.numPlanes); - mInitCheck = BAD_VALUE; - return; - } - break; - case C2PlanarLayout::TYPE_RGBA: - mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA; - switch (mColorFormat) { - // TODO media image - case COLOR_FormatRGBAFlexible: - case COLOR_Format32bitABGR8888: - case COLOR_Format32bitARGB8888: - case COLOR_Format32bitBGRA8888: - break; - default: - ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat); - mInitCheck = BAD_VALUE; - return; - } - if (layout.numPlanes != 4) { - ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes); - mInitCheck = BAD_VALUE; - return; - } - break; - default: - mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; - ALOGD("Unknown layout"); - mInitCheck = BAD_VALUE; - return; - } - 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.allocatedDepth < plane.bitDepth - || plane.rightShift != plane.allocatedDepth - plane.bitDepth) { - ALOGD("rightShift value of %u unsupported", plane.rightShift); - mInitCheck = BAD_VALUE; - return; - } - if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) { - ALOGD("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 += mStride * mVStride - / plane.rowSampling / plane.colSampling; - } - - mBackBufferSize = bufferSize; - mInitCheck = OK; - } - - status_t initCheck() const { return mInitCheck; } - - uint32_t backBufferSize() const { return mBackBufferSize; } - - /** - * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped - * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the - * data into a backing buffer explicitly. - * - * \return media buffer. This is null if wrapping failed. - */ - sp<ABuffer> wrap() const { - if (mBackBuffer == nullptr) { - return mWrapped; - } - return nullptr; - } - - bool setBackBuffer(const sp<ABuffer> &backBuffer) { - if (backBuffer->capacity() < mBackBufferSize) { - return false; - } - backBuffer->setRange(0, mBackBufferSize); - mBackBuffer = backBuffer; - return true; - } - - /** - * Copy C2GraphicView to MediaImage2. - */ - status_t copyToMediaImage() { - if (mInitCheck != OK) { - return mInitCheck; - } - return ImageCopy(mBackBuffer->base(), getMediaImage(), mView); - } - - const sp<ABuffer> &imageData() const { return mMediaImage; } - -private: - status_t mInitCheck; - - const C2GraphicView mView; - uint32_t mWidth; - uint32_t mHeight; - int32_t mColorFormat; ///< SDK color format for MediaImage - sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer) - uint32_t mAllocatedDepth; - uint32_t mBackBufferSize; - sp<ABuffer> mMediaImage; - std::function<sp<ABuffer>(size_t)> mAlloc; - - sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer - - 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; - } - - int32_t colorFormat = COLOR_FormatYUV420Flexible; - (void)format->findInt32("color-format", &colorFormat); - - GraphicView2MediaImageConverter converter(view, colorFormat); - 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) { - setImageData(imageData); -} - -std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() { - uint32_t width = mView.width(); - uint32_t height = mView.height(); - if (!mWrapped) { - (void)ImageCopy(mView, base(), imageData()); - } - return C2Buffer::CreateGraphicBuffer( - mBlock->share(C2Rect(width, height), C2Fence())); -} - -// GraphicMetadataBuffer -GraphicMetadataBuffer::GraphicMetadataBuffer( - const sp<AMessage> &format, - const std::shared_ptr<C2Allocator> &alloc) - : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))), - mAlloc(alloc) { - ((VideoNativeMetadata *)base())->pBuffer = nullptr; -} - -std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() { -#ifndef __LP64__ - VideoNativeMetadata *meta = (VideoNativeMetadata *)base(); - ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer; - if (buffer == nullptr) { - ALOGD("VideoNativeMetadata contains null buffer"); - return nullptr; - } - - ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height); - C2Handle *handle = WrapNativeCodec2GrallocHandle( - buffer->handle, - buffer->width, - buffer->height, - buffer->format, - buffer->usage, - buffer->stride); - std::shared_ptr<C2GraphicAllocation> alloc; - c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc); - if (err != C2_OK) { - ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation"); - return nullptr; - } - std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc); - - meta->pBuffer = 0; - // TODO: fence - return C2Buffer::CreateGraphicBuffer( - block->share(C2Rect(buffer->width, buffer->height), C2Fence())); -#else - ALOGE("GraphicMetadataBuffer does not work on 64-bit arch"); - return nullptr; -#endif -} - -// 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; - - int32_t colorFormat = COLOR_FormatYUV420Flexible; - (void)format->findInt32("color-format", &colorFormat); - - GraphicView2MediaImageConverter converter(*view, colorFormat); - 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.copyToMediaImage(); - // 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) { - setImageData(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; - } - - int32_t colorFormat = COLOR_FormatYUV420Flexible; - // FIXME: format() is not const, but we cannot change it, so do a const cast here - const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat); - - GraphicView2MediaImageConverter converter( - buffer->data().graphicBlocks()[0].map().get(), colorFormat); - 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; - } - int32_t colorFormat = COLOR_FormatYUV420Flexible; - format()->findInt32("color-format", &colorFormat); - - GraphicView2MediaImageConverter converter( - buffer->data().graphicBlocks()[0].map().get(), colorFormat); - 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.copyToMediaImage(); - setImageData(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/sfplugin/Codec2Buffer.h b/media/sfplugin/Codec2Buffer.h deleted file mode 100644 index d5d41a4..0000000 --- a/media/sfplugin/Codec2Buffer.h +++ /dev/null @@ -1,403 +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 <mediadrm/ICrypto.h> - -namespace android { - -/** - * Copies a graphic view into a media image. - * - * \param imgBase base of MediaImage - * \param img MediaImage data - * \param view graphic view - * - * \return OK on success - */ -status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView &view); - -/** - * Copies a media image into a graphic view. - * - * \param view graphic view - * \param imgBase base of MediaImage - * \param img MediaImage data - * - * \return OK on success - */ -status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage2 *img); - -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); - - /** - * sets MediaImage data for flexible graphic buffers - */ - void setImageData(const sp<ABuffer> &imageData); -}; - -/** - * 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 VideoNativeMetadata. - */ -class GraphicMetadataBuffer : public Codec2Buffer { -public: - /** - * Construct a new GraphicMetadataBuffer with local linear buffer for - * VideoNativeMetadata. - * - * \param format mandatory buffer format for MediaCodecBuffer - */ - GraphicMetadataBuffer( - const sp<AMessage> &format, const std::shared_ptr<C2Allocator> &alloc); - - std::shared_ptr<C2Buffer> asC2Buffer() override; - - virtual ~GraphicMetadataBuffer() = default; - -private: - GraphicMetadataBuffer() = delete; - - std::shared_ptr<C2Allocator> mAlloc; -}; - -/** - * 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/sfplugin/Codec2InfoBuilder.cpp b/media/sfplugin/Codec2InfoBuilder.cpp deleted file mode 100644 index 4a6d672..0000000 --- a/media/sfplugin/Codec2InfoBuilder.cpp +++ /dev/null @@ -1,653 +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 <strings.h> - -#include <C2Component.h> -#include <C2Config.h> -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <Codec2Mapper.h> - -#include <OMX_Audio.h> -#include <OMX_AudioExt.h> -#include <OMX_IndexExt.h> -#include <OMX_Types.h> -#include <OMX_Video.h> -#include <OMX_VideoExt.h> -#include <OMX_AsString.h> - -#include <android/hardware/media/omx/1.0/IOmx.h> -#include <android/hardware/media/omx/1.0/IOmxObserver.h> -#include <android/hardware/media/omx/1.0/IOmxNode.h> -#include <android/hardware/media/omx/1.0/types.h> - -#include <android-base/properties.h> -#include <codec2/hidl/client.h> -#include <cutils/native_handle.h> -#include <media/omx/1.0/WOmxNode.h> -#include <media/stagefright/MediaCodecConstants.h> -#include <media/stagefright/foundation/ALookup.h> -#include <media/stagefright/foundation/MediaDefs.h> -#include <media/stagefright/omx/OMXUtils.h> -#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h> - -#include "Codec2InfoBuilder.h" - -namespace android { - -using Traits = C2Component::Traits; - -namespace /* unnamed */ { - -bool hasPrefix(const std::string& s, const char* prefix) { - size_t prefixLen = strlen(prefix); - return s.compare(0, prefixLen, prefix) == 0; -} - -bool hasSuffix(const std::string& s, const char* suffix) { - size_t suffixLen = strlen(suffix); - return suffixLen > s.size() ? false : - s.compare(s.size() - suffixLen, suffixLen, suffix) == 0; -} - -// Constants from ACodec -constexpr OMX_U32 kPortIndexInput = 0; -constexpr OMX_U32 kPortIndexOutput = 1; -constexpr OMX_U32 kMaxIndicesToCheck = 32; - -status_t queryOmxCapabilities( - const char* name, const char* mediaType, bool isEncoder, - MediaCodecInfo::CapabilitiesWriter* caps) { - - const char *role = GetComponentRole(isEncoder, mediaType); - if (role == nullptr) { - return BAD_VALUE; - } - - using namespace ::android::hardware::media::omx::V1_0; - using ::android::hardware::Return; - using ::android::hardware::Void; - using ::android::hardware::hidl_vec; - using ::android::hardware::media::omx::V1_0::utils::LWOmxNode; - - sp<IOmx> omx = IOmx::getService(); - if (!omx) { - ALOGW("Could not obtain IOmx service."); - return NO_INIT; - } - - struct Observer : IOmxObserver { - virtual Return<void> onMessages(const hidl_vec<Message>&) override { - return Void(); - } - }; - - sp<Observer> observer = new Observer(); - Status status; - sp<IOmxNode> tOmxNode; - Return<void> transStatus = omx->allocateNode( - name, observer, - [&status, &tOmxNode](Status s, const sp<IOmxNode>& n) { - status = s; - tOmxNode = n; - }); - if (!transStatus.isOk()) { - ALOGW("IOmx::allocateNode -- transaction failed."); - return NO_INIT; - } - if (status != Status::OK) { - ALOGW("IOmx::allocateNode -- error returned: %d.", - static_cast<int>(status)); - return NO_INIT; - } - - sp<LWOmxNode> omxNode = new LWOmxNode(tOmxNode); - - status_t err = SetComponentRole(omxNode, role); - if (err != OK) { - omxNode->freeNode(); - ALOGW("Failed to SetComponentRole: component = %s, role = %s.", - name, role); - return err; - } - - bool isVideo = hasPrefix(mediaType, "video/") == 0; - bool isImage = hasPrefix(mediaType, "image/") == 0; - - if (isVideo || isImage) { - OMX_VIDEO_PARAM_PROFILELEVELTYPE param; - InitOMXParams(¶m); - param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; - - for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { - param.nProfileIndex = index; - status_t err = omxNode->getParameter( - OMX_IndexParamVideoProfileLevelQuerySupported, - ¶m, sizeof(param)); - if (err != OK) { - break; - } - caps->addProfileLevel(param.eProfile, param.eLevel); - - // AVC components may not list the constrained profiles explicitly, but - // decoders that support a profile also support its constrained version. - // Encoders must explicitly support constrained profiles. - if (!isEncoder && strcasecmp(mediaType, MEDIA_MIMETYPE_VIDEO_AVC) == 0) { - if (param.eProfile == OMX_VIDEO_AVCProfileHigh) { - caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel); - } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) { - caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedBaseline, param.eLevel); - } - } - - if (index == kMaxIndicesToCheck) { - ALOGW("[%s] stopping checking profiles after %u: %x/%x", - name, index, - param.eProfile, param.eLevel); - } - } - - // Color format query - // return colors in the order reported by the OMX component - // prefix "flexible" standard ones with the flexible equivalent - OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; - InitOMXParams(&portFormat); - portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput; - for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { - portFormat.nIndex = index; - status_t err = omxNode->getParameter( - OMX_IndexParamVideoPortFormat, - &portFormat, sizeof(portFormat)); - if (err != OK) { - break; - } - - OMX_U32 flexibleEquivalent; - if (IsFlexibleColorFormat( - omxNode, portFormat.eColorFormat, false /* usingNativeWindow */, - &flexibleEquivalent)) { - caps->addColorFormat(flexibleEquivalent); - } - caps->addColorFormat(portFormat.eColorFormat); - - if (index == kMaxIndicesToCheck) { - ALOGW("[%s] stopping checking formats after %u: %s(%x)", - name, index, - asString(portFormat.eColorFormat), portFormat.eColorFormat); - } - } - } else if (strcasecmp(mediaType, MEDIA_MIMETYPE_AUDIO_AAC) == 0) { - // More audio codecs if they have profiles. - OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param; - InitOMXParams(¶m); - param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; - for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { - param.nProfileIndex = index; - status_t err = omxNode->getParameter( - (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported, - ¶m, sizeof(param)); - if (err != OK) { - break; - } - // For audio, level is ignored. - caps->addProfileLevel(param.eProfile, 0 /* level */); - - if (index == kMaxIndicesToCheck) { - ALOGW("[%s] stopping checking profiles after %u: %x", - name, index, - param.eProfile); - } - } - - // NOTE: Without Android extensions, OMX does not provide a way to query - // AAC profile support - if (param.nProfileIndex == 0) { - ALOGW("component %s doesn't support profile query.", name); - } - } - - if (isVideo && !isEncoder) { - native_handle_t *sidebandHandle = nullptr; - if (omxNode->configureVideoTunnelMode( - kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) { - // tunneled playback includes adaptive playback - caps->addDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK, 1); - caps->addDetail(MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK, 1); - } else if (omxNode->setPortMode( - kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK || - omxNode->prepareForAdaptivePlayback( - kPortIndexOutput, OMX_TRUE, - 1280 /* width */, 720 /* height */) == OK) { - caps->addDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK, 1); - } - } - - if (isVideo && isEncoder) { - OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; - InitOMXParams(¶ms); - params.nPortIndex = kPortIndexOutput; - // TODO: should we verify if fallback is supported? - if (omxNode->getConfig( - (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, - ¶ms, sizeof(params)) == OK) { - caps->addDetail(MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH, 1); - } - } - - omxNode->freeNode(); - return OK; -} - -void buildOmxInfo(const MediaCodecsXmlParser& parser, - MediaCodecListWriter* writer) { - uint32_t omxRank = ::android::base::GetUintProperty( - "debug.stagefright.omx_default_rank", uint32_t(0x100)); - for (const MediaCodecsXmlParser::Codec& codec : parser.getCodecMap()) { - const std::string &name = codec.first; - if (!hasPrefix(codec.first, "OMX.")) { - continue; - } - const MediaCodecsXmlParser::CodecProperties &properties = codec.second; - bool encoder = properties.isEncoder; - std::unique_ptr<MediaCodecInfoWriter> info = - writer->addMediaCodecInfo(); - info->setName(name.c_str()); - info->setOwner("default"); - typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0; - if (encoder) { - attrs |= MediaCodecInfo::kFlagIsEncoder; - } - // NOTE: we don't support software-only codecs in OMX - if (!hasPrefix(name, "OMX.google.")) { - attrs |= MediaCodecInfo::kFlagIsVendor; - if (properties.quirkSet.find("attribute::software-codec") - == properties.quirkSet.end()) { - attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated; - } - } - info->setAttributes(attrs); - info->setRank(omxRank); - // OMX components don't have aliases - for (const MediaCodecsXmlParser::Type &type : properties.typeMap) { - const std::string &mediaType = type.first; - std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps = - info->addMediaType(mediaType.c_str()); - const MediaCodecsXmlParser::AttributeMap &attrMap = type.second; - for (const MediaCodecsXmlParser::Attribute& attr : attrMap) { - const std::string &key = attr.first; - const std::string &value = attr.second; - if (hasPrefix(key, "feature-") && - !hasPrefix(key, "feature-bitrate-modes")) { - caps->addDetail(key.c_str(), hasPrefix(value, "1") ? 1 : 0); - } else { - caps->addDetail(key.c_str(), value.c_str()); - } - } - status_t err = queryOmxCapabilities( - name.c_str(), - mediaType.c_str(), - encoder, - caps.get()); - if (err != OK) { - ALOGI("Failed to query capabilities for %s (media type: %s). Error: %d", - name.c_str(), - mediaType.c_str(), - static_cast<int>(err)); - } - } - } -} - -} // unnamed namespace - -status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) { - // TODO: Remove run-time configurations once all codecs are working - // properly. (Assume "full" behavior eventually.) - // - // debug.stagefright.ccodec supports 5 values. - // 0 - Only OMX components are available. - // 1 - Audio decoders and encoders with prefix "c2.android." are available - // and ranked first. - // All other components with prefix "c2.android." are available with - // their normal ranks. - // Components with prefix "c2.vda." are available with their normal - // ranks. - // All other components with suffix ".avc.decoder" or ".avc.encoder" - // are available but ranked last. - // 2 - Components with prefix "c2.android." are available and ranked - // first. - // Components with prefix "c2.vda." are available with their normal - // ranks. - // All other components with suffix ".avc.decoder" or ".avc.encoder" - // are available but ranked last. - // 3 - Components with prefix "c2.android." are available and ranked - // first. - // All other components are available with their normal ranks. - // 4 - All components are available with their normal ranks. - // - // The default value (boot time) is 1. - // - // Note: Currently, OMX components have default rank 0x100, while all - // Codec2.0 software components have default rank 0x200. - int option = ::android::base::GetIntProperty("debug.stagefright.ccodec", 1); - - // Obtain Codec2Client - std::vector<Traits> traits = Codec2Client::ListComponents(); - - MediaCodecsXmlParser parser; - if (option == 0) { - parser.parseXmlFilesInSearchDirs(); - } else { - parser.parseXmlFilesInSearchDirs( - { "media_codecs_c2.xml", "media_codecs_performance_c2.xml" }); - } - if (parser.getParsingStatus() != OK) { - ALOGD("XML parser no good"); - return OK; - } - - bool surfaceTest(Codec2Client::CreateInputSurface()); - if (option == 0 || (option != 4 && !surfaceTest)) { - buildOmxInfo(parser, writer); - } - - for (const Traits& trait : traits) { - C2Component::rank_t rank = trait.rank; - - std::shared_ptr<Codec2Client::Interface> intf = - Codec2Client::CreateInterfaceByName(trait.name.c_str()); - if (!intf || parser.getCodecMap().count(intf->getName()) == 0) { - ALOGD("%s not found in xml", trait.name.c_str()); - continue; - } - std::string canonName = intf->getName(); - - // TODO: Remove this block once all codecs are enabled by default. - switch (option) { - case 0: - continue; - case 1: - if (hasPrefix(canonName, "c2.vda.")) { - break; - } - if (hasPrefix(canonName, "c2.android.")) { - if (trait.domain == C2Component::DOMAIN_AUDIO) { - rank = 1; - break; - } - break; - } - if (hasSuffix(canonName, ".avc.decoder") || - hasSuffix(canonName, ".avc.encoder")) { - rank = std::numeric_limits<decltype(rank)>::max(); - break; - } - continue; - case 2: - if (hasPrefix(canonName, "c2.vda.")) { - break; - } - if (hasPrefix(canonName, "c2.android.")) { - rank = 1; - break; - } - if (hasSuffix(canonName, ".avc.decoder") || - hasSuffix(canonName, ".avc.encoder")) { - rank = std::numeric_limits<decltype(rank)>::max(); - break; - } - continue; - case 3: - if (hasPrefix(canonName, "c2.android.")) { - rank = 1; - } - break; - } - - ALOGV("canonName = %s", canonName.c_str()); - std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo(); - codecInfo->setName(trait.name.c_str()); - codecInfo->setOwner(("codec2::" + trait.owner).c_str()); - const MediaCodecsXmlParser::CodecProperties &codec = parser.getCodecMap().at(canonName); - - bool encoder = trait.kind == C2Component::KIND_ENCODER; - typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0; - - if (encoder) { - attrs |= MediaCodecInfo::kFlagIsEncoder; - } - if (trait.owner == "software") { - attrs |= MediaCodecInfo::kFlagIsSoftwareOnly; - } else { - attrs |= MediaCodecInfo::kFlagIsVendor; - if (trait.owner == "vendor-software") { - attrs |= MediaCodecInfo::kFlagIsSoftwareOnly; - } else if (codec.quirkSet.find("attribute::software-codec") == codec.quirkSet.end()) { - attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated; - } - } - codecInfo->setAttributes(attrs); - codecInfo->setRank(rank); - - for (const std::string &alias : codec.aliases) { - codecInfo->addAlias(alias.c_str()); - } - - 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->addMediaType(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()); - } - } - - bool gotProfileLevels = false; - if (intf) { - std::shared_ptr<C2Mapper::ProfileLevelMapper> mapper = - C2Mapper::GetProfileLevelMapper(trait.mediaType); - // if we don't know the media type, pass through all values unmapped - - // TODO: we cannot find levels that are local 'maxima' without knowing the coding - // e.g. H.263 level 45 and level 30 could be two values for highest level as - // they don't include one another. For now we use the last supported value. - C2StreamProfileLevelInfo pl(encoder /* output */, 0u); - std::vector<C2FieldSupportedValuesQuery> profileQuery = { - C2FieldSupportedValuesQuery::Possible(C2ParamField(&pl, &pl.profile)) - }; - - c2_status_t err = intf->querySupportedValues(profileQuery, C2_DONT_BLOCK); - ALOGV("query supported profiles -> %s | %s", - asString(err), asString(profileQuery[0].status)); - if (err == C2_OK && profileQuery[0].status == C2_OK) { - if (profileQuery[0].values.type == C2FieldSupportedValues::VALUES) { - std::vector<std::shared_ptr<C2ParamDescriptor>> supportedParams; - bool hdrSupported = false; - err = intf->querySupportedParams(&supportedParams); - if (err == C2_OK) { - for (const std::shared_ptr<C2ParamDescriptor> &desc : supportedParams) { - if (desc->index().coreIndex() == C2StreamHdrStaticInfo::CORE_INDEX) { - hdrSupported = true; - break; - } - } - } - ALOGV("HDR %ssupported", hdrSupported ? "" : "not "); - for (C2Value::Primitive profile : profileQuery[0].values.values) { - pl.profile = (C2Config::profile_t)profile.ref<uint32_t>(); - std::vector<std::unique_ptr<C2SettingResult>> failures; - err = intf->config({&pl}, C2_DONT_BLOCK, &failures); - ALOGV("set profile to %u -> %s", pl.profile, asString(err)); - std::vector<C2FieldSupportedValuesQuery> levelQuery = { - C2FieldSupportedValuesQuery::Current(C2ParamField(&pl, &pl.level)) - }; - err = intf->querySupportedValues(levelQuery, C2_DONT_BLOCK); - ALOGV("query supported levels -> %s | %s", - asString(err), asString(levelQuery[0].status)); - if (err == C2_OK && levelQuery[0].status == C2_OK) { - if (levelQuery[0].values.type == C2FieldSupportedValues::VALUES - && levelQuery[0].values.values.size() > 0) { - C2Value::Primitive level = levelQuery[0].values.values.back(); - pl.level = (C2Config::level_t)level.ref<uint32_t>(); - ALOGV("supporting level: %u", pl.level); - bool added = false; - int32_t sdkProfile, sdkLevel; - if (mapper && mapper->mapProfile(pl.profile, &sdkProfile) - && mapper->mapLevel(pl.level, &sdkLevel)) { - caps->addProfileLevel( - (uint32_t)sdkProfile, (uint32_t)sdkLevel); - gotProfileLevels = true; - added = true; - } else if (!mapper) { - sdkProfile = pl.profile; - sdkLevel = pl.level; - caps->addProfileLevel(pl.profile, pl.level); - gotProfileLevels = true; - added = true; - } - if (added && hdrSupported) { - static ALookup<int32_t, int32_t> sHdrProfileMap = { - { VP9Profile2, VP9Profile2HDR }, - { VP9Profile3, VP9Profile3HDR }, - }; - int32_t sdkHdrProfile; - if (sHdrProfileMap.lookup(sdkProfile, &sdkHdrProfile)) { - caps->addProfileLevel( - (uint32_t)sdkHdrProfile, (uint32_t)sdkLevel); - } - } - - // for H.263 also advertise the second highest level if the - // codec supports level 45, as level 45 only covers level 10 - // TODO: move this to some form of a setting so it does not - // have to be here - if (mediaType == MIMETYPE_VIDEO_H263) { - C2Config::level_t nextLevel = C2Config::LEVEL_UNUSED; - for (C2Value::Primitive v : levelQuery[0].values.values) { - C2Config::level_t level = - (C2Config::level_t)v.ref<uint32_t>(); - if (level < C2Config::LEVEL_H263_45 - && level > nextLevel) { - nextLevel = level; - } - } - if (nextLevel != C2Config::LEVEL_UNUSED - && nextLevel != pl.level - && mapper - && mapper->mapProfile(pl.profile, &sdkProfile) - && mapper->mapLevel(nextLevel, &sdkLevel)) { - caps->addProfileLevel( - (uint32_t)sdkProfile, (uint32_t)sdkLevel); - } - } - } - } - } - } - } - } - - if (!gotProfileLevels) { - if (mediaType == MIMETYPE_VIDEO_VP9) { - if (encoder) { - caps->addProfileLevel(VP9Profile0, VP9Level41); - } else { - caps->addProfileLevel(VP9Profile0, VP9Level5); - caps->addProfileLevel(VP9Profile2, VP9Level5); - caps->addProfileLevel(VP9Profile2HDR, VP9Level5); - } - } else if (mediaType == MIMETYPE_VIDEO_HEVC && !encoder) { - caps->addProfileLevel(HEVCProfileMain, HEVCMainTierLevel51); - caps->addProfileLevel(HEVCProfileMainStill, HEVCMainTierLevel51); - } else if (mediaType == MIMETYPE_VIDEO_VP8) { - if (encoder) { - caps->addProfileLevel(VP8ProfileMain, VP8Level_Version0); - } else { - caps->addProfileLevel(VP8ProfileMain, VP8Level_Version0); - } - } else if (mediaType == MIMETYPE_VIDEO_AVC) { - if (encoder) { - caps->addProfileLevel(AVCProfileBaseline, AVCLevel41); -// caps->addProfileLevel(AVCProfileConstrainedBaseline, AVCLevel41); - caps->addProfileLevel(AVCProfileMain, AVCLevel41); - } else { - caps->addProfileLevel(AVCProfileBaseline, AVCLevel52); - caps->addProfileLevel(AVCProfileConstrainedBaseline, AVCLevel52); - caps->addProfileLevel(AVCProfileMain, AVCLevel52); - caps->addProfileLevel(AVCProfileConstrainedHigh, AVCLevel52); - caps->addProfileLevel(AVCProfileHigh, AVCLevel52); - } - } else if (mediaType == MIMETYPE_VIDEO_MPEG4) { - if (encoder) { - caps->addProfileLevel(MPEG4ProfileSimple, MPEG4Level2); - } else { - caps->addProfileLevel(MPEG4ProfileSimple, MPEG4Level3); - } - } else if (mediaType == MIMETYPE_VIDEO_H263) { - if (encoder) { - caps->addProfileLevel(H263ProfileBaseline, H263Level45); - } else { - caps->addProfileLevel(H263ProfileBaseline, H263Level30); - caps->addProfileLevel(H263ProfileBaseline, H263Level45); - caps->addProfileLevel(H263ProfileISWV2, H263Level30); - caps->addProfileLevel(H263ProfileISWV2, H263Level45); - } - } else if (mediaType == MIMETYPE_VIDEO_MPEG2 && !encoder) { - caps->addProfileLevel(MPEG2ProfileSimple, MPEG2LevelHL); - caps->addProfileLevel(MPEG2ProfileMain, MPEG2LevelHL); - } - } - - // TODO: get this from intf() as well, but how do we map them to - // MediaCodec color formats? - if (mediaType.find("video") != std::string::npos) { - // vendor video codecs prefer opaque format - if (trait.name.find("android") == std::string::npos) { - caps->addColorFormat(COLOR_FormatSurface); - } - caps->addColorFormat(COLOR_FormatYUV420Flexible); - caps->addColorFormat(COLOR_FormatYUV420Planar); - caps->addColorFormat(COLOR_FormatYUV420SemiPlanar); - caps->addColorFormat(COLOR_FormatYUV420PackedPlanar); - caps->addColorFormat(COLOR_FormatYUV420PackedSemiPlanar); - // framework video encoders must support surface format, though it is unclear - // that they will be able to map it if it is opaque - if (encoder && trait.name.find("android") != std::string::npos) { - caps->addColorFormat(COLOR_FormatSurface); - } - } - } - } - return OK; -} - -} // namespace android - -extern "C" android::MediaCodecListBuilderBase *CreateBuilder() { - return new android::Codec2InfoBuilder; -} - diff --git a/media/sfplugin/Codec2InfoBuilder.h b/media/sfplugin/Codec2InfoBuilder.h deleted file mode 100644 index 30c189e..0000000 --- a/media/sfplugin/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/sfplugin/InputSurfaceWrapper.h b/media/sfplugin/InputSurfaceWrapper.h deleted file mode 100644 index d9c4eec..0000000 --- a/media/sfplugin/InputSurfaceWrapper.h +++ /dev/null @@ -1,107 +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_ - -#include <codec2/hidl/client.h> -#include <system/graphics.h> - -namespace android { - -/** - * Wrapper interface around InputSurface. - */ -class InputSurfaceWrapper { -public: - InputSurfaceWrapper() - : mDataSpace(HAL_DATASPACE_UNKNOWN) { - } - - virtual ~InputSurfaceWrapper() = default; - - /** - * Connect the surface with |comp|. 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<Codec2Client::Component> &comp) = 0; - - /** - * Disconnect the surface from the component if any. - */ - virtual void disconnect() = 0; - - /** - * Start pushing buffers to the surface. - */ - virtual status_t start() = 0; - - /** - * Ref: GraphicBufferSource::signalEndOfInputStream. - */ - virtual status_t signalEndOfInputStream() = 0; - - /// Input Surface configuration - struct Config { - // IN PARAMS (GBS) - float mMinFps; // minimum fps (repeat frame to achieve this) - float mMaxFps; // max fps (via frame drop) - float mCaptureFps; // capture fps - float mCodedFps; // coded fps - bool mSuspended; // suspended - int64_t mTimeOffsetUs; // time offset (input => codec) - int64_t mSuspendAtUs; // suspend/resume time - int64_t mStartAtUs; // start time - bool mStopped; // stopped - int64_t mStopAtUs; // stop time - - // OUT PARAMS (GBS) - int64_t mInputDelayUs; // delay between encoder input and surface input - - // IN PARAMS (CODEC WRAPPER) - float mFixedAdjustedFps; // fixed fps via PTS manipulation - float mMinAdjustedFps; // minimum fps via PTS manipulation - }; - - /** - * Configures input surface. - * - * \param config configuration. This can be updated during this call to provide output - * parameters, but not to provide configured parameters (to avoid continually - * reconfiguring) - */ - virtual status_t configure(Config &config) = 0; - - /** - * Configures desired data space. - * - * \param dataSpace desired data space - */ - inline void setDataSpace(android_dataspace dataSpace) { - mDataSpace = dataSpace; - } - -protected: - android_dataspace mDataSpace; -}; - -} // namespace android - -#endif // INPUT_SURFACE_WRAPPER_H_ diff --git a/media/sfplugin/ReflectedParamUpdater.cpp b/media/sfplugin/ReflectedParamUpdater.cpp deleted file mode 100644 index 880d4a5..0000000 --- a/media/sfplugin/ReflectedParamUpdater.cpp +++ /dev/null @@ -1,575 +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 "ReflectedParamUpdater" -#include <utils/Log.h> - -#include <iostream> -#include <set> -#include <sstream> - -#include <C2Debug.h> -#include <C2ParamInternal.h> - -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AString.h> -#include <media/stagefright/foundation/hexdump.h> - -#include "ReflectedParamUpdater.h" - -namespace android { - -std::string ReflectedParamUpdater::Dict::debugString(size_t indent_) const { - std::string indent(indent_, ' '); - std::stringstream s; - s << "Dict {" << std::endl; - - for (const auto &it : *this) { - s << indent << " "; - - C2Value c2Value; - int32_t int32Value; - uint32_t uint32Value; - int64_t int64Value; - uint64_t uint64Value; - float floatValue; - sp<ABuffer> bufValue; - AString strValue; - if (it.second.find(&c2Value)) { - switch (c2Value.type()) { - case C2Value::INT32: - (void)c2Value.get(&int32Value); - s << "c2::i32 " << it.first << " = " << int32Value; - break; - case C2Value::UINT32: - (void)c2Value.get(&uint32Value); - s << "c2::u32 " << it.first << " = " << uint32Value; - break; - case C2Value::CNTR32: - // dump counter value as unsigned - (void)c2Value.get((c2_cntr32_t*)&uint32Value); - s << "c2::c32 " << it.first << " = " << uint32Value; - break; - case C2Value::INT64: - (void)c2Value.get(&int64Value); - s << "c2::i64 " << it.first << " = " << int64Value; - break; - case C2Value::UINT64: - (void)c2Value.get(&uint64Value); - s << "c2::u64 " << it.first << " = " << uint64Value; - break; - case C2Value::CNTR64: - // dump counter value as unsigned - (void)c2Value.get((c2_cntr64_t*)&uint64Value); - s << "c2::c64 " << it.first << " = " << uint64Value; - break; - case C2Value::FLOAT: - (void)c2Value.get(&floatValue); - s << "c2::float " << it.first << " = " << floatValue; - break; - default: - // dump unsupported values for debugging, these should not be used - s << "c2::unsupported " << it.first; - } - } else if (it.second.find(&int32Value)) { - s << "int32_t " << it.first << " = " << int32Value; - } else if (it.second.find(&int64Value)) { - s << "int64_t " << it.first << " = " << int64Value; - } else if (it.second.find(&strValue)) { - s << "string " << it.first << " = \"" << strValue.c_str() << "\""; - } else if (it.second.find(&bufValue)) { - s << "Buffer " << it.first << " = "; - if (bufValue != nullptr && bufValue->data() != nullptr && bufValue->size() <= 64) { - s << "{" << std::endl; - AString tmp; - hexdump(bufValue->data(), bufValue->size(), indent_ + 4, &tmp); - s << tmp.c_str() << indent << " }"; - } else { - s << (void*)bufValue.get(); - } - } else { - // dump unsupported values for debugging, this should never happen. - s << "unsupported " << it.first; - } - s << std::endl; - } - s << indent << "}"; - - return s.str(); -} - -void ReflectedParamUpdater::addParamDesc( - const std::shared_ptr<C2ParamReflector> &reflector, - const std::vector<std::shared_ptr<C2ParamDescriptor>> ¶mDescs) { - for (const std::shared_ptr<C2ParamDescriptor> &desc : paramDescs) { - std::unique_ptr<C2StructDescriptor> structDesc = reflector->describe( - desc->index().coreIndex()); - if (structDesc == nullptr) { - ALOGD("Could not describe %s", desc->name().c_str()); - continue; - } - addParamDesc(desc, *structDesc, reflector, true /* markVendor */); - } - - // TEMP: also add vendor parameters as non-vendor - for (const std::shared_ptr<C2ParamDescriptor> &desc : paramDescs) { - if (!desc->index().isVendor()) { - continue; - } - std::unique_ptr<C2StructDescriptor> structDesc = reflector->describe( - desc->index().coreIndex()); - if (structDesc) { - addParamDesc(desc, *structDesc, reflector, false /* markVendor */); - } - } -} - -void ReflectedParamUpdater::addParamStructDesc( - std::shared_ptr<C2ParamDescriptor> desc, - C2String path, - size_t offset, - const C2StructDescriptor &structDesc, - const std::shared_ptr<C2ParamReflector> &reflector) { - for (auto it = structDesc.begin(); it != structDesc.end(); ++it) { - C2String fieldName = path + "." + it->name(); - if (it->type() & C2FieldDescriptor::STRUCT_FLAG) { - if (reflector == nullptr || it->extent() != 1) { - ALOGD("ignored struct field %s", fieldName.c_str()); - continue; - } - std::unique_ptr<C2StructDescriptor> structDesc_ = reflector->describe( - C2Param::CoreIndex(it->type()).coreIndex()); - if (structDesc_ == nullptr) { - ALOGD("Could not describe structure of %s", fieldName.c_str()); - continue; - } - addParamStructDesc(desc, fieldName, offset + _C2ParamInspector::GetOffset(*it), - *structDesc_, reflector); - continue; - } - - // verify extent and type - switch (it->type()) { - case C2FieldDescriptor::INT32: - case C2FieldDescriptor::UINT32: - case C2FieldDescriptor::CNTR32: - case C2FieldDescriptor::INT64: - case C2FieldDescriptor::UINT64: - case C2FieldDescriptor::CNTR64: - case C2FieldDescriptor::FLOAT: - if (it->extent() != 1) { - ALOGD("extent() != 1 for single value type: %s", fieldName.c_str()); - continue; - } - break; - case C2FieldDescriptor::STRING: - case C2FieldDescriptor::BLOB: - break; - - default: - ALOGD("Unrecognized type: %s", fieldName.c_str()); - continue; - } - - ALOGV("%s registered", fieldName.c_str()); - // TODO: get the proper size by iterating through the fields. - // only insert fields the very first time - mMap.emplace(fieldName, FieldDesc { - desc, - std::make_unique<C2FieldDescriptor>( - it->type(), it->extent(), it->name(), - _C2ParamInspector::GetOffset(*it), - _C2ParamInspector::GetSize(*it)), - offset, - }); - } -} - -void ReflectedParamUpdater::addParamDesc( - std::shared_ptr<C2ParamDescriptor> desc, const C2StructDescriptor &structDesc, - const std::shared_ptr<C2ParamReflector> &reflector, bool markVendor) { - C2String paramName = desc->name(); - - // prefix vendor parameters - if (desc->index().isVendor() && markVendor) { - paramName = "vendor." + paramName; - } - mParamNames.emplace(desc->index(), paramName); - - // also allow setting whole parameters in a binary fashion via ByteBuffer - // this is opt-in for now - auto it = mWholeParams.find(paramName); - if (it != mWholeParams.end() && it->second.coreIndex() == desc->index().coreIndex()) { - mMap.emplace(paramName, FieldDesc{ desc, nullptr, 0 /* offset */ }); - // don't add fields of whole parameters. - return; - } - - addParamStructDesc(desc, paramName, 0 /* offset */, structDesc, reflector); -} - -void ReflectedParamUpdater::supportWholeParam(std::string name, C2Param::CoreIndex index) { - mWholeParams.emplace(name, index); -} - -std::string ReflectedParamUpdater::getParamName(C2Param::Index index) const { - auto it = mParamNames.find(index); - if (it != mParamNames.end()) { - return it->second; - } - - std::stringstream ret; - ret << "<unknown " << index << ">"; - return ret.str(); -} - -void ReflectedParamUpdater::getParamIndicesFromMessage( - const Dict ¶ms, - std::vector<C2Param::Index> *vec /* nonnull */) const { - CHECK(vec != nullptr); - vec->clear(); - std::set<C2Param::Index> indices; - parseMessageAndDoWork( - params, - [&indices](const std::string &, const FieldDesc &desc, const void *, size_t) { - indices.insert(desc.paramDesc->index()); - }); - for (const C2Param::Index &index : indices) { - vec->push_back(index); - } -} - -void ReflectedParamUpdater::getParamIndicesForKeys( - const std::vector<std::string> &keys, - std::vector<C2Param::Index> *vec /* nonnull */) const { - CHECK(vec != nullptr); - vec->clear(); - std::set<C2Param::Index> indices; - - std::set<std::string> keyMap(keys.begin(), keys.end()); - - ALOGV("in getParamIndicesForKeys with %zu keys and map of %zu entries", - keyMap.size(), mMap.size()); - for (const std::pair<const std::string, FieldDesc> &kv : mMap) { - const std::string &name = kv.first; - const FieldDesc &desc = kv.second; - ALOGV("count of %s is %zu", name.c_str(), keyMap.count(name)); - if (keyMap.count(name) > 0) { - indices.insert(desc.paramDesc->index()); - } - } - - for (const C2Param::Index &index : indices) { - vec->push_back(index); - } -} - -void ReflectedParamUpdater::updateParamsFromMessage( - const Dict ¶ms, - std::vector<std::unique_ptr<C2Param>> *vec /* nonnull */) const { - CHECK(vec != nullptr); - - std::map<C2Param::Index, std::unique_ptr<C2Param>*> paramsMap; - for (std::unique_ptr<C2Param> ¶m : *vec) { - if (param && *param) { - paramsMap[param->index()] = ¶m; - } - } - - parseMessageAndDoWork( - params, - [¶msMap](const std::string &name, const FieldDesc &desc, const void *ptr, size_t size) { - std::unique_ptr<C2Param> *param = nullptr; - auto paramIt = paramsMap.find(desc.paramDesc->index()); - if (paramIt == paramsMap.end()) { - ALOGD("%s found, but param #%d isn't present to update", - name.c_str(), (int32_t)desc.paramDesc->index()); - return; - } - param = paramIt->second; - - struct _C2Param : public C2Param { - using C2Param::C2Param; - _C2Param(uint32_t size, uint32_t index) : C2Param(size, index) { } - }; - - // we will handle whole param updates as part of a flexible param update using - // a zero offset. - size_t offset = 0; - size_t minOffset = 0; - - // if this descriptor has a field, use the offset and size and ensure that offset - // is not part of the header - if (desc.fieldDesc) { - minOffset = sizeof(C2Param); - offset = sizeof(C2Param) + desc.offset - + _C2ParamInspector::GetOffset(*desc.fieldDesc); - } - - // reallocate or trim flexible param (or whole param) as necessary - if (!desc.fieldDesc /* whole param */ || desc.fieldDesc->extent() == 0) { - // reallocate param if more space is needed - if (param->get()->size() < offset + size) { - if (size > INT32_MAX - offset || offset < minOffset) { - // size too long or offset too early - abandon - return; - } - C2Param *newParam = (C2Param *)::operator new(offset + size); - new (newParam) _C2Param(offset + size, param->get()->index()); - if (offset > sizeof(C2Param)) { - memcpy(newParam + 1, param->get() + 1, offset - sizeof(C2Param)); - } - param->reset(newParam); - } else if (param->get()->size() > offset + size) { - // trim parameter size - _C2ParamInspector::TrimParam(param->get(), offset + size); - } - } else if (desc.fieldDesc->type() == C2FieldDescriptor::BLOB) { - // zero fill blobs if updating with smaller blob - if (desc.fieldDesc->extent() > size) { - memset((uint8_t *)(param->get()) + offset + size, 0, - desc.fieldDesc->extent() - size); - } - } - - memcpy((uint8_t *)(param->get()) + offset, ptr, size); - }); -} - -void ReflectedParamUpdater::parseMessageAndDoWork( - const Dict ¶ms, - std::function<void(const std::string &, const FieldDesc &, const void *, size_t)> work) const { - for (const std::pair<const std::string, FieldDesc> &kv : mMap) { - const std::string &name = kv.first; - const FieldDesc &desc = kv.second; - auto param = params.find(name); - if (param == params.end()) { - continue; - } - - // handle whole parameters - if (!desc.fieldDesc) { - sp<ABuffer> tmp; - if (param->second.find(&tmp) && tmp != nullptr) { - C2Param *tmpAsParam = C2Param::From(tmp->data(), tmp->size()); - if (tmpAsParam && tmpAsParam->type().type() == desc.paramDesc->index().type()) { - work(name, desc, tmp->data(), tmp->size()); - } else { - ALOGD("Param blob does not match param for '%s' (%p, %x vs %x)", - name.c_str(), tmpAsParam, tmpAsParam ? tmpAsParam->type().type() : 0xDEADu, - desc.paramDesc->index().type()); - } - } - continue; - } - - int32_t int32Value; - int64_t int64Value; - C2Value c2Value; - - C2FieldDescriptor::type_t fieldType = desc.fieldDesc->type(); - size_t fieldExtent = desc.fieldDesc->extent(); - switch (fieldType) { - case C2FieldDescriptor::INT32: - if ((param->second.find(&c2Value) && c2Value.get(&int32Value)) - || param->second.find(&int32Value)) { - work(name, desc, &int32Value, sizeof(int32Value)); - } - break; - case C2FieldDescriptor::UINT32: - if ((param->second.find(&c2Value) && c2Value.get((uint32_t*)&int32Value)) - || param->second.find(&int32Value)) { - work(name, desc, &int32Value, sizeof(int32Value)); - } - break; - case C2FieldDescriptor::CNTR32: - if ((param->second.find(&c2Value) && c2Value.get((c2_cntr32_t*)&int32Value)) - || param->second.find(&int32Value)) { - work(name, desc, &int32Value, sizeof(int32Value)); - } - break; - case C2FieldDescriptor::INT64: - if ((param->second.find(&c2Value) && c2Value.get(&int64Value)) - || param->second.find(&int64Value)) { - work(name, desc, &int64Value, sizeof(int64Value)); - } - break; - case C2FieldDescriptor::UINT64: - if ((param->second.find(&c2Value) && c2Value.get((uint64_t*)&int64Value)) - || param->second.find(&int64Value)) { - work(name, desc, &int64Value, sizeof(int64Value)); - } - break; - case C2FieldDescriptor::CNTR64: - if ((param->second.find(&c2Value) && c2Value.get((c2_cntr64_t*)&int64Value)) - || param->second.find(&int64Value)) { - work(name, desc, &int64Value, sizeof(int64Value)); - } - break; - case C2FieldDescriptor::FLOAT: { - float tmp; - if (param->second.find(&c2Value) && c2Value.get(&tmp)) { - work(name, desc, &tmp, sizeof(tmp)); - } - break; - } - case C2FieldDescriptor::STRING: { - AString tmp; - if (!param->second.find(&tmp)) { - break; - } - if (fieldExtent > 0 && tmp.size() >= fieldExtent) { - AString truncated(tmp, 0, fieldExtent - 1); - ALOGD("String value too long to fit: original \"%s\" truncated to \"%s\"", - tmp.c_str(), truncated.c_str()); - tmp = truncated; - } - work(name, desc, tmp.c_str(), tmp.size() + 1); - break; - } - - case C2FieldDescriptor::BLOB: { - sp<ABuffer> tmp; - if (!param->second.find(&tmp) || tmp == nullptr) { - break; - } - - if (fieldExtent > 0 && tmp->size() > fieldExtent) { - ALOGD("Blob value too long to fit. Truncating."); - tmp->setRange(tmp->offset(), fieldExtent); - } - work(name, desc, tmp->data(), tmp->size()); - break; - } - - default: - ALOGD("Unsupported data type for %s", name.c_str()); - break; - } - } -} - -ReflectedParamUpdater::Dict -ReflectedParamUpdater::getParams(const std::vector<std::unique_ptr<C2Param>> ¶ms_) const { - std::vector<C2Param*> params; - params.resize(params_.size()); - std::transform(params_.begin(), params_.end(), params.begin(), - [](const std::unique_ptr<C2Param>& p) -> C2Param* { return p.get(); }); - return getParams(params); -} - -ReflectedParamUpdater::Dict -ReflectedParamUpdater::getParams(const std::vector<C2Param*> ¶ms) const { - Dict ret; - - // convert vector to map - std::map<C2Param::Index, C2Param *> paramsMap; - for (C2Param *param : params) { - if (param != nullptr && *param) { - paramsMap[param->index()] = param; - } - } - - for (const std::pair<const std::string, FieldDesc> &kv : mMap) { - const std::string &name = kv.first; - const FieldDesc &desc = kv.second; - if (paramsMap.count(desc.paramDesc->index()) == 0) { - continue; - } - C2Param *param = paramsMap[desc.paramDesc->index()]; - Value value; - - // handle whole params first - if (!desc.fieldDesc) { - sp<ABuffer> buf = ABuffer::CreateAsCopy(param, param->size()); - value.set(buf); - ret.emplace(name, value); - continue; - } - - size_t offset = sizeof(C2Param) + desc.offset - + _C2ParamInspector::GetOffset(*desc.fieldDesc); - uint8_t *data = (uint8_t *)param + offset; - C2FieldDescriptor::type_t fieldType = desc.fieldDesc->type(); - switch (fieldType) { - case C2FieldDescriptor::STRING: { - size_t length = desc.fieldDesc->extent(); - if (length == 0) { - length = param->size() - offset; - } - - if (param->size() < length || param->size() - length < offset) { - ALOGD("param too small for string: length %zu size %zu offset %zu", - length, param->size(), offset); - break; - } - value.set(AString((char *)data, strnlen((char *)data, length))); - break; - } - - case C2FieldDescriptor::BLOB: { - size_t length = desc.fieldDesc->extent(); - if (length == 0) { - length = param->size() - offset; - } - - if (param->size() < length || param->size() - length < offset) { - ALOGD("param too small for blob: length %zu size %zu offset %zu", - length, param->size(), offset); - break; - } - - sp<ABuffer> buf = ABuffer::CreateAsCopy(data, length); - value.set(buf); - break; - } - - default: { - size_t valueSize = C2Value::SizeFor((C2Value::type_t)fieldType); - if (param->size() < valueSize || param->size() - valueSize < offset) { - ALOGD("param too small for c2value: size %zu offset %zu", - param->size(), offset); - break; - } - - C2Value c2Value; - switch (fieldType) { - case C2FieldDescriptor::INT32: c2Value = *((int32_t *)data); break; - case C2FieldDescriptor::UINT32: c2Value = *((uint32_t *)data); break; - case C2FieldDescriptor::CNTR32: c2Value = *((c2_cntr32_t *)data); break; - case C2FieldDescriptor::INT64: c2Value = *((int64_t *)data); break; - case C2FieldDescriptor::UINT64: c2Value = *((uint64_t *)data); break; - case C2FieldDescriptor::CNTR64: c2Value = *((c2_cntr64_t *)data); break; - case C2FieldDescriptor::FLOAT: c2Value = *((float *)data); break; - default: - ALOGD("Unsupported data type for %s", name.c_str()); - continue; - } - value.set(c2Value); - } - } - ret.emplace(name, value); - } - return ret; -} - -void ReflectedParamUpdater::clear() { - mMap.clear(); -} - -} // namespace android diff --git a/media/sfplugin/ReflectedParamUpdater.h b/media/sfplugin/ReflectedParamUpdater.h deleted file mode 100644 index 5436ba5..0000000 --- a/media/sfplugin/ReflectedParamUpdater.h +++ /dev/null @@ -1,214 +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 REFLECTED_PARAM_BUILDER_H_ -#define REFLECTED_PARAM_BUILDER_H_ - -#include <map> -#include <memory> - -#include <C2.h> -#include <C2Param.h> - -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/AData.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/foundation/AString.h> - -namespace android { - -/** - * Utility class to query and update Codec 2.0 configuration values. Use custom dictionary as - * AMessage cannot represent all types of Codec 2.0 parameters and C2Value cannot represent - * all types of SDK values. We want to be precise when setting standard parameters (use C2Value - * for arithmetic values), but also support int32 and int64 for SDK values specifically for - * vendor parameters (as SDK API does not allow specifying proper type.) When querying fields, - * we can use C2Values as they are defined. - * - * Item => Codec 2.0 value mappings: - * CValue::type => type - * int32 => int32, ctr32 or uint32 - * int64 => int64, ctr64 or uint64 - * AString => string - * ABuffer => blob - * 'Rect' => C2RectStruct (not exposed in SDK as a rectangle) - */ -class ReflectedParamUpdater { -public: - ReflectedParamUpdater() = default; - ~ReflectedParamUpdater() = default; - - /** - * Element for values - */ - struct Value : public AData<C2Value, int32_t, int64_t, AString, sp<ABuffer>>::Basic { - // allow construction from base types - Value() = default; - explicit Value(C2Value i) { set(i); } - explicit Value(int32_t i) { set(i); } - explicit Value(int64_t i) { set(i); } - explicit Value(const AString &i) { set(i); } - explicit Value(const sp<ABuffer> &i) { set(i); } - }; - - struct Dict : public std::map<std::string, Value> { - Dict() = default; - std::string debugString(size_t indent = 0) const; - }; - - /** - * Enumerates all fields of the parameter descriptors supplied, so that this opbject can later - * query and update these. - * - * For now only first-level fields are supported. Also, array fields are not supported. - * - * \param reflector C2ParamReflector object for C2Param reflection. - * \param paramDescs vector of C2ParamDescriptor objects that this object - * would recognize when building params. - */ - void addParamDesc( - const std::shared_ptr<C2ParamReflector> &reflector, - const std::vector<std::shared_ptr<C2ParamDescriptor>> ¶mDescs); - - /** - * Adds fields of a standard parameter (that may not be supported by the parameter reflector - * or may not be listed as a supported value by the component). If the parameter name is - * used for another parameter, this operation is a no-op. (Technically, this is by fields). - * - * \param T standard parameter type - * \param name parameter name - */ - template<typename T> - void addStandardParam(const std::string &name, C2ParamDescriptor::attrib_t attrib = - C2ParamDescriptor::IS_READ_ONLY) { - addParamDesc(std::make_shared<C2ParamDescriptor>( - C2Param::Index(T::PARAM_TYPE), attrib, name.c_str()), - C2StructDescriptor((T*)nullptr), nullptr /* descriptor */); - } - - /** - * Adds fields of a structure (or a parameater) described by the struct descriptor. If - * reflector is provided, fields of sub-structures are also added. Otherwise, only top-level - * fundamental typed fields (arithmetic, string and blob) are added. - * - * \param paramDesc parameter descriptor - * \param fieldDesc field descriptor - * \param path path/name of the structure (field or parent parameter) - * \param offset offset of the structure in the parameter - * \param reflector C2ParamReflector object for C2Param reflection (may be null) - */ - void addParamStructDesc( - std::shared_ptr<C2ParamDescriptor> paramDesc, C2String path, size_t offset, - const C2StructDescriptor &structDesc, - const std::shared_ptr<C2ParamReflector> &reflector); - - /** - * Adds fields of a parameter described by the struct descriptor. If reflector is provided, - * fields of sub-structures are also added. Otherwise, only top-level fundamental typed fields - * (arithmetic, string and blob) are added. - * - * \param paramDesc parameter descriptor - * \param fieldDesc field descriptor - * \param reflector C2ParamReflector object for C2Param reflection (may be null) - * \param markVendor TEMP if true, prefix vendor parameter names with "vendor." - */ - void addParamDesc( - std::shared_ptr<C2ParamDescriptor> paramDesc, const C2StructDescriptor &structDesc, - const std::shared_ptr<C2ParamReflector> &reflector, - bool markVendor = true); - - /** - * Add support for setting a parameter as a binary blob. - * - * \param name name of the parameter - * \param coreIndex parameter (core) index - */ - void supportWholeParam(std::string name, C2Param::CoreIndex coreIndex); - - /** - * Returns the name of the parameter for an index. - */ - std::string getParamName(C2Param::Index index) const; - - /** - * Get list of param indices from field names and values in AMessage object. - * - * TODO: This should be in the order that they are listed by the component. - * - * \param params[in] Dict object with field name to value pairs. - * \param vec[out] vector to store the indices from |params|. - */ - void getParamIndicesFromMessage( - const Dict ¶ms, - std::vector<C2Param::Index> *vec /* nonnull */) const; - - /** - * Get list of param indices from field names (only) in AMessage object. - * - * \param params[in] Vector object with field names. - * \param vec[out] vector to store the indices from |params|. - */ - void getParamIndicesForKeys( - const std::vector<std::string> &keys, - std::vector<C2Param::Index> *vec /* nonnull */) const; - - /** - * Update C2Param objects from field name and value in AMessage object. - * - * \param params[in] Dict object with field name to value pairs. - * \param vec[in,out] vector of the C2Param objects to be updated. - */ - void updateParamsFromMessage( - const Dict ¶ms, - std::vector<std::unique_ptr<C2Param>> *vec /* nonnull */) const; - - /** - * Get fields from C2Param objects in AMessage object. - * - * \param params[in] vector of the C2Param objects to be queried - * \return a Dict object containing the known parameters - */ - Dict getParams( - const std::vector<C2Param*> ¶ms /* nonnull */) const; - - Dict getParams( - const std::vector<std::unique_ptr<C2Param>> ¶ms /* nonnull */) const; - - /** - * Clear param descriptors in this object. - */ - void clear(); - -private: - struct FieldDesc { - std::shared_ptr<C2ParamDescriptor> paramDesc; - std::unique_ptr<C2FieldDescriptor> fieldDesc; - size_t offset; - }; - std::map<std::string, FieldDesc> mMap; - std::map<C2Param::Index, std::string> mParamNames; - std::map<std::string, C2Param::CoreIndex> mWholeParams; - - void parseMessageAndDoWork( - const Dict ¶ms, - std::function<void(const std::string &, const FieldDesc &, const void *, size_t)> work) const; - - C2_DO_NOT_COPY(ReflectedParamUpdater); -}; - -} // namespace android - -#endif // REFLECTED_PARAM_BUILDER_H_ diff --git a/media/sfplugin/SkipCutBuffer.cpp b/media/sfplugin/SkipCutBuffer.cpp deleted file mode 100644 index 5762440..0000000 --- a/media/sfplugin/SkipCutBuffer.cpp +++ /dev/null @@ -1,206 +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 "SkipCutBuffer" -#include <utils/Log.h> - -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/SkipCutBuffer.h> - -namespace android { - -SkipCutBuffer::SkipCutBuffer(size_t skip, size_t cut, size_t num16BitChannels) { - - mWriteHead = 0; - mReadHead = 0; - mCapacity = 0; - mCutBuffer = nullptr; - - if (num16BitChannels == 0 || num16BitChannels > INT32_MAX / 2) { - ALOGW("# channels out of range: %zu, using passthrough instead", num16BitChannels); - return; - } - size_t frameSize = num16BitChannels * 2; - if (skip > INT32_MAX / frameSize || cut > INT32_MAX / frameSize - || cut * frameSize > INT32_MAX - 4096) { - ALOGW("out of range skip/cut: %zu/%zu, using passthrough instead", - skip, cut); - return; - } - skip *= frameSize; - cut *= frameSize; - - mFrontPadding = mSkip = skip; - mBackPadding = cut; - mCapacity = cut + 4096; - mCutBuffer = new (std::nothrow) char[mCapacity]; - ALOGV("skipcutbuffer %zu %zu %d", skip, cut, mCapacity); -} - -SkipCutBuffer::~SkipCutBuffer() { - delete[] mCutBuffer; -} - -void SkipCutBuffer::submit(MediaBuffer *buffer) { - if (mCutBuffer == nullptr) { - // passthrough mode - return; - } - - int32_t offset = buffer->range_offset(); - int32_t buflen = buffer->range_length(); - - // drop the initial data from the buffer if needed - if (mFrontPadding > 0) { - // still data left to drop - int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding; - offset += to_drop; - buflen -= to_drop; - buffer->set_range(offset, buflen); - mFrontPadding -= to_drop; - } - - - // append data to cutbuffer - char *src = ((char*) buffer->data()) + offset; - write(src, buflen); - - - // the mediabuffer is now empty. Fill it from cutbuffer, always leaving - // at least mBackPadding bytes in the cutbuffer - char *dst = (char*) buffer->data(); - size_t copied = read(dst, buffer->size()); - buffer->set_range(0, copied); -} - -template <typename T> -void SkipCutBuffer::submitInternal(const sp<T>& buffer) { - if (mCutBuffer == nullptr) { - // passthrough mode - return; - } - - int32_t offset = buffer->offset(); - int32_t buflen = buffer->size(); - - // drop the initial data from the buffer if needed - if (mFrontPadding > 0) { - // still data left to drop - int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding; - offset += to_drop; - buflen -= to_drop; - buffer->setRange(offset, buflen); - mFrontPadding -= to_drop; - } - - - // append data to cutbuffer - char *src = (char*) buffer->data(); - write(src, buflen); - - - // the mediabuffer is now empty. Fill it from cutbuffer, always leaving - // at least mBackPadding bytes in the cutbuffer - char *dst = (char*) buffer->base(); - size_t copied = read(dst, buffer->capacity()); - buffer->setRange(0, copied); -} - -void SkipCutBuffer::submit(const sp<ABuffer>& buffer) { - submitInternal(buffer); -} - -void SkipCutBuffer::submit(const sp<MediaCodecBuffer>& buffer) { - submitInternal(buffer); -} - -void SkipCutBuffer::clear() { - mWriteHead = mReadHead = 0; - mFrontPadding = mSkip; -} - -void SkipCutBuffer::write(const char *src, size_t num) { - int32_t sizeused = (mWriteHead - mReadHead); - if (sizeused < 0) sizeused += mCapacity; - - // Everything must fit. Make sure the buffer is a little larger than needed, - // so there is no ambiguity as to whether mWriteHead == mReadHead means buffer - // full or empty - size_t available = mCapacity - sizeused - 32; - if (available < num) { - int32_t newcapacity = mCapacity + (num - available); - char * newbuffer = new char[newcapacity]; - memcpy(newbuffer, mCutBuffer, mCapacity); - delete [] mCutBuffer; - mCapacity = newcapacity; - mCutBuffer = newbuffer; - ALOGV("reallocated buffer at size %d", newcapacity); - } - - size_t copyfirst = (mCapacity - mWriteHead); - if (copyfirst > num) copyfirst = num; - if (copyfirst) { - memcpy(mCutBuffer + mWriteHead, src, copyfirst); - num -= copyfirst; - src += copyfirst; - mWriteHead += copyfirst; - CHECK_LE(mWriteHead, mCapacity); - if (mWriteHead == mCapacity) mWriteHead = 0; - if (num) { - memcpy(mCutBuffer, src, num); - mWriteHead += num; - } - } -} - -size_t SkipCutBuffer::read(char *dst, size_t num) { - int32_t available = (mWriteHead - mReadHead); - if (available < 0) available += mCapacity; - - available -= mBackPadding; - if (available <=0) { - return 0; - } - if (available < int32_t(num)) { - num = available; - } - - size_t copyfirst = (mCapacity - mReadHead); - if (copyfirst > num) copyfirst = num; - if (copyfirst) { - memcpy(dst, mCutBuffer + mReadHead, copyfirst); - num -= copyfirst; - dst += copyfirst; - mReadHead += copyfirst; - CHECK_LE(mReadHead, mCapacity); - if (mReadHead == mCapacity) mReadHead = 0; - if (num) { - memcpy(dst, mCutBuffer, num); - mReadHead += num; - } - } - return available; -} - -size_t SkipCutBuffer::size() { - int32_t available = (mWriteHead - mReadHead); - if (available < 0) available += mCapacity; - return available; -} - -} // namespace android diff --git a/media/sfplugin/SkipCutBuffer.h b/media/sfplugin/SkipCutBuffer.h deleted file mode 100644 index 0fb5690..0000000 --- a/media/sfplugin/SkipCutBuffer.h +++ /dev/null @@ -1,67 +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. - */ - -#ifndef SKIP_CUT_BUFFER_H_ - -#define SKIP_CUT_BUFFER_H_ - -#include <media/MediaCodecBuffer.h> -#include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/foundation/ABuffer.h> - -namespace android { - -/** - * utility class to cut the start and end off a stream of data in MediaBuffers - * - */ -class SkipCutBuffer: public RefBase { - public: - // 'skip' is the number of frames to skip from the beginning - // 'cut' is the number of frames to cut from the end - // 'num16BitChannels' is the number of channels, which are assumed to be 16 bit wide each - SkipCutBuffer(size_t skip, size_t cut, size_t num16Channels); - - // Submit one MediaBuffer for skipping and cutting. This may consume all or - // some of the data in the buffer, or it may add data to it. - // After this, the caller should continue processing the buffer as usual. - void submit(MediaBuffer *buffer); - void submit(const sp<ABuffer>& buffer); // same as above, but with an ABuffer - void submit(const sp<MediaCodecBuffer>& buffer); // same as above, but with an ABuffer - void clear(); - size_t size(); // how many bytes are currently stored in the buffer - - protected: - virtual ~SkipCutBuffer(); - - private: - void write(const char *src, size_t num); - size_t read(char *dst, size_t num); - template <typename T> - void submitInternal(const sp<T>& buffer); - int32_t mSkip; - int32_t mFrontPadding; - int32_t mBackPadding; - int32_t mWriteHead; - int32_t mReadHead; - int32_t mCapacity; - char* mCutBuffer; - DISALLOW_EVIL_CONSTRUCTORS(SkipCutBuffer); -}; - -} // namespace android - -#endif // OMX_CODEC_H_ diff --git a/media/sfplugin/tests/Android.bp b/media/sfplugin/tests/Android.bp deleted file mode 100644 index 8a6992f..0000000 --- a/media/sfplugin/tests/Android.bp +++ /dev/null @@ -1,56 +0,0 @@ -cc_test { - name: "ccodec_test", - - srcs: [ - "ReflectedParamUpdater_test.cpp", - ], - - include_dirs: [ - "hardware/google/av/media/sfplugin", - ], - - shared_libs: [ - "libstagefright_ccodec", - "libstagefright_codec2", - "libstagefright_foundation", - "libutils", - ], - - cflags: [ - "-Werror", - "-Wall", - ], -} - -cc_test { - name: "mc_sanity", - - srcs: [ - "MediaCodec_sanity_test.cpp", - ], - - include_dirs: [ - "hardware/google/av/media/sfplugin", - ], - - header_libs: [ - "libmediadrm_headers", - ], - - shared_libs: [ - "libbinder", - "libgui", - "libmedia", - "libmedia_omx", - "libstagefright", - "libstagefright_ccodec", - "libstagefright_codec2", - "libstagefright_foundation", - "libutils", - ], - - cflags: [ - "-Werror", - "-Wall", - ], -} diff --git a/media/sfplugin/tests/MediaCodec_sanity_test.cpp b/media/sfplugin/tests/MediaCodec_sanity_test.cpp deleted file mode 100644 index 3c43f1f..0000000 --- a/media/sfplugin/tests/MediaCodec_sanity_test.cpp +++ /dev/null @@ -1,453 +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. - */ - -#include <stdlib.h> - -#include <algorithm> - -#include <binder/ProcessState.h> -#include <gtest/gtest.h> -#include <gui/Surface.h> -#include <media/MediaCodecBuffer.h> -#include <media/hardware/VideoAPI.h> -#include <media/stagefright/MediaCodec.h> -#include <media/stagefright/MediaCodecConstants.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ALooper.h> -#include <media/stagefright/foundation/AMessage.h> -#include <mediadrm/ICrypto.h> - -namespace android { - -class MediaCodecSanityTest : public ::testing::Test { -public: - MediaCodecSanityTest() - : looper(new ALooper), - cfg(new AMessage), - ifmt(new AMessage), - ofmt(new AMessage) { - ProcessState::self()->startThreadPool(); - looper->start(); - } - - ~MediaCodecSanityTest() { - if (codec != nullptr) { - codec->release(); - } - looper->stop(); - } - - sp<ALooper> looper; - sp<MediaCodec> codec; - sp<AMessage> cfg; - sp<AMessage> ifmt; - sp<AMessage> ofmt; -}; - -const static size_t kLinearBufferSize = 1048576; - -// data for a codec input frame -struct FrameData { - const uint8_t *data; - size_t size; - template<size_t N> - constexpr FrameData(const uint8_t(&data_)[N]) : data(data_), size(N) { } -}; - -// one yellow frame of 240x180 (albeit 4:4:4) -const uint8_t avcStream_A1[] = { // IDR frame - 0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x0d, 0xac, 0xd9, 0x41, 0x41, 0xfa, 0x10, 0x00, 0x00, - 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x20, 0xf1, 0x42, 0x99, 0x60, - - 0x00, 0x00, 0x00, 0x01, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0, - - 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00, 0x2b, 0xff, 0xfe, 0xd8, 0xe7, 0xf3, 0x2c, 0xa5, 0x60, - 0xca, 0xbb, 0xf1, 0x5c, 0x44, 0x7c, 0x9a, 0xa5, 0xc3, 0xab, 0x2f, 0x77, 0x0a, 0x94, 0x0d, 0x19, - 0x43, 0x3b, 0x4f, 0x25, 0xea, 0x66, 0x00, 0x01, 0x24, 0xcd, 0x35, 0x5f, 0xc2, 0x34, 0x89, 0xd1, - 0xa5, 0x60, 0x09, 0x98, 0x00, 0x01, 0x1b, 0x0e, 0xcb, 0x0d, 0x04, 0x86, 0x94, 0xe2, 0x32, 0x3c, - 0xdd, 0x0f, -}; - -FrameData avcStream_A[] __unused = { avcStream_A1 }; - -// AVC stream of 2 yellow frames (240x180) -const uint8_t avcStream_B1[] = { // IDR frame - 0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x0c, 0xac, 0xd9, 0x41, 0x41, 0xfa, 0x10, 0x00, 0x00, - 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x02, 0x80, 0xf1, 0x42, 0x99, 0x60, - - 0x00, 0x00, 0x00, 0x01, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0, - - 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00, 0x33, 0xff, 0xfe, 0xdf, 0x32, 0xf8, 0x14, 0xd6, 0x25, - 0xd0, 0x74, 0x42, 0x50, 0x84, 0x6f, 0xf4, 0xc2, 0x5c, 0x76, 0x37, 0x17, 0x72, 0xac, 0x52, 0xfc, - 0xd6, 0x1f, 0xd2, 0xd0, 0x60, 0xb2, 0x20, 0x00, 0x10, 0x3d, 0x2a, 0xc0, 0xe4, 0x27, 0xcb, 0xce, - 0xea, 0x25, 0x00, 0x81, 0x00, 0x00, 0x0f, 0x40, 0xbc, 0x81, 0x15, 0xc1, 0x65, 0x20, 0x80, 0x81, - 0x7a, 0x57, 0x51, -}; - -const uint8_t avcStream_B2[] = { // P frame - 0x00, 0x00, 0x00, 0x01, 0x41, 0x9a, 0x21, 0x6c, 0x42, 0xbf, 0xfe, 0x38, 0x40, 0x00, 0x0d, 0x48, -}; - -FrameData avcStream_B[] = { avcStream_B1, avcStream_B2 }; - -class MediaCodecInputBufferSizeTest : public MediaCodecSanityTest, - public ::testing::WithParamInterface<int32_t> { -}; - -TEST_P(MediaCodecInputBufferSizeTest, TestAvcDecoder) { - codec = MediaCodec::CreateByComponentName(looper, "c2.android.avc.decoder"); - cfg->setInt32("width", 320); - cfg->setInt32("height", 240); - cfg->setString("mime", MIMETYPE_VIDEO_AVC); - - const int32_t InputSize = GetParam(); - if (InputSize >= 0) { - cfg->setInt32("max-input-size", InputSize); - } - - EXPECT_EQ(codec->configure(cfg, nullptr, nullptr, 0), OK); - EXPECT_EQ(codec->getInputFormat(&ifmt), OK); - int32_t maxInputSize; - ASSERT_TRUE(ifmt->findInt32("max-input-size", &maxInputSize)); - if (InputSize > 0) { - EXPECT_EQ(maxInputSize, InputSize); - } else { - EXPECT_GE(maxInputSize, 1 << 20); // 1 MB - } - EXPECT_EQ(codec->start(), OK); - size_t ix; - EXPECT_EQ(codec->dequeueInputBuffer(&ix, 1000000), OK); - sp<MediaCodecBuffer> buf; - EXPECT_EQ(codec->getInputBuffer(ix, &buf), OK); - EXPECT_GE(buf->size(), (size_t)maxInputSize); - EXPECT_LE(buf->size(), (size_t)maxInputSize + 4096u); -} - -TEST_P(MediaCodecInputBufferSizeTest, TestVideoDecoder) { - codec = MediaCodec::CreateByComponentName(looper, "c2.android.vp8.decoder"); - cfg->setInt32("width", 320); - cfg->setInt32("height", 240); - cfg->setString("mime", MIMETYPE_VIDEO_VP8); - - const int32_t InputSize = GetParam(); - if (InputSize >= 0) { - cfg->setInt32("max-input-size", InputSize); - } - - EXPECT_EQ(codec->configure(cfg, nullptr, nullptr, 0), OK); - EXPECT_EQ(codec->getInputFormat(&ifmt), OK); - int32_t maxInputSize; - ASSERT_TRUE(ifmt->findInt32("max-input-size", &maxInputSize)); - if (InputSize > 0) { - EXPECT_EQ(maxInputSize, InputSize); - } else { - EXPECT_GE(maxInputSize, 1 << 20); // 1 MB - } - EXPECT_EQ(codec->start(), OK); - size_t ix; - EXPECT_EQ(codec->dequeueInputBuffer(&ix, 1000000), OK); - sp<MediaCodecBuffer> buf; - EXPECT_EQ(codec->getInputBuffer(ix, &buf), OK); - EXPECT_GE(buf->size(), (size_t)maxInputSize); - EXPECT_LE(buf->size(), (size_t)maxInputSize + 4096u); -} - -TEST_P(MediaCodecInputBufferSizeTest, TestAudioDecoder) { - codec = MediaCodec::CreateByComponentName(looper, "c2.android.aac.decoder"); - cfg->setInt32("sample-rate", 44100); - cfg->setInt32("channel-count", 2); - cfg->setString("mime", MIMETYPE_AUDIO_AAC); - - const int32_t InputSize = GetParam(); - if (InputSize >= 0) { - cfg->setInt32("max-input-size", InputSize); - } - - EXPECT_EQ(codec->configure(cfg, nullptr, nullptr, 0), OK); - EXPECT_EQ(codec->getInputFormat(&ifmt), OK); - int32_t maxInputSize; - if (InputSize > 0) { - ASSERT_TRUE(ifmt->findInt32("max-input-size", &maxInputSize)); - EXPECT_EQ(maxInputSize, InputSize); - } else { - if (ifmt->findInt32("max-input-size", &maxInputSize)) { - EXPECT_EQ(maxInputSize, 1 << 19); // 512 KB - } - maxInputSize = kLinearBufferSize; // input size is set by channel - } - - EXPECT_EQ(codec->start(), OK); - size_t ix; - EXPECT_EQ(codec->dequeueInputBuffer(&ix, 1000000), OK); - sp<MediaCodecBuffer> buf; - EXPECT_EQ(codec->getInputBuffer(ix, &buf), OK); - EXPECT_GE(buf->size(), (size_t)maxInputSize); - EXPECT_LE(buf->size(), (size_t)maxInputSize + 4096u); -} - -INSTANTIATE_TEST_CASE_P(InputSizes, MediaCodecInputBufferSizeTest, ::testing::Values(-1, 1234, 12345678)); - -TEST_F(MediaCodecSanityTest, TestAvcDecoderHdrStaticInfo) { - codec = MediaCodec::CreateByComponentName(looper, "c2.android.avc.decoder"); - cfg->setInt32("width", 320); - cfg->setInt32("height", 240); - cfg->setString("mime", MIMETYPE_VIDEO_AVC); - HDRStaticInfo info = { .mID = HDRStaticInfo::kType1, .sType1 = { - .mR = { .x = 35400, .y = 14600 }, .mG = { .x = 8500, .y = 39850 }, - .mB = { .x = 6550, .y = 2300 }, .mW = { .x = 15635, .y = 16450 }, - .mMaxDisplayLuminance = 1000, .mMinDisplayLuminance = 1000, - .mMaxContentLightLevel = 1000, .mMaxFrameAverageLightLevel = 120 } - }; - cfg->setBuffer("hdr-static-info", ABuffer::CreateAsCopy(&info, sizeof(info))); - - EXPECT_EQ(codec->configure(cfg, nullptr, nullptr, 0), OK); - EXPECT_EQ(codec->getOutputFormat(&ofmt), OK); - sp<ABuffer> oinfo; - ASSERT_TRUE(ofmt->findBuffer("hdr-static-info", &oinfo)); - ASSERT_EQ(oinfo->size(), sizeof(info)); - EXPECT_EQ(memcmp(oinfo->data(), &info, sizeof(info)), 0); - - EXPECT_EQ(codec->start(), OK); - // assume we can submit all input before dequeuing output - size_t frameIx = 0; - size_t ix; - sp<MediaCodecBuffer> buf; - for (const FrameData &frame : avcStream_B) { - EXPECT_EQ(codec->dequeueInputBuffer(&ix, 1000000), OK); - EXPECT_EQ(codec->getInputBuffer(ix, &buf), OK); - ASSERT_GE(buf->capacity(), frame.size); - memcpy(buf->base(), frame.data, frame.size); - EXPECT_EQ(buf->setRange(0, frame.size), OK); - bool eos = ++frameIx == NELEM(avcStream_B); - EXPECT_EQ(codec->queueInputBuffer(ix, 0, frame.size, frameIx * 33333, - eos ? BUFFER_FLAG_END_OF_STREAM : 0), OK); - } - - size_t offset, size; - int64_t ts; - uint32_t flags; - bool mInfoFormatChangedOk = true; - bool mInfoBuffersChangedOk = true; - while (true) { - status_t err = codec->dequeueOutputBuffer(&ix, &offset, &size, &ts, &flags, 1000000); - if (err == INFO_FORMAT_CHANGED && mInfoFormatChangedOk) { - mInfoFormatChangedOk = false; - } else if (err == INFO_OUTPUT_BUFFERS_CHANGED && mInfoBuffersChangedOk) { - mInfoBuffersChangedOk = false; - } else { - ASSERT_EQ(err, OK); - break; - } - } - EXPECT_EQ(codec->getOutputBuffer(ix, &buf), OK); - EXPECT_EQ(codec->getOutputFormat(ix, &ofmt), OK); - ASSERT_TRUE(ofmt->findBuffer("hdr-static-info", &oinfo)); - ASSERT_EQ(oinfo->size(), sizeof(info)); - EXPECT_EQ(memcmp(oinfo->data(), &info, sizeof(info)), 0); -} - -TEST_F(MediaCodecSanityTest, TestVideoDecoderHdrStaticInfo) { - codec = MediaCodec::CreateByComponentName(looper, "c2.android.mpeg4.decoder"); - cfg->setInt32("width", 320); - cfg->setInt32("height", 240); - cfg->setString("mime", MIMETYPE_VIDEO_MPEG4); - HDRStaticInfo info = { .mID = HDRStaticInfo::kType1, .sType1 = { - .mR = { .x = 35400, .y = 14600 }, .mG = { .x = 8500, .y = 39850 }, - .mB = { .x = 6550, .y = 2300 }, .mW = { .x = 15635, .y = 16450 }, - .mMaxDisplayLuminance = 1000, .mMinDisplayLuminance = 1000, - .mMaxContentLightLevel = 1000, .mMaxFrameAverageLightLevel = 120 } - }; - cfg->setBuffer("hdr-static-info", ABuffer::CreateAsCopy(&info, sizeof(info))); - - EXPECT_EQ(codec->configure(cfg, nullptr, nullptr, 0), OK); - EXPECT_EQ(codec->getOutputFormat(&ofmt), OK); - sp<ABuffer> oinfo; - ASSERT_TRUE(ofmt->findBuffer("hdr-static-info", &oinfo)); - ASSERT_EQ(oinfo->size(), sizeof(info)); - EXPECT_EQ(memcmp(oinfo->data(), &info, sizeof(info)), 0); -} - -class MediaCodecByteBufferTest : public MediaCodecSanityTest, - public ::testing::WithParamInterface<int32_t> { -}; - -TEST_P(MediaCodecByteBufferTest, TestVideoDecoder420Planar) { - codec = MediaCodec::CreateByComponentName(looper, "c2.android.avc.decoder"); -// codec = MediaCodec::CreateByComponentName(looper, "OMX.google.h264.decoder"); - cfg->setInt32("width", 320); - cfg->setInt32("height", 240); - cfg->setString("mime", MIMETYPE_VIDEO_AVC); - const int32_t Color = GetParam(); - if (Color >= 0) { - cfg->setInt32("color-format", Color); - } - int32_t xcolor = Color == -1 ? COLOR_FormatYUV420Planar : Color; - - EXPECT_EQ(codec->configure(cfg, nullptr, nullptr, 0), OK); - EXPECT_EQ(codec->getOutputFormat(&ofmt), OK); - int32_t ocolor = -1; - EXPECT_TRUE(ofmt->findInt32("color-format", &ocolor)); - EXPECT_EQ(ocolor, xcolor); - - EXPECT_EQ(codec->start(), OK); - // assume we can submit all input before dequeuing output - size_t frameIx = 0; - size_t ix; - sp<MediaCodecBuffer> buf; - for (const FrameData &frame : avcStream_A) { - EXPECT_EQ(codec->dequeueInputBuffer(&ix, 1000000), OK); - EXPECT_EQ(codec->getInputBuffer(ix, &buf), OK); - ASSERT_GE(buf->capacity(), frame.size); - memcpy(buf->base(), frame.data, frame.size); - EXPECT_EQ(buf->setRange(0, frame.size), OK); - bool eos = ++frameIx == NELEM(avcStream_A); - EXPECT_EQ(codec->queueInputBuffer(ix, 0, frame.size, frameIx * 33333, - eos ? BUFFER_FLAG_END_OF_STREAM : 0), OK); - } - - size_t offset, size; - int64_t ts; - uint32_t flags; - bool mInfoFormatChangedOk = true; - bool mInfoBuffersChangedOk = true; - while (true) { - status_t err = codec->dequeueOutputBuffer(&ix, &offset, &size, &ts, &flags, 1000000); - if (err == INFO_FORMAT_CHANGED && mInfoFormatChangedOk) { - mInfoFormatChangedOk = false; - } else if (err == INFO_OUTPUT_BUFFERS_CHANGED && mInfoBuffersChangedOk) { - mInfoBuffersChangedOk = false; - } else { - ASSERT_EQ(err, OK); - break; - } - } - EXPECT_EQ(codec->getOutputBuffer(ix, &buf), OK); - EXPECT_EQ(codec->getOutputFormat(ix, &ofmt), OK); - ASSERT_TRUE(ofmt->findInt32("color-format", &ocolor)); - EXPECT_EQ(ocolor, xcolor) << ofmt->debugString(8).c_str() << buf->meta()->debugString(8).c_str(); - // expect an image-data in both format and meta - sp<ABuffer> imgBuf, imgBuf2; - ASSERT_TRUE(ofmt->findBuffer("image-data", &imgBuf)); - ASSERT_TRUE(buf->meta()->findBuffer("image-data", &imgBuf2)); - EXPECT_EQ(imgBuf->size(), sizeof(MediaImage2)); - ASSERT_EQ(imgBuf->size(), imgBuf2->size()); - EXPECT_EQ(0, memcmp(imgBuf->data(), imgBuf2->data(), imgBuf->size())); - MediaImage2 *img = (MediaImage2*)imgBuf->data(); - EXPECT_EQ(img->mType, img->MEDIA_IMAGE_TYPE_YUV); - EXPECT_EQ(img->mNumPlanes, 3u); - EXPECT_EQ(img->mWidth, 320u); - EXPECT_EQ(img->mHeight, 240u); - EXPECT_EQ(img->mBitDepth, 8u); - EXPECT_EQ(img->mBitDepthAllocated, 8u); - - // read strides from format - int32_t stride, vstride; - ofmt->findInt32("stride", &stride) || ofmt->findInt32("width", &stride); - ofmt->findInt32("slice-height", &vstride) || ofmt->findInt32("height", &vstride); - - EXPECT_EQ(img->mPlane[img->Y].mHorizSubsampling, 1u); - EXPECT_EQ(img->mPlane[img->Y].mVertSubsampling, 1u); - EXPECT_EQ(img->mPlane[img->U].mHorizSubsampling, 2u); - EXPECT_EQ(img->mPlane[img->U].mVertSubsampling, 2u); - EXPECT_EQ(img->mPlane[img->V].mHorizSubsampling, 2u); - EXPECT_EQ(img->mPlane[img->V].mVertSubsampling, 2u); - - switch (xcolor) { - // defined formats - case COLOR_FormatYUV420Planar: - case COLOR_FormatYUV420PackedPlanar: - EXPECT_EQ(img->mPlane[img->Y].mOffset, 0u); - EXPECT_EQ(img->mPlane[img->Y].mColInc, 1); - EXPECT_EQ(img->mPlane[img->Y].mRowInc, stride); - - EXPECT_EQ(img->mPlane[img->U].mOffset, (uint32_t)(stride * vstride)); - EXPECT_EQ(img->mPlane[img->U].mColInc, 1); - EXPECT_EQ(img->mPlane[img->U].mRowInc, stride / 2); - - EXPECT_EQ(img->mPlane[img->V].mOffset, (uint32_t)(stride * vstride * 5 / 4)); - EXPECT_EQ(img->mPlane[img->V].mColInc, 1); - EXPECT_EQ(img->mPlane[img->V].mRowInc, stride / 2); - - EXPECT_GE(size, (size_t)(stride * vstride * 5 / 4 + stride / 2 * 119 + 160)); - EXPECT_LE(size, (size_t)(stride * vstride * 3 / 2)); - break; - - case COLOR_FormatYUV420SemiPlanar: - case COLOR_FormatYUV420PackedSemiPlanar: - EXPECT_EQ(img->mPlane[img->Y].mOffset, 0u); - EXPECT_EQ(img->mPlane[img->Y].mColInc, 1); - EXPECT_EQ(img->mPlane[img->Y].mRowInc, stride); - - EXPECT_EQ(img->mPlane[img->U].mOffset, (uint32_t)(stride * vstride)); - EXPECT_EQ(img->mPlane[img->U].mColInc, 2); - EXPECT_EQ(img->mPlane[img->U].mRowInc, stride); - - EXPECT_EQ(img->mPlane[img->V].mOffset, (uint32_t)(stride * vstride + 1)); - EXPECT_EQ(img->mPlane[img->V].mColInc, 2); - EXPECT_EQ(img->mPlane[img->V].mRowInc, stride); - - EXPECT_GE(size, (size_t)(stride * vstride + stride * 119 + 320)); - EXPECT_LE(size, (size_t)(stride * vstride * 3 / 2)); - break; - - case COLOR_FormatYUV420Flexible: - // anything goes, but stride should match Y plane - EXPECT_EQ(img->mPlane[img->Y].mRowInc, stride); - - EXPECT_GE(size, - std::max({ - img->mPlane[img->Y].mOffset + 239 * img->mPlane[img->Y].mRowInc - + 319 * img->mPlane[img->Y].mColInc + 1, - img->mPlane[img->U].mOffset + 119 * img->mPlane[img->U].mRowInc - + 159 * img->mPlane[img->U].mColInc + 1, - img->mPlane[img->V].mOffset + 119 * img->mPlane[img->V].mRowInc - + 159 * img->mPlane[img->V].mColInc + 1 })); - break; - - default: - break; - } - - // validate all pixels -#if 0 - fprintf(stderr, "MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }\n", - img->mWidth, img->mHeight, - img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc, - img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc, - img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc); -#endif - for (ix = 0; ix < 3; ++ix) { - const static uint8_t expected[] = { 210, 16, 146 }; - for (uint32_t y = 0; y < img->mHeight / img->mPlane[ix].mVertSubsampling ; ++y) { - for (uint32_t x = 0; x < img->mWidth / img->mPlane[ix].mHorizSubsampling; ++x) { - uint8_t val = buf->data()[img->mPlane[ix].mOffset + img->mPlane[ix].mColInc * x - + img->mPlane[ix].mRowInc * y]; - ASSERT_EQ(val, expected[ix]) << "incorrect value for plane " - << ix << " at x=" << x << ", y=" << y; - } - } - } -} - -INSTANTIATE_TEST_CASE_P(InputSizes, MediaCodecByteBufferTest, ::testing::Values( - -1, - COLOR_FormatYUV420Planar, - COLOR_FormatYUV420SemiPlanar, - COLOR_FormatYUV420PackedPlanar, - COLOR_FormatYUV420PackedSemiPlanar, - COLOR_FormatYUV420Flexible)); - -} // namespace android diff --git a/media/sfplugin/tests/ReflectedParamUpdater_test.cpp b/media/sfplugin/tests/ReflectedParamUpdater_test.cpp deleted file mode 100644 index c7db0e3..0000000 --- a/media/sfplugin/tests/ReflectedParamUpdater_test.cpp +++ /dev/null @@ -1,352 +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 __C2_GENERATE_GLOBAL_VARS__ - -#include <set> - -#include <gtest/gtest.h> - -#include <C2ParamDef.h> - -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/hexdump.h> -#include <ReflectedParamUpdater.h> - -namespace android { - -namespace { - -enum { - kParamIndexTestStart = 0x1000, - kParamIndexInt, - kParamIndexString, - kParamIndexComposite, - kParamIndexFlexString, - - kParamIndexLong = C2Param::TYPE_INDEX_VENDOR_START, -}; - -typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexInt> C2IntInfo; -typedef C2GlobalParam<C2Info, C2Int64Value, kParamIndexLong> C2LongInfo; - -struct C2FixedSizeStringStruct { - char value[12]; - - DEFINE_AND_DESCRIBE_BASE_C2STRUCT(FixedSizeString) - C2FIELD(value, "value") -}; -typedef C2GlobalParam<C2Info, C2FixedSizeStringStruct, kParamIndexString> C2StringInfo; - -struct C2CompositeStruct { - int32_t i32; - uint64_t u64; - char str[12]; - uint8_t blob[8]; - uint8_t flexBlob[]; - - C2CompositeStruct() = default; - - DEFINE_AND_DESCRIBE_BASE_FLEX_C2STRUCT(Composite, flexBlob) - C2FIELD(i32, "i32") - C2FIELD(u64, "u64") - C2FIELD(str, "str") - C2FIELD(blob, "blob") - C2FIELD(flexBlob, "flex-blob") -}; -static_assert(C2CompositeStruct::FLEX_SIZE == 1, ""); -static_assert(_C2FlexHelper<C2CompositeStruct>::FLEX_SIZE == 1, ""); -typedef C2GlobalParam<C2Info, C2CompositeStruct, kParamIndexComposite> C2CompositeInfo; - -typedef C2GlobalParam<C2Info, C2StringValue, kParamIndexFlexString> C2FlexStringInfo; - -#define SUPPORTED_TYPES \ - C2IntInfo, \ - C2LongInfo, \ - C2StringInfo, \ - C2CompositeInfo, \ - C2FlexStringInfo - -template<typename... TYPES> struct describe_impl; -template<typename T, typename... TYPES> struct describe_impl<T, TYPES...> { - static std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex index) { - if (index == T::CORE_INDEX) { - return std::make_unique<C2StructDescriptor>(T::CORE_INDEX, T::FieldList()); - } else { - return describe_impl<TYPES...>::describe(index); - } - } -}; - -template<> struct describe_impl<> { - static std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex) { - return nullptr; - } -}; - -template<typename T> const char *GetName() { return nullptr; } -template<> const char *GetName<C2IntInfo>() { return "int"; } -template<> const char *GetName<C2LongInfo>() { return "long"; } -template<> const char *GetName<C2StringInfo>() { return "string"; } -template<> const char *GetName<C2CompositeInfo>() { return "composite"; } -template<> const char *GetName<C2FlexStringInfo>() { return "flex-string"; } - -template<typename... TYPES> struct fill_descriptors_impl; -template<typename T, typename... TYPES> struct fill_descriptors_impl<T, TYPES...> { - static void fill(std::vector<std::shared_ptr<C2ParamDescriptor>> *vec) { - fill_descriptors_impl<TYPES...>::fill(vec); - vec->push_back(std::make_shared<C2ParamDescriptor>( - T::PARAM_TYPE, C2ParamDescriptor::IS_PERSISTENT, GetName<T>())); - } -}; - -template<> struct fill_descriptors_impl<> { - static void fill(std::vector<std::shared_ptr<C2ParamDescriptor>> *) {} -}; - -template<typename T> T *CastParam(const std::unique_ptr<C2Param> ¶m) { - return (T *)param.get(); -} - -class ParamReflector : public C2ParamReflector { -public: - ParamReflector() = default; - ~ParamReflector() override = default; - - std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex paramIndex) const override { - return describe_impl<SUPPORTED_TYPES>::describe(paramIndex); - } -}; - -} // namespace - -class ReflectedParamUpdaterTest : public ::testing::Test { -public: - ReflectedParamUpdaterTest() : mReflector(new ParamReflector) { - fill_descriptors_impl<SUPPORTED_TYPES>::fill(&mDescriptors); - } - - std::shared_ptr<C2ParamReflector> mReflector; - std::vector<std::shared_ptr<C2ParamDescriptor>> mDescriptors; -}; - -TEST_F(ReflectedParamUpdaterTest, SingleValueTest) { - ReflectedParamUpdater updater; - - ReflectedParamUpdater::Dict msg; - msg.emplace("int.value", int32_t(12)); - msg.emplace("vendor.long.value", int64_t(34)); - - updater.addParamDesc(mReflector, mDescriptors); - - std::vector<C2Param::Index> indices; - updater.getParamIndicesFromMessage(msg, &indices); - EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; })); - EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2FlexStringInfo::PARAM_TYPE; })); - - std::vector<std::unique_ptr<C2Param>> params; - params.emplace_back(new C2IntInfo); - params.emplace_back(new C2LongInfo); - EXPECT_EQ(0, CastParam<C2IntInfo>(params[0])->value); - EXPECT_EQ(0, CastParam<C2LongInfo>(params[1])->value); - - updater.updateParamsFromMessage(msg, ¶ms); - EXPECT_EQ(12, CastParam<C2IntInfo>(params[0])->value); - EXPECT_EQ(34, CastParam<C2LongInfo>(params[1])->value); - - C2Value c2Value; - int32_t int32Value = 0; - int64_t int64Value = 0; - msg = updater.getParams(params); - ASSERT_EQ(1u, msg.count("int.value")); - EXPECT_EQ(true, msg["int.value"].find(&c2Value)); - EXPECT_EQ(true, c2Value.get(&int32Value)); - EXPECT_EQ(12, int32Value); - - ASSERT_EQ(1u, msg.count("vendor.long.value")); - EXPECT_EQ(true, msg["vendor.long.value"].find(&c2Value)); - EXPECT_EQ(true, c2Value.get(&int64Value)); - EXPECT_EQ(34, int64Value); -} - -TEST_F(ReflectedParamUpdaterTest, StringTest) { - ReflectedParamUpdater updater; - - ReflectedParamUpdater::Dict msg; - msg.emplace("string.value", AString("56")); - msg.emplace("flex-string.value", AString("Some string")); - updater.addParamDesc(mReflector, mDescriptors); - - std::vector<C2Param::Index> indices; - updater.getParamIndicesFromMessage(msg, &indices); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; })); - EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; })); - EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2FlexStringInfo::PARAM_TYPE; })); - - std::vector<std::unique_ptr<C2Param>> params; - params.emplace_back(new C2StringInfo); - EXPECT_EQ(0, CastParam<C2StringInfo>(params[0])->value[0]); - params.emplace_back(C2FlexStringInfo::AllocUnique(0)); - EXPECT_EQ(0u, CastParam<C2FlexStringInfo>(params[1])->flexCount()); - char *flexStringData = &CastParam<C2FlexStringInfo>(params[1])->m.value[0]; - - updater.updateParamsFromMessage(msg, ¶ms); - EXPECT_STREQ("56", CastParam<C2StringInfo>(params[0])->value); - EXPECT_EQ(12u, CastParam<C2FlexStringInfo>(params[0])->flexCount()); - EXPECT_STREQ("Some string", CastParam<C2FlexStringInfo>(params[1])->m.value); - EXPECT_NE(flexStringData, &CastParam<C2FlexStringInfo>(params[1])->m.value[0]); - flexStringData = &CastParam<C2FlexStringInfo>(params[1])->m.value[0]; - - // verify truncation and in-place update - msg["string.value"] = ReflectedParamUpdater::Value(AString("1234567890ABCDE")); - msg["flex-string.value"] = ReflectedParamUpdater::Value(AString("abc")); - updater.updateParamsFromMessage(msg, ¶ms); - EXPECT_STREQ("1234567890A", CastParam<C2StringInfo>(params[0])->value); - EXPECT_EQ(4u, CastParam<C2FlexStringInfo>(params[1])->flexCount()); - EXPECT_STREQ("abc", CastParam<C2FlexStringInfo>(params[1])->m.value); - EXPECT_EQ(flexStringData, &CastParam<C2FlexStringInfo>(params[1])->m.value[0]); - - AString strValue; - msg = updater.getParams(params); - ASSERT_EQ(1u, msg.count("string.value")); - EXPECT_EQ(true, msg["string.value"].find(&strValue)); - EXPECT_STREQ("1234567890A", strValue.c_str()); - - ASSERT_EQ(1u, msg.count("flex-string.value")); - EXPECT_EQ(true, msg["flex-string.value"].find(&strValue)); - EXPECT_STREQ("abc", strValue.c_str()); -} - -TEST_F(ReflectedParamUpdaterTest, CompositeTest) { - ReflectedParamUpdater updater; - - ReflectedParamUpdater::Dict msg; - msg.emplace("composite.i32", int32_t(78)); - msg.emplace("composite.u64", int64_t(910)); - msg.emplace("composite.str", AString("1112")); - msg.emplace("composite.blob", ABuffer::CreateAsCopy("buffer08", 8)); - msg.emplace("composite.flex-blob", ABuffer::CreateAsCopy("flex-buffer-14", 14)); - - updater.addParamDesc(mReflector, mDescriptors); - - std::vector<C2Param::Index> indices; - updater.getParamIndicesFromMessage(msg, &indices); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; })); - EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; })); - - std::vector<std::unique_ptr<C2Param>> params; - params.emplace_back(C2CompositeInfo::AllocUnique(0)); - EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.i32); - EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->m.u64); - EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.str[0]); - EXPECT_EQ(0, memcmp("\0\0\0\0\0\0\0\0", CastParam<C2CompositeInfo>(params[0])->m.blob, 8)); - EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->flexCount()); - uint8_t *flexBlobData = &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]; - - updater.updateParamsFromMessage(msg, ¶ms); - EXPECT_EQ(78, CastParam<C2CompositeInfo>(params[0])->m.i32); - EXPECT_EQ(910u, CastParam<C2CompositeInfo>(params[0])->m.u64); - EXPECT_STREQ("1112", CastParam<C2CompositeInfo>(params[0])->m.str); - EXPECT_EQ(0, memcmp("buffer08", CastParam<C2CompositeInfo>(params[0])->m.blob, 8)); - AString hex; - hexdump(CastParam<C2CompositeInfo>(params[0])->m.blob, 8, 0, &hex); - printf("%s\n", hex.c_str()); - ASSERT_EQ(14u, CastParam<C2CompositeInfo>(params[0])->flexCount()); - EXPECT_EQ(0, memcmp("flex-buffer-14", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 14)); - EXPECT_NE(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]); - flexBlobData = &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]; - - // test setting and zero extending shorter blob than allowed - msg.clear(); - msg.emplace("composite.blob", ABuffer::CreateAsCopy("buf05", 5)); - updater.updateParamsFromMessage(msg, ¶ms); - EXPECT_EQ(0, memcmp("buf05\0\0\0", CastParam<C2CompositeInfo>(params[0])->m.blob, 8)); - ASSERT_EQ(14u, CastParam<C2CompositeInfo>(params[0])->flexCount()); - EXPECT_EQ(0, memcmp("flex-buffer-14", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 14)); - EXPECT_EQ(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]); - - // test setting and trimming larger blob than allowed - msg.clear(); - msg.emplace("composite.blob", ABuffer::CreateAsCopy("ReallyLongBuffer", 16)); - updater.updateParamsFromMessage(msg, ¶ms); - EXPECT_EQ(0, memcmp("ReallyLo", CastParam<C2CompositeInfo>(params[0])->m.blob, 8)); - ASSERT_EQ(14u, CastParam<C2CompositeInfo>(params[0])->flexCount()); - EXPECT_EQ(0, memcmp("flex-buffer-14", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 14)); - EXPECT_EQ(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]); - - // test trimming flex blob in-place - msg.clear(); - msg.emplace("composite.flex-blob", ABuffer::CreateAsCopy("buf05", 5)); - updater.updateParamsFromMessage(msg, ¶ms); - ASSERT_EQ(5u, CastParam<C2CompositeInfo>(params[0])->flexCount()); - EXPECT_EQ(0, memcmp("buf05", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 5)); - EXPECT_EQ(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]); -} - -TEST_F(ReflectedParamUpdaterTest, CompositePartialTest) { - ReflectedParamUpdater updater; - - ReflectedParamUpdater::Dict msg; - msg.emplace("composite.i32", C2Value(1314)); - msg.emplace("composite.str", AString("1516")); - - updater.addParamDesc(mReflector, mDescriptors); - - std::vector<C2Param::Index> indices; - updater.getParamIndicesFromMessage(msg, &indices); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; })); - EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; })); - EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(), - [](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; })); - - std::vector<std::unique_ptr<C2Param>> params; - params.emplace_back(C2CompositeInfo::AllocUnique(12u)); - EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.i32); - EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->m.u64); - EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.str[0]); - - updater.updateParamsFromMessage(msg, ¶ms); - EXPECT_EQ(1314, CastParam<C2CompositeInfo>(params[0])->m.i32); - EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->m.u64); - EXPECT_STREQ("1516", CastParam<C2CompositeInfo>(params[0])->m.str); -} - -} // namespace android diff --git a/media/sfplugin/utils/Android.bp b/media/sfplugin/utils/Android.bp deleted file mode 100644 index fb5d9e4..0000000 --- a/media/sfplugin/utils/Android.bp +++ /dev/null @@ -1,40 +0,0 @@ -cc_library_shared { - name: "libstagefright_ccodec_utils", - vendor_available: true, - - srcs: [ - "Codec2BufferUtils.cpp", - "Codec2Mapper.cpp", - ], - - cflags: [ - "-Werror", - "-Wall", - ], - - export_include_dirs: [ - ".", - ], - - shared_libs: [ - "libbase", - "libcutils", - "liblog", - "libstagefright_codec2", - "libstagefright_codec2_vndk", - "libstagefright_foundation", - "libutils", - ], - - static_libs: [ - "libyuv_static", - ], - - sanitize: { - cfi: true, - misc_undefined: [ - "unsigned-integer-overflow", - "signed-integer-overflow", - ], - }, -} diff --git a/media/sfplugin/utils/Codec2BufferUtils.cpp b/media/sfplugin/utils/Codec2BufferUtils.cpp deleted file mode 100644 index 6b8663f..0000000 --- a/media/sfplugin/utils/Codec2BufferUtils.cpp +++ /dev/null @@ -1,533 +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 "Codec2BufferUtils" -#include <utils/Log.h> - -#include <libyuv.h> - -#include <list> -#include <mutex> - -#include <media/hardware/HardwareAPI.h> -#include <media/stagefright/foundation/AUtils.h> - -#include <C2Debug.h> - -#include "Codec2BufferUtils.h" - -namespace android { - -namespace { - -/** - * A flippable, optimizable memcpy. Constructs such as (from ? src : dst) do not work as the results are - * always const. - */ -template<bool ToA, size_t S> -struct MemCopier { - template<typename A, typename B> - inline static void copy(A *a, const B *b, size_t size) { - __builtin_memcpy(a, b, size); - } -}; - -template<size_t S> -struct MemCopier<false, S> { - template<typename A, typename B> - inline static void copy(const A *a, B *b, size_t size) { - MemCopier<true, S>::copy(b, a, size); - } -}; - -/** - * Copies between a MediaImage and a graphic view. - * - * \param ToMediaImage whether to copy to (or from) the MediaImage - * \param view graphic view (could be ConstGraphicView or GraphicView depending on direction) - * \param img MediaImage data - * \param imgBase base of MediaImage (could be const uint8_t* or uint8_t* depending on direction) - */ -template<bool ToMediaImage, typename View, typename ImagePixel> -static status_t _ImageCopy(View &view, const MediaImage2 *img, ImagePixel *imgBase) { - // TODO: more efficient copying --- e.g. copy interleaved planes together, etc. - const C2PlanarLayout &layout = view.layout(); - const size_t bpp = divUp(img->mBitDepthAllocated, 8u); - - for (uint32_t i = 0; i < layout.numPlanes; ++i) { - typename std::conditional<ToMediaImage, uint8_t, const uint8_t>::type *imgRow = - imgBase + img->mPlane[i].mOffset; - typename std::conditional<ToMediaImage, const uint8_t, uint8_t>::type *viewRow = - viewRow = view.data()[i]; - const C2PlaneInfo &plane = layout.planes[i]; - if (plane.colSampling != img->mPlane[i].mHorizSubsampling - || plane.rowSampling != img->mPlane[i].mVertSubsampling - || plane.allocatedDepth != img->mBitDepthAllocated - || plane.allocatedDepth < plane.bitDepth - // MediaImage only supports MSB values - || plane.rightShift != plane.allocatedDepth - plane.bitDepth - || (bpp > 1 && plane.endianness != plane.NATIVE)) { - return BAD_VALUE; - } - - uint32_t planeW = img->mWidth / plane.colSampling; - uint32_t planeH = img->mHeight / plane.rowSampling; - - bool canCopyByRow = (plane.colInc == 1) && (img->mPlane[i].mColInc == 1); - bool canCopyByPlane = canCopyByRow && (plane.rowInc == img->mPlane[i].mRowInc); - if (canCopyByPlane) { - MemCopier<ToMediaImage, 0>::copy(imgRow, viewRow, plane.rowInc * planeH); - } else if (canCopyByRow) { - for (uint32_t row = 0; row < planeH; ++row) { - MemCopier<ToMediaImage, 0>::copy( - imgRow, viewRow, std::min(plane.rowInc, img->mPlane[i].mRowInc)); - imgRow += img->mPlane[i].mRowInc; - viewRow += plane.rowInc; - } - } else { - for (uint32_t row = 0; row < planeH; ++row) { - decltype(imgRow) imgPtr = imgRow; - decltype(viewRow) viewPtr = viewRow; - for (uint32_t col = 0; col < planeW; ++col) { - MemCopier<ToMediaImage, 0>::copy(imgPtr, viewPtr, bpp); - imgPtr += img->mPlane[i].mColInc; - viewPtr += plane.colInc; - } - imgRow += img->mPlane[i].mRowInc; - viewRow += plane.rowInc; - } - } - } - return OK; -} - -} // namespace - -status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView &view) { - if (view.width() != img->mWidth || view.height() != img->mHeight) { - return BAD_VALUE; - } - if ((IsNV12(view) && IsI420(img)) || (IsI420(view) && IsNV12(img))) { - // Take shortcuts to use libyuv functions between NV12 and I420 conversion. - const uint8_t* src_y = view.data()[0]; - const uint8_t* src_u = view.data()[1]; - const uint8_t* src_v = view.data()[2]; - int32_t src_stride_y = view.layout().planes[0].rowInc; - int32_t src_stride_u = view.layout().planes[1].rowInc; - int32_t src_stride_v = view.layout().planes[2].rowInc; - uint8_t* dst_y = imgBase + img->mPlane[0].mOffset; - uint8_t* dst_u = imgBase + img->mPlane[1].mOffset; - uint8_t* dst_v = imgBase + img->mPlane[2].mOffset; - int32_t dst_stride_y = img->mPlane[0].mRowInc; - int32_t dst_stride_u = img->mPlane[1].mRowInc; - 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())) { - 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())) { - return OK; - } - } - } - return _ImageCopy<true>(view, img, imgBase); -} - -status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage2 *img) { - if (view.width() != img->mWidth || view.height() != img->mHeight) { - return BAD_VALUE; - } - if ((IsNV12(img) && IsI420(view)) || (IsI420(img) && IsNV12(view))) { - // Take shortcuts to use libyuv functions between NV12 and I420 conversion. - const uint8_t* src_y = imgBase + img->mPlane[0].mOffset; - const uint8_t* src_u = imgBase + img->mPlane[1].mOffset; - const uint8_t* src_v = imgBase + img->mPlane[2].mOffset; - int32_t src_stride_y = img->mPlane[0].mRowInc; - int32_t src_stride_u = img->mPlane[1].mRowInc; - int32_t src_stride_v = img->mPlane[2].mRowInc; - uint8_t* dst_y = view.data()[0]; - uint8_t* dst_u = view.data()[1]; - uint8_t* dst_v = view.data()[2]; - int32_t dst_stride_y = view.layout().planes[0].rowInc; - int32_t dst_stride_u = view.layout().planes[1].rowInc; - int32_t dst_stride_v = view.layout().planes[2].rowInc; - if (IsNV12(img) && IsI420(view)) { - 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())) { - 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())) { - return OK; - } - } - } - return _ImageCopy<false>(view, img, imgBase); -} - -bool IsYUV420(const C2GraphicView &view) { - const C2PlanarLayout &layout = view.layout(); - return (layout.numPlanes == 3 - && layout.type == C2PlanarLayout::TYPE_YUV - && layout.planes[layout.PLANE_Y].channel == C2PlaneInfo::CHANNEL_Y - && layout.planes[layout.PLANE_Y].allocatedDepth == 8 - && layout.planes[layout.PLANE_Y].bitDepth == 8 - && layout.planes[layout.PLANE_Y].rightShift == 0 - && layout.planes[layout.PLANE_Y].colSampling == 1 - && layout.planes[layout.PLANE_Y].rowSampling == 1 - && layout.planes[layout.PLANE_U].channel == C2PlaneInfo::CHANNEL_CB - && layout.planes[layout.PLANE_U].allocatedDepth == 8 - && layout.planes[layout.PLANE_U].bitDepth == 8 - && layout.planes[layout.PLANE_U].rightShift == 0 - && layout.planes[layout.PLANE_U].colSampling == 2 - && layout.planes[layout.PLANE_U].rowSampling == 2 - && layout.planes[layout.PLANE_V].channel == C2PlaneInfo::CHANNEL_CR - && layout.planes[layout.PLANE_V].allocatedDepth == 8 - && layout.planes[layout.PLANE_V].bitDepth == 8 - && layout.planes[layout.PLANE_V].rightShift == 0 - && layout.planes[layout.PLANE_V].colSampling == 2 - && layout.planes[layout.PLANE_V].rowSampling == 2); -} - -bool IsNV12(const C2GraphicView &view) { - if (!IsYUV420(view)) { - return false; - } - const C2PlanarLayout &layout = view.layout(); - return (layout.rootPlanes == 2 - && layout.planes[layout.PLANE_U].colInc == 2 - && layout.planes[layout.PLANE_U].rootIx == layout.PLANE_U - && layout.planes[layout.PLANE_U].offset == 0 - && layout.planes[layout.PLANE_V].colInc == 2 - && layout.planes[layout.PLANE_V].rootIx == layout.PLANE_U - && layout.planes[layout.PLANE_V].offset == 1); -} - -bool IsI420(const C2GraphicView &view) { - if (!IsYUV420(view)) { - return false; - } - const C2PlanarLayout &layout = view.layout(); - return (layout.rootPlanes == 3 - && layout.planes[layout.PLANE_U].colInc == 1 - && layout.planes[layout.PLANE_U].rootIx == layout.PLANE_U - && layout.planes[layout.PLANE_U].offset == 0 - && layout.planes[layout.PLANE_V].colInc == 1 - && layout.planes[layout.PLANE_V].rootIx == layout.PLANE_V - && layout.planes[layout.PLANE_V].offset == 0); -} - -bool IsYUV420(const MediaImage2 *img) { - return (img->mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV - && img->mNumPlanes == 3 - && img->mBitDepth == 8 - && img->mBitDepthAllocated == 8 - && img->mPlane[0].mHorizSubsampling == 1 - && img->mPlane[0].mVertSubsampling == 1 - && img->mPlane[1].mHorizSubsampling == 2 - && img->mPlane[1].mVertSubsampling == 2 - && img->mPlane[2].mHorizSubsampling == 2 - && img->mPlane[2].mVertSubsampling == 2); -} - -bool IsNV12(const MediaImage2 *img) { - if (!IsYUV420(img)) { - return false; - } - return (img->mPlane[1].mColInc == 2 - && img->mPlane[2].mColInc == 2 - && (img->mPlane[2].mOffset - img->mPlane[1].mOffset == 1)); -} - -bool IsI420(const MediaImage2 *img) { - if (!IsYUV420(img)) { - return false; - } - return (img->mPlane[1].mColInc == 1 - && img->mPlane[2].mColInc == 1 - && img->mPlane[2].mOffset > img->mPlane[1].mOffset); -} - -MediaImage2 CreateYUV420PlanarMediaImage2( - uint32_t width, uint32_t height, uint32_t stride, uint32_t vstride) { - return MediaImage2 { - .mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV, - .mNumPlanes = 3, - .mWidth = width, - .mHeight = height, - .mBitDepth = 8, - .mBitDepthAllocated = 8, - .mPlane = { - { - .mOffset = 0, - .mColInc = 1, - .mRowInc = (int32_t)stride, - .mHorizSubsampling = 1, - .mVertSubsampling = 1, - }, - { - .mOffset = stride * vstride, - .mColInc = 1, - .mRowInc = (int32_t)stride / 2, - .mHorizSubsampling = 2, - .mVertSubsampling = 2, - }, - { - .mOffset = stride * vstride * 5 / 4, - .mColInc = 1, - .mRowInc = (int32_t)stride / 2, - .mHorizSubsampling = 2, - .mVertSubsampling = 2, - } - }, - }; -} - -MediaImage2 CreateYUV420SemiPlanarMediaImage2( - uint32_t width, uint32_t height, uint32_t stride, uint32_t vstride) { - return MediaImage2 { - .mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV, - .mNumPlanes = 3, - .mWidth = width, - .mHeight = height, - .mBitDepth = 8, - .mBitDepthAllocated = 8, - .mPlane = { - { - .mOffset = 0, - .mColInc = 1, - .mRowInc = (int32_t)stride, - .mHorizSubsampling = 1, - .mVertSubsampling = 1, - }, - { - .mOffset = stride * vstride, - .mColInc = 2, - .mRowInc = (int32_t)stride, - .mHorizSubsampling = 2, - .mVertSubsampling = 2, - }, - { - .mOffset = stride * vstride + 1, - .mColInc = 2, - .mRowInc = (int32_t)stride, - .mHorizSubsampling = 2, - .mVertSubsampling = 2, - } - }, - }; -} - -status_t ConvertRGBToPlanarYUV( - uint8_t *dstY, size_t dstStride, size_t dstVStride, size_t bufferSize, - const C2GraphicView &src) { - CHECK(dstY != nullptr); - CHECK((src.width() & 1) == 0); - CHECK((src.height() & 1) == 0); - - if (dstStride * dstVStride * 3 / 2 > bufferSize) { - ALOGD("conversion buffer is too small for converting from RGB to YUV"); - return NO_MEMORY; - } - - 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]; - -#define CLIP3(x,y,z) (((z) < (x)) ? (x) : (((z) > (y)) ? (y) : (z))) - for (size_t y = 0; y < src.height(); ++y) { - for (size_t x = 0; x < src.width(); ++x) { - uint8_t red = *pRed; - uint8_t green = *pGreen; - uint8_t blue = *pBlue; - - // using ITU-R BT.601 conversion matrix - unsigned luma = - CLIP3(0, (((red * 66 + green * 129 + blue * 25) >> 8) + 16), 255); - - dstY[x] = luma; - - if ((x & 1) == 0 && (y & 1) == 0) { - unsigned U = - CLIP3(0, (((-red * 38 - green * 74 + blue * 112) >> 8) + 128), 255); - - unsigned V = - CLIP3(0, (((red * 112 - green * 94 - blue * 18) >> 8) + 128), 255); - - 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; - } - return OK; -} - -namespace { - -/** - * A block of raw allocated memory. - */ -struct MemoryBlockPoolBlock { - MemoryBlockPoolBlock(size_t size) - : mData(new uint8_t[size]), mSize(mData ? size : 0) { } - - ~MemoryBlockPoolBlock() { - delete[] mData; - } - - const uint8_t *data() const { - return mData; - } - - size_t size() const { - return mSize; - } - - C2_DO_NOT_COPY(MemoryBlockPoolBlock); - -private: - uint8_t *mData; - size_t mSize; -}; - -/** - * A simple raw memory block pool implementation. - */ -struct MemoryBlockPoolImpl { - void release(std::list<MemoryBlockPoolBlock>::const_iterator block) { - std::lock_guard<std::mutex> lock(mMutex); - // return block to free blocks if it is the current size; otherwise, discard - if (block->size() == mCurrentSize) { - mFreeBlocks.splice(mFreeBlocks.begin(), mBlocksInUse, block); - } else { - mBlocksInUse.erase(block); - } - } - - std::list<MemoryBlockPoolBlock>::const_iterator fetch(size_t size) { - std::lock_guard<std::mutex> lock(mMutex); - mFreeBlocks.remove_if([size](const MemoryBlockPoolBlock &block) -> bool { - return block.size() != size; - }); - mCurrentSize = size; - if (mFreeBlocks.empty()) { - mBlocksInUse.emplace_front(size); - } else { - mBlocksInUse.splice(mBlocksInUse.begin(), mFreeBlocks, mFreeBlocks.begin()); - } - return mBlocksInUse.begin(); - } - - MemoryBlockPoolImpl() = default; - - C2_DO_NOT_COPY(MemoryBlockPoolImpl); - -private: - std::mutex mMutex; - std::list<MemoryBlockPoolBlock> mFreeBlocks; - std::list<MemoryBlockPoolBlock> mBlocksInUse; - size_t mCurrentSize; -}; - -} // namespace - -struct MemoryBlockPool::Impl : MemoryBlockPoolImpl { -}; - -struct MemoryBlock::Impl { - Impl(std::list<MemoryBlockPoolBlock>::const_iterator block, - std::shared_ptr<MemoryBlockPoolImpl> pool) - : mBlock(block), mPool(pool) { - } - - ~Impl() { - mPool->release(mBlock); - } - - const uint8_t *data() const { - return mBlock->data(); - } - - size_t size() const { - return mBlock->size(); - } - -private: - std::list<MemoryBlockPoolBlock>::const_iterator mBlock; - std::shared_ptr<MemoryBlockPoolImpl> mPool; -}; - -MemoryBlock MemoryBlockPool::fetch(size_t size) { - std::list<MemoryBlockPoolBlock>::const_iterator poolBlock = mImpl->fetch(size); - return MemoryBlock(std::make_shared<MemoryBlock::Impl>( - poolBlock, std::static_pointer_cast<MemoryBlockPoolImpl>(mImpl))); -} - -MemoryBlockPool::MemoryBlockPool() - : mImpl(std::make_shared<MemoryBlockPool::Impl>()) { -} - -MemoryBlock::MemoryBlock(std::shared_ptr<MemoryBlock::Impl> impl) - : mImpl(impl) { -} - -MemoryBlock::MemoryBlock() = default; - -MemoryBlock::~MemoryBlock() = default; - -const uint8_t* MemoryBlock::data() const { - return mImpl ? mImpl->data() : nullptr; -} - -size_t MemoryBlock::size() const { - return mImpl ? mImpl->size() : 0; -} - -MemoryBlock MemoryBlock::Allocate(size_t size) { - return MemoryBlockPool().fetch(size); -} - -} // namespace android diff --git a/media/sfplugin/utils/Codec2BufferUtils.h b/media/sfplugin/utils/Codec2BufferUtils.h deleted file mode 100644 index afadf00..0000000 --- a/media/sfplugin/utils/Codec2BufferUtils.h +++ /dev/null @@ -1,166 +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 CODEC2_BUFFER_UTILS_H_ -#define CODEC2_BUFFER_UTILS_H_ - -#include <C2Buffer.h> -#include <C2ParamDef.h> - -#include <media/hardware/VideoAPI.h> -#include <utils/Errors.h> - -namespace android { - -/** - * Converts an RGB view to planar YUV 420 media image. - * - * \param dstY pointer to media image buffer - * \param dstStride stride in bytes - * \param dstVStride vertical stride in pixels - * \param bufferSize media image buffer size - * \param src source image - * - * \retval NO_MEMORY media image is too small - * \retval OK on success - */ -status_t ConvertRGBToPlanarYUV( - uint8_t *dstY, size_t dstStride, size_t dstVStride, size_t bufferSize, - const C2GraphicView &src); - -/** - * Returns a planar YUV 420 8-bit media image descriptor. - * - * \param width width of image in pixels - * \param height height of image in pixels - * \param stride stride of image in pixels - * \param vstride vertical stride of image in pixels - */ -MediaImage2 CreateYUV420PlanarMediaImage2( - uint32_t width, uint32_t height, uint32_t stride, uint32_t vstride); - -/** - * Returns a semiplanar YUV 420 8-bit media image descriptor. - * - * \param width width of image in pixels - * \param height height of image in pixels - * \param stride stride of image in pixels - * \param vstride vertical stride of image in pixels - */ -MediaImage2 CreateYUV420SemiPlanarMediaImage2( - uint32_t width, uint32_t height, uint32_t stride, uint32_t vstride); - -/** - * Copies a graphic view into a media image. - * - * \param imgBase base of MediaImage - * \param img MediaImage data - * \param view graphic view - * - * \return OK on success - */ -status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView &view); - -/** - * Copies a media image into a graphic view. - * - * \param view graphic view - * \param imgBase base of MediaImage - * \param img MediaImage data - * - * \return OK on success - */ -status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage2 *img); - -/** - * Returns true iff a view has a YUV 420 888 layout. - */ -bool IsYUV420(const C2GraphicView &view); - -/** - * Returns true iff a view has a NV12 layout. - */ -bool IsNV12(const C2GraphicView &view); - -/** - * Returns true iff a view has a I420 layout. - */ -bool IsI420(const C2GraphicView &view); - -/** - * Returns true iff a MediaImage2 has a YUV 420 888 layout. - */ -bool IsYUV420(const MediaImage2 *img); - -/** - * Returns true iff a MediaImage2 has a NV12 layout. - */ -bool IsNV12(const MediaImage2 *img); - -/** - * Returns true iff a MediaImage2 has a I420 layout. - */ -bool IsI420(const MediaImage2 *img); - -/** - * A raw memory block to use for internal buffers. - * - * TODO: replace this with C2LinearBlocks from a private C2BlockPool - */ -struct MemoryBlock : public C2MemoryBlock<uint8_t> { - virtual const uint8_t* data() const override; - virtual size_t size() const override; - - inline uint8_t *data() { - return const_cast<uint8_t*>(const_cast<const MemoryBlock*>(this)->data()); - } - - // allocates an unmanaged block (not in a pool) - static MemoryBlock Allocate(size_t); - - // memory block with no actual memory (size is 0, data is null) - MemoryBlock(); - - struct Impl; - MemoryBlock(std::shared_ptr<Impl> impl); - virtual ~MemoryBlock(); - -private: - std::shared_ptr<Impl> mImpl; -}; - -/** - * A raw memory mini-pool. - */ -struct MemoryBlockPool { - /** - * Fetches a block with a given size. - * - * \param size size in bytes - */ - MemoryBlock fetch(size_t size); - - MemoryBlockPool(); - ~MemoryBlockPool() = default; - -private: - struct Impl; - std::shared_ptr<Impl> mImpl; -}; - -} // namespace android - -#endif // CODEC2_BUFFER_UTILS_H_ diff --git a/media/sfplugin/utils/Codec2Mapper.cpp b/media/sfplugin/utils/Codec2Mapper.cpp deleted file mode 100644 index 97e17e8..0000000 --- a/media/sfplugin/utils/Codec2Mapper.cpp +++ /dev/null @@ -1,815 +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 "Codec2Mapper" -#include <utils/Log.h> - -#include <media/stagefright/MediaCodecConstants.h> -#include <media/stagefright/SurfaceUtils.h> -#include <media/stagefright/foundation/ALookup.h> -#include <media/stagefright/foundation/ColorUtils.h> -#include <media/stagefright/foundation/MediaDefs.h> - -#include <stdint.h> // for INT32_MAX - -#include "Codec2Mapper.h" - -using namespace android; - -namespace { - -ALookup<C2Config::profile_t, int32_t> sAacProfiles = { - { C2Config::PROFILE_AAC_LC, AACObjectLC }, - { C2Config::PROFILE_AAC_MAIN, AACObjectMain }, - { C2Config::PROFILE_AAC_SSR, AACObjectSSR }, - { C2Config::PROFILE_AAC_LTP, AACObjectLTP }, - { C2Config::PROFILE_AAC_HE, AACObjectHE }, - { C2Config::PROFILE_AAC_SCALABLE, AACObjectScalable }, - { C2Config::PROFILE_AAC_ER_LC, AACObjectERLC }, - { C2Config::PROFILE_AAC_ER_SCALABLE, AACObjectERScalable }, - { C2Config::PROFILE_AAC_LD, AACObjectLD }, - { C2Config::PROFILE_AAC_HE_PS, AACObjectHE_PS }, - { C2Config::PROFILE_AAC_ELD, AACObjectELD }, - { C2Config::PROFILE_AAC_XHE, AACObjectXHE }, -}; - -ALookup<C2Config::level_t, int32_t> sAvcLevels = { - { C2Config::LEVEL_AVC_1, AVCLevel1 }, - { C2Config::LEVEL_AVC_1B, AVCLevel1b }, - { C2Config::LEVEL_AVC_1_1, AVCLevel11 }, - { C2Config::LEVEL_AVC_1_2, AVCLevel12 }, - { C2Config::LEVEL_AVC_1_3, AVCLevel13 }, - { C2Config::LEVEL_AVC_2, AVCLevel2 }, - { C2Config::LEVEL_AVC_2_1, AVCLevel21 }, - { C2Config::LEVEL_AVC_2_2, AVCLevel22 }, - { C2Config::LEVEL_AVC_3, AVCLevel3 }, - { C2Config::LEVEL_AVC_3_1, AVCLevel31 }, - { C2Config::LEVEL_AVC_3_2, AVCLevel32 }, - { C2Config::LEVEL_AVC_4, AVCLevel4 }, - { C2Config::LEVEL_AVC_4_1, AVCLevel41 }, - { C2Config::LEVEL_AVC_4_2, AVCLevel42 }, - { C2Config::LEVEL_AVC_5, AVCLevel5 }, - { C2Config::LEVEL_AVC_5_1, AVCLevel51 }, - { C2Config::LEVEL_AVC_5_2, AVCLevel52 }, - -}; - -ALookup<C2Config::profile_t, int32_t> sAvcProfiles = { - // treat restricted profiles as full profile if there is no equivalent - which works for - // decoders, but not for encoders - { C2Config::PROFILE_AVC_BASELINE, AVCProfileBaseline }, - { C2Config::PROFILE_AVC_CONSTRAINED_BASELINE, AVCProfileConstrainedBaseline }, - { C2Config::PROFILE_AVC_MAIN, AVCProfileMain }, - { C2Config::PROFILE_AVC_EXTENDED, AVCProfileExtended }, - { C2Config::PROFILE_AVC_HIGH, AVCProfileHigh }, - { C2Config::PROFILE_AVC_PROGRESSIVE_HIGH, AVCProfileHigh }, - { C2Config::PROFILE_AVC_CONSTRAINED_HIGH, AVCProfileConstrainedHigh }, - { C2Config::PROFILE_AVC_HIGH_10, AVCProfileHigh10 }, - { C2Config::PROFILE_AVC_PROGRESSIVE_HIGH_10, AVCProfileHigh10 }, - { C2Config::PROFILE_AVC_HIGH_422, AVCProfileHigh422 }, - { C2Config::PROFILE_AVC_HIGH_444_PREDICTIVE, AVCProfileHigh444 }, - { C2Config::PROFILE_AVC_HIGH_10_INTRA, AVCProfileHigh10 }, - { C2Config::PROFILE_AVC_HIGH_422_INTRA, AVCProfileHigh422 }, - { C2Config::PROFILE_AVC_HIGH_444_INTRA, AVCProfileHigh444 }, - { C2Config::PROFILE_AVC_CAVLC_444_INTRA, AVCProfileHigh444 }, -}; - -ALookup<C2Config::bitrate_mode_t, int32_t> sBitrateModes = { - { C2Config::BITRATE_CONST, BITRATE_MODE_CBR }, - { C2Config::BITRATE_VARIABLE, BITRATE_MODE_VBR }, - { C2Config::BITRATE_IGNORE, BITRATE_MODE_CQ }, -}; - -ALookup<C2Color::matrix_t, ColorAspects::MatrixCoeffs> sColorMatricesSf = { - { C2Color::MATRIX_UNSPECIFIED, ColorAspects::MatrixUnspecified }, - { C2Color::MATRIX_BT709, ColorAspects::MatrixBT709_5 }, - { C2Color::MATRIX_FCC47_73_682, ColorAspects::MatrixBT470_6M }, - { C2Color::MATRIX_BT601, ColorAspects::MatrixBT601_6 }, - { C2Color::MATRIX_SMPTE240M, ColorAspects::MatrixSMPTE240M }, - { C2Color::MATRIX_BT2020, ColorAspects::MatrixBT2020 }, - { C2Color::MATRIX_BT2020_CONSTANT, ColorAspects::MatrixBT2020Constant }, - { C2Color::MATRIX_OTHER, ColorAspects::MatrixOther }, -}; - -ALookup<C2Color::primaries_t, ColorAspects::Primaries> sColorPrimariesSf = { - { C2Color::PRIMARIES_UNSPECIFIED, ColorAspects::PrimariesUnspecified }, - { C2Color::PRIMARIES_BT709, ColorAspects::PrimariesBT709_5 }, - { C2Color::PRIMARIES_BT470_M, ColorAspects::PrimariesBT470_6M }, - { C2Color::PRIMARIES_BT601_625, ColorAspects::PrimariesBT601_6_625 }, - { C2Color::PRIMARIES_BT601_525, ColorAspects::PrimariesBT601_6_525 }, - { C2Color::PRIMARIES_GENERIC_FILM, ColorAspects::PrimariesGenericFilm }, - { C2Color::PRIMARIES_BT2020, ColorAspects::PrimariesBT2020 }, -// { C2Color::PRIMARIES_RP431, ColorAspects::Primaries... }, -// { C2Color::PRIMARIES_EG432, ColorAspects::Primaries... }, -// { C2Color::PRIMARIES_EBU3213, ColorAspects::Primaries... }, - { C2Color::PRIMARIES_OTHER, ColorAspects::PrimariesOther }, -}; - -ALookup<C2Color::range_t, int32_t> sColorRanges = { - { C2Color::RANGE_FULL, COLOR_RANGE_FULL }, - { C2Color::RANGE_LIMITED, COLOR_RANGE_LIMITED }, -}; - -ALookup<C2Color::range_t, ColorAspects::Range> sColorRangesSf = { - { C2Color::RANGE_UNSPECIFIED, ColorAspects::RangeUnspecified }, - { C2Color::RANGE_FULL, ColorAspects::RangeFull }, - { C2Color::RANGE_LIMITED, ColorAspects::RangeLimited }, - { C2Color::RANGE_OTHER, ColorAspects::RangeOther }, -}; - -ALookup<C2Color::transfer_t, int32_t> sColorTransfers = { - { C2Color::TRANSFER_LINEAR, COLOR_TRANSFER_LINEAR }, - { C2Color::TRANSFER_170M, COLOR_TRANSFER_SDR_VIDEO }, - { C2Color::TRANSFER_ST2084, COLOR_TRANSFER_ST2084 }, - { C2Color::TRANSFER_HLG, COLOR_TRANSFER_HLG }, -}; - -ALookup<C2Color::transfer_t, ColorAspects::Transfer> sColorTransfersSf = { - { C2Color::TRANSFER_UNSPECIFIED, ColorAspects::TransferUnspecified }, - { C2Color::TRANSFER_LINEAR, ColorAspects::TransferLinear }, - { C2Color::TRANSFER_SRGB, ColorAspects::TransferSRGB }, - { C2Color::TRANSFER_170M, ColorAspects::TransferSMPTE170M }, - { C2Color::TRANSFER_GAMMA22, ColorAspects::TransferGamma22 }, - { C2Color::TRANSFER_GAMMA28, ColorAspects::TransferGamma28 }, - { C2Color::TRANSFER_ST2084, ColorAspects::TransferST2084 }, - { C2Color::TRANSFER_HLG, ColorAspects::TransferHLG }, - { C2Color::TRANSFER_240M, ColorAspects::TransferSMPTE240M }, - { C2Color::TRANSFER_XVYCC, ColorAspects::TransferXvYCC }, - { C2Color::TRANSFER_BT1361, ColorAspects::TransferBT1361 }, - { C2Color::TRANSFER_ST428, ColorAspects::TransferST428 }, - { C2Color::TRANSFER_OTHER, ColorAspects::TransferOther }, -}; - -ALookup<C2Config::level_t, int32_t> sDolbyVisionLevels = { - { C2Config::LEVEL_DV_MAIN_HD_24, DolbyVisionLevelHd24 }, - { C2Config::LEVEL_DV_MAIN_HD_30, DolbyVisionLevelHd30 }, - { C2Config::LEVEL_DV_MAIN_FHD_24, DolbyVisionLevelFhd24 }, - { C2Config::LEVEL_DV_MAIN_FHD_30, DolbyVisionLevelFhd30 }, - { C2Config::LEVEL_DV_MAIN_FHD_60, DolbyVisionLevelFhd60 }, - { C2Config::LEVEL_DV_MAIN_UHD_24, DolbyVisionLevelUhd24 }, - { C2Config::LEVEL_DV_MAIN_UHD_30, DolbyVisionLevelUhd30 }, - { C2Config::LEVEL_DV_MAIN_UHD_48, DolbyVisionLevelUhd48 }, - { C2Config::LEVEL_DV_MAIN_UHD_60, DolbyVisionLevelUhd60 }, - - // high tiers are not yet supported on android, for now map them to main tier - { C2Config::LEVEL_DV_HIGH_HD_24, DolbyVisionLevelHd24 }, - { C2Config::LEVEL_DV_HIGH_HD_30, DolbyVisionLevelHd30 }, - { C2Config::LEVEL_DV_HIGH_FHD_24, DolbyVisionLevelFhd24 }, - { C2Config::LEVEL_DV_HIGH_FHD_30, DolbyVisionLevelFhd30 }, - { C2Config::LEVEL_DV_HIGH_FHD_60, DolbyVisionLevelFhd60 }, - { C2Config::LEVEL_DV_HIGH_UHD_24, DolbyVisionLevelUhd24 }, - { C2Config::LEVEL_DV_HIGH_UHD_30, DolbyVisionLevelUhd30 }, - { C2Config::LEVEL_DV_HIGH_UHD_48, DolbyVisionLevelUhd48 }, - { C2Config::LEVEL_DV_HIGH_UHD_60, DolbyVisionLevelUhd60 }, -}; - -ALookup<C2Config::profile_t, int32_t> sDolbyVisionProfiles = { - { C2Config::PROFILE_DV_AV_PER, DolbyVisionProfileDvavPer }, - { C2Config::PROFILE_DV_AV_PEN, DolbyVisionProfileDvavPen }, - { C2Config::PROFILE_DV_HE_DER, DolbyVisionProfileDvheDer }, - { C2Config::PROFILE_DV_HE_DEN, DolbyVisionProfileDvheDen }, - { C2Config::PROFILE_DV_HE_04, DolbyVisionProfileDvheDtr }, - { C2Config::PROFILE_DV_HE_05, DolbyVisionProfileDvheStn }, - { C2Config::PROFILE_DV_HE_DTH, DolbyVisionProfileDvheDth }, - { C2Config::PROFILE_DV_HE_07, DolbyVisionProfileDvheDtb }, - { C2Config::PROFILE_DV_HE_08, DolbyVisionProfileDvheSt }, - { C2Config::PROFILE_DV_AV_09, DolbyVisionProfileDvavSe }, -}; - -ALookup<C2Config::level_t, int32_t> sH263Levels = { - { C2Config::LEVEL_H263_10, H263Level10 }, - { C2Config::LEVEL_H263_20, H263Level20 }, - { C2Config::LEVEL_H263_30, H263Level30 }, - { C2Config::LEVEL_H263_40, H263Level40 }, - { C2Config::LEVEL_H263_45, H263Level45 }, - { C2Config::LEVEL_H263_50, H263Level50 }, - { C2Config::LEVEL_H263_60, H263Level60 }, - { C2Config::LEVEL_H263_70, H263Level70 }, -}; - -ALookup<C2Config::profile_t, int32_t> sH263Profiles = { - { C2Config::PROFILE_H263_BASELINE, H263ProfileBaseline }, - { C2Config::PROFILE_H263_H320, H263ProfileH320Coding }, - { C2Config::PROFILE_H263_V1BC, H263ProfileBackwardCompatible }, - { C2Config::PROFILE_H263_ISWV2, H263ProfileISWV2 }, - { C2Config::PROFILE_H263_ISWV3, H263ProfileISWV3 }, - { C2Config::PROFILE_H263_HIGH_COMPRESSION, H263ProfileHighCompression }, - { C2Config::PROFILE_H263_INTERNET, H263ProfileInternet }, - { C2Config::PROFILE_H263_INTERLACE, H263ProfileInterlace }, - { C2Config::PROFILE_H263_HIGH_LATENCY, H263ProfileHighLatency }, -}; - -ALookup<C2Config::level_t, int32_t> sHevcLevels = { - { C2Config::LEVEL_HEVC_MAIN_1, HEVCMainTierLevel1 }, - { C2Config::LEVEL_HEVC_MAIN_2, HEVCMainTierLevel2 }, - { C2Config::LEVEL_HEVC_MAIN_2_1, HEVCMainTierLevel21 }, - { C2Config::LEVEL_HEVC_MAIN_3, HEVCMainTierLevel3 }, - { C2Config::LEVEL_HEVC_MAIN_3_1, HEVCMainTierLevel31 }, - { C2Config::LEVEL_HEVC_MAIN_4, HEVCMainTierLevel4 }, - { C2Config::LEVEL_HEVC_MAIN_4_1, HEVCMainTierLevel41 }, - { C2Config::LEVEL_HEVC_MAIN_5, HEVCMainTierLevel5 }, - { C2Config::LEVEL_HEVC_MAIN_5_1, HEVCMainTierLevel51 }, - { C2Config::LEVEL_HEVC_MAIN_5_2, HEVCMainTierLevel52 }, - { C2Config::LEVEL_HEVC_MAIN_6, HEVCMainTierLevel6 }, - { C2Config::LEVEL_HEVC_MAIN_6_1, HEVCMainTierLevel61 }, - { C2Config::LEVEL_HEVC_MAIN_6_2, HEVCMainTierLevel62 }, - - { C2Config::LEVEL_HEVC_HIGH_4, HEVCHighTierLevel4 }, - { C2Config::LEVEL_HEVC_HIGH_4_1, HEVCHighTierLevel41 }, - { C2Config::LEVEL_HEVC_HIGH_5, HEVCHighTierLevel5 }, - { C2Config::LEVEL_HEVC_HIGH_5_1, HEVCHighTierLevel51 }, - { C2Config::LEVEL_HEVC_HIGH_5_2, HEVCHighTierLevel52 }, - { C2Config::LEVEL_HEVC_HIGH_6, HEVCHighTierLevel6 }, - { C2Config::LEVEL_HEVC_HIGH_6_1, HEVCHighTierLevel61 }, - { C2Config::LEVEL_HEVC_HIGH_6_2, HEVCHighTierLevel62 }, - - // map high tier levels below 4 to main tier - { C2Config::LEVEL_HEVC_MAIN_1, HEVCHighTierLevel1 }, - { C2Config::LEVEL_HEVC_MAIN_2, HEVCHighTierLevel2 }, - { C2Config::LEVEL_HEVC_MAIN_2_1, HEVCHighTierLevel21 }, - { C2Config::LEVEL_HEVC_MAIN_3, HEVCHighTierLevel3 }, - { C2Config::LEVEL_HEVC_MAIN_3_1, HEVCHighTierLevel31 }, -}; - -ALookup<C2Config::profile_t, int32_t> sHevcProfiles = { - { C2Config::PROFILE_HEVC_MAIN, HEVCProfileMain }, - { C2Config::PROFILE_HEVC_MAIN_10, HEVCProfileMain10 }, - { C2Config::PROFILE_HEVC_MAIN_STILL, HEVCProfileMainStill }, - { C2Config::PROFILE_HEVC_MAIN_INTRA, HEVCProfileMain }, - { C2Config::PROFILE_HEVC_MAIN_10_INTRA, HEVCProfileMain10 }, -}; - -ALookup<C2Config::level_t, int32_t> sMpeg2Levels = { - { C2Config::LEVEL_MP2V_LOW, MPEG2LevelLL }, - { C2Config::LEVEL_MP2V_MAIN, MPEG2LevelML }, - { C2Config::LEVEL_MP2V_HIGH_1440, MPEG2LevelH14 }, - { C2Config::LEVEL_MP2V_HIGH, MPEG2LevelHL }, - { C2Config::LEVEL_MP2V_HIGHP, MPEG2LevelHP }, -}; - -ALookup<C2Config::profile_t, int32_t> sMpeg2Profiles = { - { C2Config::PROFILE_MP2V_SIMPLE, MPEG2ProfileSimple }, - { C2Config::PROFILE_MP2V_MAIN, MPEG2ProfileMain }, - { C2Config::PROFILE_MP2V_SNR_SCALABLE, MPEG2ProfileSNR }, - { C2Config::PROFILE_MP2V_SPATIALLY_SCALABLE, MPEG2ProfileSpatial }, - { C2Config::PROFILE_MP2V_HIGH, MPEG2ProfileHigh }, - { C2Config::PROFILE_MP2V_422, MPEG2Profile422 }, -}; - -ALookup<C2Config::level_t, int32_t> sMpeg4Levels = { - { C2Config::LEVEL_MP4V_0, MPEG4Level0 }, - { C2Config::LEVEL_MP4V_0B, MPEG4Level0b }, - { C2Config::LEVEL_MP4V_1, MPEG4Level1 }, - { C2Config::LEVEL_MP4V_2, MPEG4Level2 }, - { C2Config::LEVEL_MP4V_3, MPEG4Level3 }, - { C2Config::LEVEL_MP4V_3B, MPEG4Level3b }, - { C2Config::LEVEL_MP4V_4, MPEG4Level4 }, - { C2Config::LEVEL_MP4V_4A, MPEG4Level4a }, - { C2Config::LEVEL_MP4V_5, MPEG4Level5 }, - { C2Config::LEVEL_MP4V_6, MPEG4Level6 }, -}; - -ALookup<C2Config::profile_t, int32_t> sMpeg4Profiles = { - { C2Config::PROFILE_MP4V_SIMPLE, MPEG4ProfileSimple }, - { C2Config::PROFILE_MP4V_SIMPLE_SCALABLE, MPEG4ProfileSimpleScalable }, - { C2Config::PROFILE_MP4V_CORE, MPEG4ProfileCore }, - { C2Config::PROFILE_MP4V_MAIN, MPEG4ProfileMain }, - { C2Config::PROFILE_MP4V_NBIT, MPEG4ProfileNbit }, - { C2Config::PROFILE_MP4V_ARTS, MPEG4ProfileAdvancedRealTime }, - { C2Config::PROFILE_MP4V_CORE_SCALABLE, MPEG4ProfileCoreScalable }, - { C2Config::PROFILE_MP4V_ACE, MPEG4ProfileAdvancedCoding }, - { C2Config::PROFILE_MP4V_ADVANCED_CORE, MPEG4ProfileAdvancedCore }, - { C2Config::PROFILE_MP4V_ADVANCED_SIMPLE, MPEG4ProfileAdvancedSimple }, -}; - -ALookup<C2Config::pcm_encoding_t, int32_t> sPcmEncodings = { - { C2Config::PCM_8, kAudioEncodingPcm8bit }, - { C2Config::PCM_16, kAudioEncodingPcm16bit }, - { C2Config::PCM_FLOAT, kAudioEncodingPcmFloat }, -}; - -ALookup<C2Config::level_t, int32_t> sVp9Levels = { - { C2Config::LEVEL_VP9_1, VP9Level1 }, - { C2Config::LEVEL_VP9_1_1, VP9Level11 }, - { C2Config::LEVEL_VP9_2, VP9Level2 }, - { C2Config::LEVEL_VP9_2_1, VP9Level21 }, - { C2Config::LEVEL_VP9_3, VP9Level3 }, - { C2Config::LEVEL_VP9_3_1, VP9Level31 }, - { C2Config::LEVEL_VP9_4, VP9Level4 }, - { C2Config::LEVEL_VP9_4_1, VP9Level41 }, - { C2Config::LEVEL_VP9_5, VP9Level5 }, - { C2Config::LEVEL_VP9_5_1, VP9Level51 }, - { C2Config::LEVEL_VP9_5_2, VP9Level52 }, - { C2Config::LEVEL_VP9_6, VP9Level6 }, - { C2Config::LEVEL_VP9_6_1, VP9Level61 }, - { C2Config::LEVEL_VP9_6_2, VP9Level62 }, -}; - -ALookup<C2Config::profile_t, int32_t> sVp9Profiles = { - { C2Config::PROFILE_VP9_0, VP9Profile0 }, - { C2Config::PROFILE_VP9_1, VP9Profile1 }, - { C2Config::PROFILE_VP9_2, VP9Profile2 }, - { C2Config::PROFILE_VP9_3, VP9Profile3 }, -}; - -/** - * A helper that passes through vendor extension profile and level values. - */ -struct ProfileLevelMapperHelper : C2Mapper::ProfileLevelMapper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) = 0; - virtual bool simpleMap(int32_t from, C2Config::level_t *to) = 0; - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) = 0; - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) = 0; - - template<typename T, typename U> - bool passThroughMap(T from, U *to) { - // allow (and pass through) vendor extensions - if (from >= (T)C2_PROFILE_LEVEL_VENDOR_START && from < (T)INT32_MAX) { - *to = (U)from; - return true; - } - return simpleMap(from, to); - } - - virtual bool mapLevel(C2Config::level_t from, int32_t *to) { - return passThroughMap(from, to); - } - - virtual bool mapLevel(int32_t from, C2Config::level_t *to) { - return passThroughMap(from, to); - } - - virtual bool mapProfile(C2Config::profile_t from, int32_t *to) { - return passThroughMap(from, to); - } - - virtual bool mapProfile(int32_t from, C2Config::profile_t *to) { - return passThroughMap(from, to); - } -}; - -// AAC only uses profiles, map all levels to unused or 0 -struct AacProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t, int32_t *to) { - *to = 0; - return true; - } - virtual bool simpleMap(int32_t, C2Config::level_t *to) { - *to = C2Config::LEVEL_UNUSED; - return true; - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sAacProfiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sAacProfiles.map(from, to); - } -}; - -struct AvcProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) { - return sAvcLevels.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::level_t *to) { - return sAvcLevels.map(from, to); - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sAvcProfiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sAvcProfiles.map(from, to); - } -}; - -struct DolbyVisionProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) { - return sDolbyVisionLevels.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::level_t *to) { - return sDolbyVisionLevels.map(from, to); - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sDolbyVisionProfiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sDolbyVisionProfiles.map(from, to); - } -}; - -struct H263ProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) { - return sH263Levels.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::level_t *to) { - return sH263Levels.map(from, to); - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sH263Profiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sH263Profiles.map(from, to); - } -}; - -struct HevcProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) { - return sHevcLevels.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::level_t *to) { - return sHevcLevels.map(from, to); - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sHevcProfiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sHevcProfiles.map(from, to); - } -}; - -struct Mpeg2ProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) { - return sMpeg2Levels.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::level_t *to) { - return sMpeg2Levels.map(from, to); - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sMpeg2Profiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sMpeg2Profiles.map(from, to); - } -}; - -struct Mpeg4ProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) { - return sMpeg4Levels.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::level_t *to) { - return sMpeg4Levels.map(from, to); - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sMpeg4Profiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sMpeg4Profiles.map(from, to); - } -}; - -// VP8 has no profiles and levels in Codec 2.0, but we use main profile and level 0 in MediaCodec -// map all profiles and levels to that. -struct Vp8ProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t, int32_t *to) { - *to = VP8Level_Version0; - return true; - } - virtual bool simpleMap(int32_t, C2Config::level_t *to) { - *to = C2Config::LEVEL_UNUSED; - return true; - } - virtual bool simpleMap(C2Config::profile_t, int32_t *to) { - *to = VP8ProfileMain; - return true; - } - virtual bool simpleMap(int32_t, C2Config::profile_t *to) { - *to = C2Config::PROFILE_UNUSED; - return true; - } -}; - -struct Vp9ProfileLevelMapper : ProfileLevelMapperHelper { - virtual bool simpleMap(C2Config::level_t from, int32_t *to) { - return sVp9Levels.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::level_t *to) { - return sVp9Levels.map(from, to); - } - virtual bool simpleMap(C2Config::profile_t from, int32_t *to) { - return sVp9Profiles.map(from, to); - } - virtual bool simpleMap(int32_t from, C2Config::profile_t *to) { - return sVp9Profiles.map(from, to); - } -}; - -} // namespace - -// static -std::shared_ptr<C2Mapper::ProfileLevelMapper> -C2Mapper::GetProfileLevelMapper(std::string mediaType) { - std::transform(mediaType.begin(), mediaType.begin(), mediaType.end(), ::tolower); - if (mediaType == MIMETYPE_AUDIO_AAC) { - return std::make_shared<AacProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_AVC) { - return std::make_shared<AvcProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_DOLBY_VISION) { - return std::make_shared<DolbyVisionProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_H263) { - return std::make_shared<H263ProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_HEVC) { - return std::make_shared<HevcProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_MPEG2) { - return std::make_shared<Mpeg2ProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_MPEG4) { - return std::make_shared<Mpeg4ProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_VP8) { - return std::make_shared<Vp8ProfileLevelMapper>(); - } else if (mediaType == MIMETYPE_VIDEO_VP9) { - return std::make_shared<Vp9ProfileLevelMapper>(); - } - return nullptr; -} - -// static -bool C2Mapper::map(C2Config::bitrate_mode_t from, int32_t *to) { - return sBitrateModes.map(from, to); -} - -// static -bool C2Mapper::map(int32_t from, C2Config::bitrate_mode_t *to) { - return sBitrateModes.map(from, to); -} - -// static -bool C2Mapper::map(C2Config::pcm_encoding_t from, int32_t *to) { - return sPcmEncodings.map(from, to); -} - -// static -bool C2Mapper::map(int32_t from, C2Config::pcm_encoding_t *to) { - return sPcmEncodings.map(from, to); -} - -// static -bool C2Mapper::map(C2Color::range_t from, int32_t *to) { - bool res = true; - // map SDK defined values directly. For other values, use wrapping from ColorUtils. - if (!sColorRanges.map(from, to)) { - ColorAspects::Range sfRange; - - // map known constants and keep vendor extensions. all other values are mapped to 'Other' - if (!sColorRangesSf.map(from, &sfRange)) { - // use static cast and ensure it is in the extension range - if (from < C2Color::RANGE_VENDOR_START || from > C2Color::RANGE_OTHER) { - sfRange = ColorAspects::RangeOther; - res = false; - } - } - - *to = ColorUtils::wrapColorAspectsIntoColorRange(sfRange); - } - return res; -} - -// static -bool C2Mapper::map(int32_t from, C2Color::range_t *to) { - // map SDK defined values directly. For other values, use wrapping from ColorUtils. - if (!sColorRanges.map(from, to)) { - ColorAspects::Range sfRange; - (void)ColorUtils::unwrapColorAspectsFromColorRange(from, &sfRange); - - // map known constants and keep vendor extensions. all other values are mapped to 'Other' - if (!sColorRangesSf.map(sfRange, to)) { - // use static cast and ensure it is in the extension range - *to = (C2Color::range_t)sfRange; - if (*to < C2Color::RANGE_VENDOR_START || *to > C2Color::RANGE_OTHER) { - *to = C2Color::RANGE_OTHER; - return false; - } - } - } - - return true; -} - -// static -bool C2Mapper::map(C2Color::range_t from, ColorAspects::Range *to) { - return sColorRangesSf.map(from, to); -} - -// static -bool C2Mapper::map(ColorAspects::Range from, C2Color::range_t *to) { - return sColorRangesSf.map(from, to); -} - -// static -bool C2Mapper::map(C2Color::primaries_t primaries, C2Color::matrix_t matrix, int32_t *standard) { - ColorAspects::Primaries sfPrimaries; - ColorAspects::MatrixCoeffs sfMatrix; - bool res = true; - - // map known constants and keep vendor extensions. all other values are mapped to 'Other' - if (!sColorPrimariesSf.map(primaries, &sfPrimaries)) { - // ensure it is in the extension range and use static cast - if (primaries < C2Color::PRIMARIES_VENDOR_START || primaries > C2Color::PRIMARIES_OTHER) { - // undefined non-extension values map to 'Other' - sfPrimaries = ColorAspects::PrimariesOther; - res = false; - } else { - sfPrimaries = (ColorAspects::Primaries)primaries; - } - } - - if (!sColorMatricesSf.map(matrix, &sfMatrix)) { - // use static cast and ensure it is in the extension range - if (matrix < C2Color::MATRIX_VENDOR_START || matrix > C2Color::MATRIX_OTHER) { - // undefined non-extension values map to 'Other' - sfMatrix = ColorAspects::MatrixOther; - res = false; - } else { - sfMatrix = (ColorAspects::MatrixCoeffs)matrix; - } - } - - *standard = ColorUtils::wrapColorAspectsIntoColorStandard(sfPrimaries, sfMatrix); - - return res; -} - -// static -bool C2Mapper::map(int32_t standard, C2Color::primaries_t *primaries, C2Color::matrix_t *matrix) { - // first map to stagefright foundation aspects => these actually map nearly 1:1 to - // Codec 2.0 aspects - ColorAspects::Primaries sfPrimaries; - ColorAspects::MatrixCoeffs sfMatrix; - bool res = true; - (void)ColorUtils::unwrapColorAspectsFromColorStandard(standard, &sfPrimaries, &sfMatrix); - - // map known constants and keep vendor extensions. all other values are mapped to 'Other' - if (!sColorPrimariesSf.map(sfPrimaries, primaries)) { - // use static cast and ensure it is in the extension range - *primaries = (C2Color::primaries_t)sfPrimaries; - if (*primaries < C2Color::PRIMARIES_VENDOR_START || *primaries > C2Color::PRIMARIES_OTHER) { - *primaries = C2Color::PRIMARIES_OTHER; - res = false; - } - } - - if (!sColorMatricesSf.map(sfMatrix, matrix)) { - // use static cast and ensure it is in the extension range - *matrix = (C2Color::matrix_t)sfMatrix; - if (*matrix < C2Color::MATRIX_VENDOR_START || *matrix > C2Color::MATRIX_OTHER) { - *matrix = C2Color::MATRIX_OTHER; - res = false; - } - } - - return res; -} - -// static -bool C2Mapper::map(C2Color::primaries_t from, ColorAspects::Primaries *to) { - return sColorPrimariesSf.map(from, to); -} - -// static -bool C2Mapper::map(ColorAspects::Primaries from, C2Color::primaries_t *to) { - return sColorPrimariesSf.map(from, to); -} - -// static -bool C2Mapper::map(C2Color::matrix_t from, ColorAspects::MatrixCoeffs *to) { - return sColorMatricesSf.map(from, to); -} - -// static -bool C2Mapper::map(ColorAspects::MatrixCoeffs from, C2Color::matrix_t *to) { - return sColorMatricesSf.map(from, to); -} - -// static -bool C2Mapper::map(C2Color::transfer_t from, int32_t *to) { - bool res = true; - // map SDK defined values directly. For other values, use wrapping from ColorUtils. - if (!sColorTransfers.map(from, to)) { - ColorAspects::Transfer sfTransfer; - - // map known constants and keep vendor extensions. all other values are mapped to 'Other' - if (!sColorTransfersSf.map(from, &sfTransfer)) { - // use static cast and ensure it is in the extension range - if (from < C2Color::TRANSFER_VENDOR_START || from > C2Color::TRANSFER_OTHER) { - sfTransfer = ColorAspects::TransferOther; - res = false; - } - } - - *to = ColorUtils::wrapColorAspectsIntoColorTransfer(sfTransfer); - } - return res; -} - -// static -bool C2Mapper::map(int32_t from, C2Color::transfer_t *to) { - // map SDK defined values directly. For other values, use wrapping from ColorUtils. - if (!sColorTransfers.map(from, to)) { - ColorAspects::Transfer sfTransfer; - (void)ColorUtils::unwrapColorAspectsFromColorTransfer(from, &sfTransfer); - - // map known constants and keep vendor extensions. all other values are mapped to 'Other' - if (!sColorTransfersSf.map(sfTransfer, to)) { - // use static cast and ensure it is in the extension range - *to = (C2Color::transfer_t)sfTransfer; - if (*to < C2Color::TRANSFER_VENDOR_START || *to > C2Color::TRANSFER_OTHER) { - *to = C2Color::TRANSFER_OTHER; - return false; - } - } - } - - return true; -} - -// static -bool C2Mapper::map( - C2Color::range_t range, C2Color::primaries_t primaries, - C2Color::matrix_t matrix, C2Color::transfer_t transfer, uint32_t *dataSpace) { -#if 0 - // pure reimplementation - *dataSpace = HAL_DATASPACE_UNKNOWN; // this is 0 - - switch (range) { - case C2Color::RANGE_FULL: *dataSpace |= HAL_DATASPACE_RANGE_FULL; break; - case C2Color::RANGE_LIMITED: *dataSpace |= HAL_DATASPACE_RANGE_LIMITED; break; - default: break; - } - - switch (transfer) { - case C2Color::TRANSFER_LINEAR: *dataSpace |= HAL_DATASPACE_TRANSFER_LINEAR; break; - case C2Color::TRANSFER_SRGB: *dataSpace |= HAL_DATASPACE_TRANSFER_SRGB; break; - case C2Color::TRANSFER_170M: *dataSpace |= HAL_DATASPACE_TRANSFER_SMPTE_170M; break; - case C2Color::TRANSFER_GAMMA22: *dataSpace |= HAL_DATASPACE_TRANSFER_GAMMA2_2; break; - case C2Color::TRANSFER_GAMMA28: *dataSpace |= HAL_DATASPACE_TRANSFER_GAMMA2_8; break; - case C2Color::TRANSFER_ST2084: *dataSpace |= HAL_DATASPACE_TRANSFER_ST2084; break; - case C2Color::TRANSFER_HLG: *dataSpace |= HAL_DATASPACE_TRANSFER_HLG; break; - default: break; - } - - switch (primaries) { - case C2Color::PRIMARIES_BT601_525: - *dataSpace |= (matrix == C2Color::MATRIX_SMPTE240M - || matrix == C2Color::MATRIX_BT709) - ? HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED - : HAL_DATASPACE_STANDARD_BT601_525; - break; - case C2Color::PRIMARIES_BT601_625: - *dataSpace |= (matrix == C2Color::MATRIX_SMPTE240M - || matrix == C2Color::MATRIX_BT709) - ? HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED - : HAL_DATASPACE_STANDARD_BT601_625; - break; - case C2Color::PRIMARIES_BT2020: - *dataSpace |= (matrix == C2Color::MATRIX_BT2020CONSTANT - ? HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE - : HAL_DATASPACE_STANDARD_BT2020); - break; - case C2Color::PRIMARIES_BT470_M: - *dataSpace |= HAL_DATASPACE_STANDARD_BT470M; - break; - case C2Color::PRIMARIES_BT709: - *dataSpace |= HAL_DATASPACE_STANDARD_BT709; - break; - default: break; - } -#else - // for now use legacy implementation - ColorAspects aspects; - if (!sColorRangesSf.map(range, &aspects.mRange)) { - aspects.mRange = ColorAspects::RangeUnspecified; - } - if (!sColorPrimariesSf.map(primaries, &aspects.mPrimaries)) { - aspects.mPrimaries = ColorAspects::PrimariesUnspecified; - } - if (!sColorMatricesSf.map(matrix, &aspects.mMatrixCoeffs)) { - aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; - } - if (!sColorTransfersSf.map(transfer, &aspects.mTransfer)) { - aspects.mTransfer = ColorAspects::TransferUnspecified; - } - *dataSpace = ColorUtils::getDataSpaceForColorAspects(aspects, true /* mayExpand */); -#endif - return true; -} - -// static -bool C2Mapper::map(C2Color::transfer_t from, ColorAspects::Transfer *to) { - return sColorTransfersSf.map(from, to); -} - -// static -bool C2Mapper::map(ColorAspects::Transfer from, C2Color::transfer_t *to) { - return sColorTransfersSf.map(from, to); -} diff --git a/media/sfplugin/utils/Codec2Mapper.h b/media/sfplugin/utils/Codec2Mapper.h deleted file mode 100644 index 1eeb92e..0000000 --- a/media/sfplugin/utils/Codec2Mapper.h +++ /dev/null @@ -1,78 +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 ANDROID_CODEC2_MAPPER_H_ -#define ANDROID_CODEC2_MAPPER_H_ - -#include <C2Config.h> - -#include <media/stagefright/foundation/ColorUtils.h> - -#include <memory> - -namespace android { - - /** - * Utility class to map Codec 2.0 values to android values. - */ - struct C2Mapper { - struct ProfileLevelMapper { - virtual bool mapProfile(C2Config::profile_t, int32_t*) = 0; - virtual bool mapProfile(int32_t, C2Config::profile_t*) = 0; - virtual bool mapLevel(C2Config::level_t, int32_t*) = 0; - virtual bool mapLevel(int32_t, C2Config::level_t*) = 0; - virtual ~ProfileLevelMapper() = default; - }; - - static std::shared_ptr<ProfileLevelMapper> - GetProfileLevelMapper(std::string mediaType); - - // convert between bitrates - static bool map(C2Config::bitrate_mode_t, int32_t*); - static bool map(int32_t, C2Config::bitrate_mode_t*); - - // convert between pcm encodings - static bool map(C2Config::pcm_encoding_t, int32_t*); - static bool map(int32_t, C2Config::pcm_encoding_t*); - - // convert between picture types - static bool map(C2Config::picture_type_t, int32_t*); - static bool map(int32_t, C2Config::picture_type_t*); - - // convert between color aspects - static bool map(C2Color::range_t, int32_t*); - static bool map(int32_t, C2Color::range_t*); - static bool map(C2Color::primaries_t, C2Color::matrix_t, int32_t*); - static bool map(int32_t, C2Color::primaries_t*, C2Color::matrix_t*); - static bool map(C2Color::transfer_t, int32_t*); - static bool map(int32_t, C2Color::transfer_t*); - - static bool map( - C2Color::range_t, C2Color::primaries_t, C2Color::matrix_t, C2Color::transfer_t, - uint32_t *dataSpace); - - static bool map(C2Color::range_t, ColorAspects::Range*); - static bool map(ColorAspects::Range, C2Color::range_t*); - static bool map(C2Color::primaries_t, ColorAspects::Primaries*); - static bool map(ColorAspects::Primaries, C2Color::primaries_t*); - static bool map(C2Color::matrix_t, ColorAspects::MatrixCoeffs*); - static bool map(ColorAspects::MatrixCoeffs, C2Color::matrix_t*); - static bool map(C2Color::transfer_t, ColorAspects::Transfer*); - static bool map(ColorAspects::Transfer, C2Color::transfer_t*); - }; -} - -#endif // ANDROID_CODEC2_MAPPER_H_ |
