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 "C2SoftVorbisDec" 19 #include <log/log.h> 20 21 #include <media/stagefright/foundation/MediaDefs.h> 22 23 #include <C2PlatformSupport.h> 24 #include <SimpleC2Interface.h> 25 26 #include "C2SoftVorbisDec.h" 27 28 extern "C" { 29 #include <Tremolo/codec_internal.h> 30 31 int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb); 32 int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb); 33 int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb); 34 } 35 36 namespace android { 37 38 namespace { 39 40 constexpr char COMPONENT_NAME[] = "c2.android.vorbis.decoder"; 41 42 } // namespace 43 44 class C2SoftVorbisDec::IntfImpl : public SimpleInterface<void>::BaseParams { 45 public: 46 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper) 47 : SimpleInterface<void>::BaseParams( 48 helper, 49 COMPONENT_NAME, 50 C2Component::KIND_DECODER, 51 C2Component::DOMAIN_AUDIO, 52 MEDIA_MIMETYPE_AUDIO_VORBIS) { 53 noPrivateBuffers(); 54 noInputReferences(); 55 noOutputReferences(); 56 noInputLatency(); 57 noTimeStretch(); 58 setDerivedInstance(this); 59 60 addParameter( 61 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES) 62 .withConstValue(new C2ComponentAttributesSetting( 63 C2Component::ATTRIB_IS_TEMPORAL)) 64 .build()); 65 66 addParameter( 67 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE) 68 .withDefault(new C2StreamSampleRateInfo::output(0u, 48000)) 69 .withFields({C2F(mSampleRate, value).inRange(8000, 96000)}) 70 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) 71 .build()); 72 73 addParameter( 74 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT) 75 .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) 76 .withFields({C2F(mChannelCount, value).inRange(1, 8)}) 77 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) 78 .build()); 79 80 addParameter( 81 DefineParam(mBitrate, C2_PARAMKEY_BITRATE) 82 .withDefault(new C2StreamBitrateInfo::input(0u, 64000)) 83 .withFields({C2F(mBitrate, value).inRange(32000, 500000)}) 84 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) 85 .build()); 86 87 addParameter( 88 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE) 89 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192 * 2 * sizeof(int16_t))) 90 .build()); 91 } 92 93 private: 94 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; 95 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; 96 std::shared_ptr<C2StreamBitrateInfo::input> mBitrate; 97 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize; 98 }; 99 100 C2SoftVorbisDec::C2SoftVorbisDec( 101 const char *name, 102 c2_node_id_t id, 103 const std::shared_ptr<IntfImpl> &intfImpl) 104 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), 105 mIntf(intfImpl), 106 mState(nullptr), 107 mVi(nullptr) { 108 } 109 110 C2SoftVorbisDec::~C2SoftVorbisDec() { 111 onRelease(); 112 } 113 114 c2_status_t C2SoftVorbisDec::onInit() { 115 status_t err = initDecoder(); 116 return err == OK ? C2_OK : C2_NO_MEMORY; 117 } 118 119 c2_status_t C2SoftVorbisDec::onStop() { 120 if (mState) { 121 vorbis_dsp_clear(mState); 122 delete mState; 123 mState = nullptr; 124 } 125 126 if (mVi) { 127 vorbis_info_clear(mVi); 128 delete mVi; 129 mVi = nullptr; 130 } 131 mNumFramesLeftOnPage = -1; 132 mSignalledOutputEos = false; 133 mSignalledError = false; 134 135 return (initDecoder() == OK ? C2_OK : C2_CORRUPTED); 136 } 137 138 void C2SoftVorbisDec::onReset() { 139 (void)onStop(); 140 } 141 142 void C2SoftVorbisDec::onRelease() { 143 if (mState) { 144 vorbis_dsp_clear(mState); 145 delete mState; 146 mState = nullptr; 147 } 148 149 if (mVi) { 150 vorbis_info_clear(mVi); 151 delete mVi; 152 mVi = nullptr; 153 } 154 } 155 156 status_t C2SoftVorbisDec::initDecoder() { 157 mVi = new vorbis_info{}; 158 if (!mVi) return NO_MEMORY; 159 vorbis_info_clear(mVi); 160 161 mState = new vorbis_dsp_state{}; 162 if (!mState) return NO_MEMORY; 163 vorbis_dsp_clear(mState); 164 165 mNumFramesLeftOnPage = -1; 166 mSignalledError = false; 167 mSignalledOutputEos = false; 168 mInfoUnpacked = false; 169 mBooksUnpacked = false; 170 return OK; 171 } 172 173 c2_status_t C2SoftVorbisDec::onFlush_sm() { 174 mNumFramesLeftOnPage = -1; 175 mSignalledOutputEos = false; 176 if (mState) vorbis_dsp_restart(mState); 177 178 return C2_OK; 179 } 180 181 c2_status_t C2SoftVorbisDec::drain( 182 uint32_t drainMode, 183 const std::shared_ptr<C2BlockPool> &pool) { 184 (void) pool; 185 if (drainMode == NO_DRAIN) { 186 ALOGW("drain with NO_DRAIN: no-op"); 187 return C2_OK; 188 } 189 if (drainMode == DRAIN_CHAIN) { 190 ALOGW("DRAIN_CHAIN not supported"); 191 return C2_OMITTED; 192 } 193 194 return C2_OK; 195 } 196 197 static void fillEmptyWork(const std::unique_ptr<C2Work> &work) { 198 work->worklets.front()->output.flags = work->input.flags; 199 work->worklets.front()->output.buffers.clear(); 200 work->worklets.front()->output.ordinal = work->input.ordinal; 201 work->workletsProcessed = 1u; 202 } 203 204 static void makeBitReader( 205 const void *data, size_t size, 206 ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) { 207 buf->data = (uint8_t *)data; 208 buf->size = size; 209 buf->refcount = 1; 210 buf->ptr.owner = nullptr; 211 212 ref->buffer = buf; 213 ref->begin = 0; 214 ref->length = size; 215 ref->next = nullptr; 216 217 oggpack_readinit(bits, ref); 218 } 219 220 // (CHECK!) multiframe is tricky. decode call doesnt return the number of bytes 221 // consumed by the component. Also it is unclear why numPageFrames is being 222 // tagged at the end of input buffers for new pages. Refer lines 297-300 in 223 // SimpleDecodingSource.cpp 224 void C2SoftVorbisDec::process( 225 const std::unique_ptr<C2Work> &work, 226 const std::shared_ptr<C2BlockPool> &pool) { 227 // Initialize output work 228 work->result = C2_OK; 229 work->workletsProcessed = 1u; 230 work->worklets.front()->output.configUpdate.clear(); 231 work->worklets.front()->output.flags = work->input.flags; 232 233 if (mSignalledError || mSignalledOutputEos) { 234 work->result = C2_BAD_VALUE; 235 return; 236 } 237 238 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); 239 size_t inOffset = 0u; 240 size_t inSize = 0u; 241 C2ReadView rView = mDummyReadView; 242 if (!work->input.buffers.empty()) { 243 rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); 244 inSize = rView.capacity(); 245 if (inSize && rView.error()) { 246 ALOGE("read view map failed %d", rView.error()); 247 work->result = rView.error(); 248 return; 249 } 250 } 251 252 if (inSize == 0) { 253 fillEmptyWork(work); 254 if (eos) { 255 mSignalledOutputEos = true; 256 ALOGV("signalled EOS"); 257 } 258 return; 259 } 260 261 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize, 262 (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku()); 263 const uint8_t *data = rView.data() + inOffset; 264 int32_t numChannels = mVi->channels; 265 int32_t samplingRate = mVi->rate; 266 /* Decode vorbis headers only once */ 267 if (inSize > 7 && !memcmp(&data[1], "vorbis", 6) && (!mInfoUnpacked || !mBooksUnpacked)) { 268 if ((data[0] != 1) && (data[0] != 5)) { 269 ALOGE("unexpected type received %d", data[0]); 270 mSignalledError = true; 271 work->result = C2_CORRUPTED; 272 return; 273 } 274 275 ogg_buffer buf; 276 ogg_reference ref; 277 oggpack_buffer bits; 278 279 // skip 7 <type + "vorbis"> bytes 280 makeBitReader((const uint8_t *)data + 7, inSize - 7, &buf, &ref, &bits); 281 if (data[0] == 1) { 282 vorbis_info_init(mVi); 283 if (0 != _vorbis_unpack_info(mVi, &bits)) { 284 ALOGE("Encountered error while unpacking info"); 285 mSignalledError = true; 286 work->result = C2_CORRUPTED; 287 return; 288 } 289 if (mVi->rate != samplingRate || 290 mVi->channels != numChannels) { 291 ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels); 292 samplingRate = mVi->rate; 293 numChannels = mVi->channels; 294 295 C2StreamSampleRateInfo::output sampleRateInfo(0u, samplingRate); 296 C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels); 297 std::vector<std::unique_ptr<C2SettingResult>> failures; 298 c2_status_t err = mIntf->config( 299 { &sampleRateInfo, &channelCountInfo }, 300 C2_MAY_BLOCK, 301 &failures); 302 if (err == OK) { 303 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(sampleRateInfo)); 304 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(channelCountInfo)); 305 } else { 306 ALOGE("Config Update failed"); 307 mSignalledError = true; 308 work->result = C2_CORRUPTED; 309 return; 310 } 311 } 312 mInfoUnpacked = true; 313 } else { 314 if (!mInfoUnpacked) { 315 ALOGE("Data with type:5 sent before sending type:1"); 316 mSignalledError = true; 317 work->result = C2_CORRUPTED; 318 return; 319 } 320 if (0 != _vorbis_unpack_books(mVi, &bits)) { 321 ALOGE("Encountered error while unpacking books"); 322 mSignalledError = true; 323 work->result = C2_CORRUPTED; 324 return; 325 } 326 if (0 != vorbis_dsp_init(mState, mVi)) { 327 ALOGE("Encountered error while dsp init"); 328 mSignalledError = true; 329 work->result = C2_CORRUPTED; 330 return; 331 } 332 mBooksUnpacked = true; 333 } 334 fillEmptyWork(work); 335 if (eos) { 336 mSignalledOutputEos = true; 337 ALOGV("signalled EOS"); 338 } 339 return; 340 } 341 342 if (!mInfoUnpacked || !mBooksUnpacked) { 343 ALOGE("Missing CODEC_CONFIG data mInfoUnpacked: %d mBooksUnpack %d", mInfoUnpacked, mBooksUnpacked); 344 mSignalledError = true; 345 work->result = C2_CORRUPTED; 346 return; 347 } 348 349 int32_t numPageFrames = 0; 350 if (inSize < sizeof(numPageFrames)) { 351 ALOGE("input header has size %zu, expected %zu", inSize, sizeof(numPageFrames)); 352 mSignalledError = true; 353 work->result = C2_CORRUPTED; 354 return; 355 } 356 memcpy(&numPageFrames, data + inSize - sizeof(numPageFrames), sizeof(numPageFrames)); 357 inSize -= sizeof(numPageFrames); 358 if (numPageFrames >= 0) { 359 mNumFramesLeftOnPage = numPageFrames; 360 } 361 362 ogg_buffer buf; 363 buf.data = const_cast<unsigned char*>(data); 364 buf.size = inSize; 365 buf.refcount = 1; 366 buf.ptr.owner = nullptr; 367 368 ogg_reference ref; 369 ref.buffer = &buf; 370 ref.begin = 0; 371 ref.length = buf.size; 372 ref.next = nullptr; 373 374 ogg_packet pack; 375 pack.packet = &ref; 376 pack.bytes = ref.length; 377 pack.b_o_s = 0; 378 pack.e_o_s = 0; 379 pack.granulepos = 0; 380 pack.packetno = 0; 381 382 size_t maxSamplesInBuffer = kMaxNumSamplesPerChannel * mVi->channels; 383 size_t outCapacity = maxSamplesInBuffer * sizeof(int16_t); 384 std::shared_ptr<C2LinearBlock> block; 385 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }; 386 c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &block); 387 if (err != C2_OK) { 388 ALOGE("fetchLinearBlock for Output failed with status %d", err); 389 work->result = C2_NO_MEMORY; 390 return; 391 } 392 C2WriteView wView = block->map().get(); 393 if (wView.error()) { 394 ALOGE("write view map failed %d", wView.error()); 395 work->result = wView.error(); 396 return; 397 } 398 399 int numFrames = 0; 400 int ret = vorbis_dsp_synthesis(mState, &pack, 1); 401 if (0 != ret) { 402 ALOGD("vorbis_dsp_synthesis returned %d; ignored", ret); 403 } else { 404 numFrames = vorbis_dsp_pcmout( 405 mState, reinterpret_cast<int16_t *> (wView.data()), 406 kMaxNumSamplesPerChannel); 407 if (numFrames < 0) { 408 ALOGD("vorbis_dsp_pcmout returned %d", numFrames); 409 numFrames = 0; 410 } 411 } 412 413 if (mNumFramesLeftOnPage >= 0) { 414 if (numFrames > mNumFramesLeftOnPage) { 415 ALOGV("discarding %d frames at end of page", numFrames - mNumFramesLeftOnPage); 416 numFrames = mNumFramesLeftOnPage; 417 } 418 mNumFramesLeftOnPage -= numFrames; 419 } 420 421 if (numFrames) { 422 int outSize = numFrames * sizeof(int16_t) * mVi->channels; 423 424 work->worklets.front()->output.flags = work->input.flags; 425 work->worklets.front()->output.buffers.clear(); 426 work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, 0, outSize)); 427 work->worklets.front()->output.ordinal = work->input.ordinal; 428 work->workletsProcessed = 1u; 429 } else { 430 fillEmptyWork(work); 431 block.reset(); 432 } 433 if (eos) { 434 mSignalledOutputEos = true; 435 ALOGV("signalled EOS"); 436 } 437 } 438 439 class C2SoftVorbisDecFactory : public C2ComponentFactory { 440 public: 441 C2SoftVorbisDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( 442 GetCodec2PlatformComponentStore()->getParamReflector())) { 443 } 444 445 virtual c2_status_t createComponent( 446 c2_node_id_t id, 447 std::shared_ptr<C2Component>* const component, 448 std::function<void(C2Component*)> deleter) override { 449 *component = std::shared_ptr<C2Component>( 450 new C2SoftVorbisDec(COMPONENT_NAME, 451 id, 452 std::make_shared<C2SoftVorbisDec::IntfImpl>(mHelper)), 453 deleter); 454 return C2_OK; 455 } 456 457 virtual c2_status_t createInterface( 458 c2_node_id_t id, 459 std::shared_ptr<C2ComponentInterface>* const interface, 460 std::function<void(C2ComponentInterface*)> deleter) override { 461 *interface = std::shared_ptr<C2ComponentInterface>( 462 new SimpleInterface<C2SoftVorbisDec::IntfImpl>( 463 COMPONENT_NAME, id, std::make_shared<C2SoftVorbisDec::IntfImpl>(mHelper)), 464 deleter); 465 return C2_OK; 466 } 467 468 virtual ~C2SoftVorbisDecFactory() override = default; 469 470 private: 471 std::shared_ptr<C2ReflectorHelper> mHelper; 472 }; 473 474 } // namespace android 475 476 extern "C" ::C2ComponentFactory* CreateCodec2Factory() { 477 ALOGV("in %s", __func__); 478 return new ::android::C2SoftVorbisDecFactory(); 479 } 480 481 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) { 482 ALOGV("in %s", __func__); 483 delete factory; 484 } 485