| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2018 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | //#define LOG_NDEBUG 0 | 
 | 18 | #define LOG_TAG "C2SoftG711Dec" | 
 | 19 | #include <log/log.h> | 
 | 20 |  | 
 | 21 | #include <media/stagefright/foundation/MediaDefs.h> | 
 | 22 |  | 
 | 23 | #include <C2PlatformSupport.h> | 
 | 24 | #include <SimpleC2Interface.h> | 
| Ayushi Khopkar | 97ac9e6 | 2020-04-02 09:54:01 +0530 | [diff] [blame] | 25 | #include <g711Dec.h> | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 26 | #include "C2SoftG711Dec.h" | 
 | 27 |  | 
 | 28 | namespace android { | 
 | 29 |  | 
| Rakesh Kumar | ed13464 | 2019-03-12 14:18:42 +0530 | [diff] [blame] | 30 | namespace { | 
 | 31 |  | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 32 | #ifdef ALAW | 
 | 33 | constexpr char COMPONENT_NAME[] = "c2.android.g711.alaw.decoder"; | 
 | 34 | #else | 
 | 35 | constexpr char COMPONENT_NAME[] = "c2.android.g711.mlaw.decoder"; | 
 | 36 | #endif | 
 | 37 |  | 
| Rakesh Kumar | ed13464 | 2019-03-12 14:18:42 +0530 | [diff] [blame] | 38 | }  // namespace | 
 | 39 |  | 
 | 40 | class C2SoftG711Dec::IntfImpl : public SimpleInterface<void>::BaseParams { | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 41 | public: | 
 | 42 |     explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) | 
| Rakesh Kumar | ed13464 | 2019-03-12 14:18:42 +0530 | [diff] [blame] | 43 |         : SimpleInterface<void>::BaseParams( | 
 | 44 |                 helper, | 
 | 45 |                 COMPONENT_NAME, | 
 | 46 |                 C2Component::KIND_DECODER, | 
 | 47 |                 C2Component::DOMAIN_AUDIO, | 
 | 48 | #ifdef ALAW | 
 | 49 |                 MEDIA_MIMETYPE_AUDIO_G711_ALAW | 
 | 50 | #else | 
 | 51 |                 MEDIA_MIMETYPE_AUDIO_G711_MLAW | 
 | 52 | #endif | 
 | 53 |                 ) { | 
 | 54 |         noPrivateBuffers(); | 
 | 55 |         noInputReferences(); | 
 | 56 |         noOutputReferences(); | 
 | 57 |         noInputLatency(); | 
 | 58 |         noTimeStretch(); | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 59 |         setDerivedInstance(this); | 
 | 60 |  | 
 | 61 |         addParameter( | 
| Rakesh Kumar | ed13464 | 2019-03-12 14:18:42 +0530 | [diff] [blame] | 62 |                 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES) | 
 | 63 |                 .withConstValue(new C2ComponentAttributesSetting( | 
 | 64 |                     C2Component::ATTRIB_IS_TEMPORAL)) | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 65 |                 .build()); | 
 | 66 |  | 
 | 67 |         addParameter( | 
| Lajos Molnar | 3bb81cd | 2019-02-20 15:10:30 -0800 | [diff] [blame] | 68 |                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE) | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 69 |                 .withDefault(new C2StreamSampleRateInfo::output(0u, 8000)) | 
 | 70 |                 .withFields({C2F(mSampleRate, value).inRange(8000, 48000)}) | 
 | 71 |                 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) | 
 | 72 |                 .build()); | 
 | 73 |  | 
 | 74 |         addParameter( | 
| Lajos Molnar | 3bb81cd | 2019-02-20 15:10:30 -0800 | [diff] [blame] | 75 |                 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT) | 
| Ray Essick | e944946 | 2019-10-22 13:33:29 -0700 | [diff] [blame] | 76 |                 .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) | 
 | 77 |                 .withFields({C2F(mChannelCount, value).inRange(1, 6)}) | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 78 |                 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) | 
 | 79 |                 .build()); | 
 | 80 |  | 
 | 81 |         addParameter( | 
| Lajos Molnar | 3bb81cd | 2019-02-20 15:10:30 -0800 | [diff] [blame] | 82 |                 DefineParam(mBitrate, C2_PARAMKEY_BITRATE) | 
 | 83 |                 .withDefault(new C2StreamBitrateInfo::input(0u, 64000)) | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 84 |                 .withFields({C2F(mBitrate, value).equalTo(64000)}) | 
 | 85 |                 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) | 
 | 86 |                 .build()); | 
 | 87 |  | 
 | 88 |         addParameter( | 
 | 89 |                 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) | 
 | 90 |                 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192)) | 
 | 91 |                 .build()); | 
 | 92 |     } | 
 | 93 |  | 
 | 94 | private: | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 95 |     std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; | 
 | 96 |     std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; | 
| Lajos Molnar | 3bb81cd | 2019-02-20 15:10:30 -0800 | [diff] [blame] | 97 |     std::shared_ptr<C2StreamBitrateInfo::input> mBitrate; | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 98 |     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; | 
 | 99 | }; | 
 | 100 |  | 
 | 101 | C2SoftG711Dec::C2SoftG711Dec( | 
 | 102 |         const char *name, | 
 | 103 |         c2_node_id_t id, | 
 | 104 |         const std::shared_ptr<IntfImpl> &intfImpl) | 
 | 105 |     : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), | 
 | 106 |       mIntf(intfImpl) { | 
 | 107 | } | 
 | 108 |  | 
 | 109 | C2SoftG711Dec::~C2SoftG711Dec() { | 
 | 110 |     onRelease(); | 
 | 111 | } | 
 | 112 |  | 
 | 113 | c2_status_t C2SoftG711Dec::onInit() { | 
 | 114 |     mSignalledOutputEos = false; | 
 | 115 |     return C2_OK; | 
 | 116 | } | 
 | 117 |  | 
 | 118 | c2_status_t C2SoftG711Dec::onStop() { | 
 | 119 |     mSignalledOutputEos = false; | 
 | 120 |     return C2_OK; | 
 | 121 | } | 
 | 122 |  | 
 | 123 | void C2SoftG711Dec::onReset() { | 
 | 124 |     (void)onStop(); | 
 | 125 | } | 
 | 126 |  | 
 | 127 | void C2SoftG711Dec::onRelease() { | 
 | 128 | } | 
 | 129 |  | 
 | 130 | c2_status_t C2SoftG711Dec::onFlush_sm() { | 
 | 131 |     return onStop(); | 
 | 132 | } | 
 | 133 |  | 
 | 134 | void C2SoftG711Dec::process( | 
 | 135 |         const std::unique_ptr<C2Work> &work, | 
 | 136 |         const std::shared_ptr<C2BlockPool> &pool) { | 
 | 137 |     // Initialize output work | 
 | 138 |     work->result = C2_OK; | 
 | 139 |     work->workletsProcessed = 1u; | 
 | 140 |     work->worklets.front()->output.flags = work->input.flags; | 
 | 141 |  | 
 | 142 |     if (mSignalledOutputEos) { | 
 | 143 |         work->result = C2_BAD_VALUE; | 
 | 144 |         return; | 
 | 145 |     } | 
 | 146 |  | 
 | 147 |     C2ReadView rView = mDummyReadView; | 
 | 148 |     size_t inOffset = 0u; | 
 | 149 |     size_t inSize = 0u; | 
 | 150 |     if (!work->input.buffers.empty()) { | 
 | 151 |         rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); | 
 | 152 |         inSize = rView.capacity(); | 
 | 153 |         if (inSize && rView.error()) { | 
 | 154 |             ALOGE("read view map failed %d", rView.error()); | 
 | 155 |             work->result = C2_CORRUPTED; | 
 | 156 |             return; | 
 | 157 |         } | 
 | 158 |     } | 
 | 159 |     bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; | 
 | 160 |     int outSize = inSize * sizeof(int16_t); | 
 | 161 |  | 
 | 162 |     ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize, | 
 | 163 |           (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku()); | 
 | 164 |  | 
 | 165 |     if (inSize == 0) { | 
 | 166 |         work->worklets.front()->output.flags = work->input.flags; | 
 | 167 |         work->worklets.front()->output.buffers.clear(); | 
 | 168 |         work->worklets.front()->output.ordinal = work->input.ordinal; | 
 | 169 |         if (eos) { | 
 | 170 |             mSignalledOutputEos = true; | 
 | 171 |             ALOGV("signalled EOS"); | 
 | 172 |         } | 
 | 173 |         return; | 
 | 174 |     } | 
 | 175 |  | 
 | 176 |     uint8_t *inputptr = const_cast<uint8_t *>(rView.data() + inOffset); | 
 | 177 |  | 
 | 178 |     std::shared_ptr<C2LinearBlock> block; | 
 | 179 |     C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }; | 
 | 180 |     c2_status_t err = pool->fetchLinearBlock(outSize, usage, &block); | 
 | 181 |     if (err != C2_OK) { | 
 | 182 |         ALOGE("fetchLinearBlock for Output failed with status %d", err); | 
 | 183 |         work->result = C2_NO_MEMORY; | 
 | 184 |         return; | 
 | 185 |     } | 
 | 186 |     C2WriteView wView = block->map().get(); | 
 | 187 |     if (wView.error()) { | 
 | 188 |         ALOGE("write view map failed %d", wView.error()); | 
 | 189 |         work->result = C2_CORRUPTED; | 
 | 190 |         return; | 
 | 191 |     } | 
 | 192 |     int16_t *outputptr = reinterpret_cast<int16_t *>(wView.data()); | 
 | 193 |  | 
 | 194 | #ifdef ALAW | 
 | 195 |     DecodeALaw(outputptr, inputptr, inSize); | 
 | 196 | #else | 
 | 197 |     DecodeMLaw(outputptr, inputptr, inSize); | 
 | 198 | #endif | 
 | 199 |  | 
 | 200 |     work->worklets.front()->output.flags = work->input.flags; | 
 | 201 |     work->worklets.front()->output.buffers.clear(); | 
 | 202 |     work->worklets.front()->output.buffers.push_back(createLinearBuffer(block)); | 
 | 203 |     work->worklets.front()->output.ordinal = work->input.ordinal; | 
 | 204 |  | 
 | 205 |     if (eos) { | 
 | 206 |         mSignalledOutputEos = true; | 
 | 207 |         ALOGV("signalled EOS"); | 
 | 208 |     } | 
 | 209 | } | 
 | 210 |  | 
 | 211 | c2_status_t C2SoftG711Dec::drain( | 
 | 212 |         uint32_t drainMode, | 
 | 213 |         const std::shared_ptr<C2BlockPool> &pool) { | 
 | 214 |     (void) pool; | 
 | 215 |     if (drainMode == NO_DRAIN) { | 
 | 216 |         ALOGW("drain with NO_DRAIN: no-op"); | 
 | 217 |         return C2_OK; | 
 | 218 |     } | 
 | 219 |     if (drainMode == DRAIN_CHAIN) { | 
 | 220 |         ALOGW("DRAIN_CHAIN not supported"); | 
 | 221 |         return C2_OMITTED; | 
 | 222 |     } | 
 | 223 |  | 
 | 224 |     return C2_OK; | 
 | 225 | } | 
 | 226 |  | 
| Pawin Vongmasa | 3665390 | 2018-11-15 00:10:25 -0800 | [diff] [blame] | 227 | class C2SoftG711DecFactory : public C2ComponentFactory { | 
 | 228 | public: | 
 | 229 |     C2SoftG711DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( | 
 | 230 |             GetCodec2PlatformComponentStore()->getParamReflector())) { | 
 | 231 |     } | 
 | 232 |  | 
 | 233 |     virtual c2_status_t createComponent( | 
 | 234 |             c2_node_id_t id, | 
 | 235 |             std::shared_ptr<C2Component>* const component, | 
 | 236 |             std::function<void(C2Component*)> deleter) override { | 
 | 237 |         *component = std::shared_ptr<C2Component>( | 
 | 238 |                 new C2SoftG711Dec(COMPONENT_NAME, id, | 
 | 239 |                                std::make_shared<C2SoftG711Dec::IntfImpl>(mHelper)), | 
 | 240 |                 deleter); | 
 | 241 |         return C2_OK; | 
 | 242 |     } | 
 | 243 |  | 
 | 244 |     virtual c2_status_t createInterface( | 
 | 245 |             c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface, | 
 | 246 |             std::function<void(C2ComponentInterface*)> deleter) override { | 
 | 247 |         *interface = std::shared_ptr<C2ComponentInterface>( | 
 | 248 |                 new SimpleInterface<C2SoftG711Dec::IntfImpl>( | 
 | 249 |                         COMPONENT_NAME, id, std::make_shared<C2SoftG711Dec::IntfImpl>(mHelper)), | 
 | 250 |                 deleter); | 
 | 251 |         return C2_OK; | 
 | 252 |     } | 
 | 253 |  | 
 | 254 |     virtual ~C2SoftG711DecFactory() override = default; | 
 | 255 |  | 
 | 256 | private: | 
 | 257 |     std::shared_ptr<C2ReflectorHelper> mHelper; | 
 | 258 | }; | 
 | 259 |  | 
 | 260 | }  // namespace android | 
 | 261 |  | 
 | 262 | extern "C" ::C2ComponentFactory* CreateCodec2Factory() { | 
 | 263 |     ALOGV("in %s", __func__); | 
 | 264 |     return new ::android::C2SoftG711DecFactory(); | 
 | 265 | } | 
 | 266 |  | 
 | 267 | extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) { | 
 | 268 |     ALOGV("in %s", __func__); | 
 | 269 |     delete factory; | 
 | 270 | } |