Loading include/private/media/AudioTrackShared.h +83 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,83 @@ namespace android { //EL_FIXME 20 seconds may not be enough and must be reconciled with new obtainBuffer implementation #define MAX_RUN_OFFLOADED_TIMEOUT_MS 20000 // assuming up to a maximum of 20 seconds of offloaded // for audio_track_cblk_t::mState, to match TrackBase.h static inline constexpr int CBLK_STATE_IDLE = 0; static inline constexpr int CBLK_STATE_PAUSING = 7; /** * MirroredVariable is a local variable which simultaneously updates * a mirrored storage location. This is useful for server side variables * where a local copy is kept, but a client visible copy is offered through shared memory. * * We use std::atomic as the default container class to access this memory. */ template <typename T, template <typename> class Container = std::atomic> class MirroredVariable { template <typename C> struct Constraints { // If setMirror is used with a different type U != T passed in, // as a general rule, the Container must issue a memcpy to read or write // (or its equivalent) to avoid possible strict aliasing issues. // The memcpy also avoids gaps in structs and alignment issues with different types. static constexpr bool ok_ = false; // Containers must specify constraints. }; template <typename X> struct Constraints<std::atomic<X>> { // Atomics force read and write to memory. static constexpr bool ok = std::is_same_v<X, T> || (std::atomic<X>::is_always_lock_free // no additional locking && sizeof(std::atomic<X>) == sizeof(X) // layout identical to X. && (std::is_arithmetic_v<X> || std::is_enum_v<X>)); // No gaps in the layout. }; static_assert(Constraints<Container<T>>::ok); public: explicit MirroredVariable(const T& t) : t_{t} {} // implicit conversion operator operator T() const { return t_; } MirroredVariable& operator=(const T& t) { t_ = t; if (mirror_ != nullptr) { *mirror_ = t; } return *this; } template <typename U> void setMirror(Container<U> *other_mirror) { // Much of the concern is with T != U, however there are additional concerns // when storage uses shared memory between processes. For atomics, it must be // lock free. static_assert(sizeof(U) == sizeof(T)); static_assert(alignof(U) == alignof(T)); static_assert(Constraints<Container<U>>::ok); static_assert(sizeof(Container<U>) == sizeof(Container<T>)); static_assert(alignof(Container<U>) == alignof(Container<T>)); auto mirror = reinterpret_cast<Container<T>*>(other_mirror); if (mirror_ != mirror) { mirror_ = mirror; if (mirror != nullptr) { *mirror = t_; } } } void clear() { mirror_ = nullptr; } MirroredVariable& operator&() const = delete; protected: T t_{}; Container<T>* mirror_ = nullptr; }; struct AudioTrackSharedStreaming { // similar to NBAIO MonoPipe // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2 Loading Loading @@ -188,6 +265,8 @@ public: volatile int32_t mFlags; // combinations of CBLK_* std::atomic<int32_t> mState; // current TrackBase state. public: union { AudioTrackSharedStreaming mStreaming; Loading @@ -198,6 +277,9 @@ public: // Cache line boundary (32 bytes) }; // TODO: ensure standard layout. // static_assert(std::is_standard_layout_v<audio_track_cblk_t>); // ---------------------------------------------------------------------------- // Proxy for shared memory control block, to isolate callers from needing to know the details. Loading Loading @@ -323,6 +405,7 @@ public: return mEpoch; } int32_t getState() const { return mCblk->mState; } uint32_t getBufferSizeInFrames() const { return mBufferSizeInFrames; } // See documentation for AudioTrack::setBufferSizeInFrames() uint32_t setBufferSizeInFrames(uint32_t requestedSize); Loading media/codec2/components/aac/C2SoftAacDec.cpp +3 −5 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ c2_status_t C2SoftAacDec::onStop() { mOutputDelayRingBufferWritePos = 0; mOutputDelayRingBufferReadPos = 0; mOutputDelayRingBufferFilled = 0; mOutputDelayRingBuffer.reset(); mBuffersInfo.clear(); status_t status = UNKNOWN_ERROR; Loading @@ -308,10 +309,7 @@ void C2SoftAacDec::onRelease() { aacDecoder_Close(mAACDecoder); mAACDecoder = nullptr; } if (mOutputDelayRingBuffer) { delete[] mOutputDelayRingBuffer; mOutputDelayRingBuffer = nullptr; } mOutputDelayRingBuffer.reset(); } status_t C2SoftAacDec::initDecoder() { Loading @@ -327,7 +325,7 @@ status_t C2SoftAacDec::initDecoder() { mOutputDelayCompensated = 0; mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax; mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize]; mOutputDelayRingBuffer.reset(new short[mOutputDelayRingBufferSize]); mOutputDelayRingBufferWritePos = 0; mOutputDelayRingBufferReadPos = 0; mOutputDelayRingBufferFilled = 0; Loading media/codec2/components/aac/C2SoftAacDec.h +1 −1 Original line number Diff line number Diff line Loading @@ -93,7 +93,7 @@ private: bool mEndOfOutput; int32_t mOutputDelayCompensated; int32_t mOutputDelayRingBufferSize; short *mOutputDelayRingBuffer; std::unique_ptr<short[]> mOutputDelayRingBuffer; int32_t mOutputDelayRingBufferWritePos; int32_t mOutputDelayRingBufferReadPos; int32_t mOutputDelayRingBufferFilled; Loading media/codec2/components/mp3/C2SoftMp3Dec.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -413,7 +413,7 @@ void C2SoftMP3::process( mConfig->inputBufferCurrentLength = (inSize - inPos); mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; mConfig->outputFrameSize = (calOutSize - outSize); mConfig->outputFrameSize = (calOutSize - outSize) / sizeof(int16_t); mConfig->pOutputBuffer = reinterpret_cast<int16_t *> (wView.data() + outSize); ERROR_CODE decoderErr; Loading media/codec2/sfplugin/CCodec.cpp +26 −7 Original line number Diff line number Diff line Loading @@ -1579,15 +1579,36 @@ status_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &s // 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); // The output format contains app-configured color aspects, and the input format // has the default color aspects. Use the default for the unspecified params. ColorAspects inputColorAspects, colorAspects; getColorAspectsFromFormat(config->mOutputFormat, colorAspects); getColorAspectsFromFormat(config->mInputFormat, inputColorAspects); if (colorAspects.mRange == ColorAspects::RangeUnspecified) { colorAspects.mRange = inputColorAspects.mRange; } if (colorAspects.mPrimaries == ColorAspects::PrimariesUnspecified) { colorAspects.mPrimaries = inputColorAspects.mPrimaries; } if (colorAspects.mTransfer == ColorAspects::TransferUnspecified) { colorAspects.mTransfer = inputColorAspects.mTransfer; } if (colorAspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified) { colorAspects.mMatrixCoeffs = inputColorAspects.mMatrixCoeffs; } android_dataspace dataSpace = getDataSpaceForColorAspects( colorAspects, /* mayExtend = */ false); surface->setDataSpace(dataSpace); setColorAspectsIntoFormat(colorAspects, config->mInputFormat, /* force = */ true); config->mInputFormat->setInt32("android._dataspace", int32_t(dataSpace)); ALOGD("input format %s to %s", inputFormatChanged ? "changed" : "unchanged", config->mInputFormat->debugString().c_str()); status_t err = mChannel->setInputSurface(surface); if (err != OK) { Loading Loading @@ -2286,8 +2307,6 @@ void CCodec::onMessageReceived(const sp<AMessage> &msg) { const C2ConstGraphicBlock &block = blocks[0]; updates.emplace_back(new C2StreamCropRectInfo::output( stream, block.crop())); updates.emplace_back(new C2StreamPictureSizeInfo::output( stream, block.crop().width, block.crop().height)); } ++stream; } Loading Loading
include/private/media/AudioTrackShared.h +83 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,83 @@ namespace android { //EL_FIXME 20 seconds may not be enough and must be reconciled with new obtainBuffer implementation #define MAX_RUN_OFFLOADED_TIMEOUT_MS 20000 // assuming up to a maximum of 20 seconds of offloaded // for audio_track_cblk_t::mState, to match TrackBase.h static inline constexpr int CBLK_STATE_IDLE = 0; static inline constexpr int CBLK_STATE_PAUSING = 7; /** * MirroredVariable is a local variable which simultaneously updates * a mirrored storage location. This is useful for server side variables * where a local copy is kept, but a client visible copy is offered through shared memory. * * We use std::atomic as the default container class to access this memory. */ template <typename T, template <typename> class Container = std::atomic> class MirroredVariable { template <typename C> struct Constraints { // If setMirror is used with a different type U != T passed in, // as a general rule, the Container must issue a memcpy to read or write // (or its equivalent) to avoid possible strict aliasing issues. // The memcpy also avoids gaps in structs and alignment issues with different types. static constexpr bool ok_ = false; // Containers must specify constraints. }; template <typename X> struct Constraints<std::atomic<X>> { // Atomics force read and write to memory. static constexpr bool ok = std::is_same_v<X, T> || (std::atomic<X>::is_always_lock_free // no additional locking && sizeof(std::atomic<X>) == sizeof(X) // layout identical to X. && (std::is_arithmetic_v<X> || std::is_enum_v<X>)); // No gaps in the layout. }; static_assert(Constraints<Container<T>>::ok); public: explicit MirroredVariable(const T& t) : t_{t} {} // implicit conversion operator operator T() const { return t_; } MirroredVariable& operator=(const T& t) { t_ = t; if (mirror_ != nullptr) { *mirror_ = t; } return *this; } template <typename U> void setMirror(Container<U> *other_mirror) { // Much of the concern is with T != U, however there are additional concerns // when storage uses shared memory between processes. For atomics, it must be // lock free. static_assert(sizeof(U) == sizeof(T)); static_assert(alignof(U) == alignof(T)); static_assert(Constraints<Container<U>>::ok); static_assert(sizeof(Container<U>) == sizeof(Container<T>)); static_assert(alignof(Container<U>) == alignof(Container<T>)); auto mirror = reinterpret_cast<Container<T>*>(other_mirror); if (mirror_ != mirror) { mirror_ = mirror; if (mirror != nullptr) { *mirror = t_; } } } void clear() { mirror_ = nullptr; } MirroredVariable& operator&() const = delete; protected: T t_{}; Container<T>* mirror_ = nullptr; }; struct AudioTrackSharedStreaming { // similar to NBAIO MonoPipe // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2 Loading Loading @@ -188,6 +265,8 @@ public: volatile int32_t mFlags; // combinations of CBLK_* std::atomic<int32_t> mState; // current TrackBase state. public: union { AudioTrackSharedStreaming mStreaming; Loading @@ -198,6 +277,9 @@ public: // Cache line boundary (32 bytes) }; // TODO: ensure standard layout. // static_assert(std::is_standard_layout_v<audio_track_cblk_t>); // ---------------------------------------------------------------------------- // Proxy for shared memory control block, to isolate callers from needing to know the details. Loading Loading @@ -323,6 +405,7 @@ public: return mEpoch; } int32_t getState() const { return mCblk->mState; } uint32_t getBufferSizeInFrames() const { return mBufferSizeInFrames; } // See documentation for AudioTrack::setBufferSizeInFrames() uint32_t setBufferSizeInFrames(uint32_t requestedSize); Loading
media/codec2/components/aac/C2SoftAacDec.cpp +3 −5 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ c2_status_t C2SoftAacDec::onStop() { mOutputDelayRingBufferWritePos = 0; mOutputDelayRingBufferReadPos = 0; mOutputDelayRingBufferFilled = 0; mOutputDelayRingBuffer.reset(); mBuffersInfo.clear(); status_t status = UNKNOWN_ERROR; Loading @@ -308,10 +309,7 @@ void C2SoftAacDec::onRelease() { aacDecoder_Close(mAACDecoder); mAACDecoder = nullptr; } if (mOutputDelayRingBuffer) { delete[] mOutputDelayRingBuffer; mOutputDelayRingBuffer = nullptr; } mOutputDelayRingBuffer.reset(); } status_t C2SoftAacDec::initDecoder() { Loading @@ -327,7 +325,7 @@ status_t C2SoftAacDec::initDecoder() { mOutputDelayCompensated = 0; mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax; mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize]; mOutputDelayRingBuffer.reset(new short[mOutputDelayRingBufferSize]); mOutputDelayRingBufferWritePos = 0; mOutputDelayRingBufferReadPos = 0; mOutputDelayRingBufferFilled = 0; Loading
media/codec2/components/aac/C2SoftAacDec.h +1 −1 Original line number Diff line number Diff line Loading @@ -93,7 +93,7 @@ private: bool mEndOfOutput; int32_t mOutputDelayCompensated; int32_t mOutputDelayRingBufferSize; short *mOutputDelayRingBuffer; std::unique_ptr<short[]> mOutputDelayRingBuffer; int32_t mOutputDelayRingBufferWritePos; int32_t mOutputDelayRingBufferReadPos; int32_t mOutputDelayRingBufferFilled; Loading
media/codec2/components/mp3/C2SoftMp3Dec.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -413,7 +413,7 @@ void C2SoftMP3::process( mConfig->inputBufferCurrentLength = (inSize - inPos); mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; mConfig->outputFrameSize = (calOutSize - outSize); mConfig->outputFrameSize = (calOutSize - outSize) / sizeof(int16_t); mConfig->pOutputBuffer = reinterpret_cast<int16_t *> (wView.data() + outSize); ERROR_CODE decoderErr; Loading
media/codec2/sfplugin/CCodec.cpp +26 −7 Original line number Diff line number Diff line Loading @@ -1579,15 +1579,36 @@ status_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &s // 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); // The output format contains app-configured color aspects, and the input format // has the default color aspects. Use the default for the unspecified params. ColorAspects inputColorAspects, colorAspects; getColorAspectsFromFormat(config->mOutputFormat, colorAspects); getColorAspectsFromFormat(config->mInputFormat, inputColorAspects); if (colorAspects.mRange == ColorAspects::RangeUnspecified) { colorAspects.mRange = inputColorAspects.mRange; } if (colorAspects.mPrimaries == ColorAspects::PrimariesUnspecified) { colorAspects.mPrimaries = inputColorAspects.mPrimaries; } if (colorAspects.mTransfer == ColorAspects::TransferUnspecified) { colorAspects.mTransfer = inputColorAspects.mTransfer; } if (colorAspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified) { colorAspects.mMatrixCoeffs = inputColorAspects.mMatrixCoeffs; } android_dataspace dataSpace = getDataSpaceForColorAspects( colorAspects, /* mayExtend = */ false); surface->setDataSpace(dataSpace); setColorAspectsIntoFormat(colorAspects, config->mInputFormat, /* force = */ true); config->mInputFormat->setInt32("android._dataspace", int32_t(dataSpace)); ALOGD("input format %s to %s", inputFormatChanged ? "changed" : "unchanged", config->mInputFormat->debugString().c_str()); status_t err = mChannel->setInputSurface(surface); if (err != OK) { Loading Loading @@ -2286,8 +2307,6 @@ void CCodec::onMessageReceived(const sp<AMessage> &msg) { const C2ConstGraphicBlock &block = blocks[0]; updates.emplace_back(new C2StreamCropRectInfo::output( stream, block.crop())); updates.emplace_back(new C2StreamPictureSizeInfo::output( stream, block.crop().width, block.crop().height)); } ++stream; } Loading