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 "C2SoftOpusDec" 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 "C2SoftOpusDec.h" 27 28extern "C" { 29 #include <opus.h> 30 #include <opus_multistream.h> 31} 32 33namespace android { 34 35constexpr char COMPONENT_NAME[] = "c2.android.opus.decoder"; 36 37class C2SoftOpusDec::IntfImpl : public C2InterfaceHelper { 38 public: 39 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper) 40 : C2InterfaceHelper(helper) { 41 setDerivedInstance(this); 42 43 addParameter( 44 DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING) 45 .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed)) 46 .build()); 47 48 addParameter( 49 DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING) 50 .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio)) 51 .build()); 52 53 addParameter( 54 DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING) 55 .withConstValue(AllocSharedString<C2PortMimeConfig::input>( 56 MEDIA_MIMETYPE_AUDIO_OPUS)) 57 .build()); 58 59 addParameter( 60 DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING) 61 .withConstValue(AllocSharedString<C2PortMimeConfig::output>( 62 MEDIA_MIMETYPE_AUDIO_RAW)) 63 .build()); 64 65 addParameter( 66 DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING) 67 .withDefault(new C2StreamSampleRateInfo::output(0u, 48000)) 68 .withFields({C2F(mSampleRate, value).equalTo(48000)}) 69 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) 70 .build()); 71 72 addParameter( 73 DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING) 74 .withDefault(new C2StreamChannelCountInfo::output(0u, 1)) 75 .withFields({C2F(mChannelCount, value).inRange(1, 8)}) 76 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps) 77 .build()); 78 79 addParameter( 80 DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING) 81 .withDefault(new C2BitrateTuning::input(0u, 6000)) 82 .withFields({C2F(mBitrate, value).inRange(6000, 510000)}) 83 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps) 84 .build()); 85 } 86 87 private: 88 std::shared_ptr<C2StreamFormatConfig::input> mInputFormat; 89 std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat; 90 std::shared_ptr<C2PortMimeConfig::input> mInputMediaType; 91 std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType; 92 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate; 93 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount; 94 std::shared_ptr<C2BitrateTuning::input> mBitrate; 95}; 96 97C2SoftOpusDec::C2SoftOpusDec(const char *name, c2_node_id_t id, 98 const std::shared_ptr<IntfImpl>& intfImpl) 99 : SimpleC2Component( 100 std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)), 101 mIntf(intfImpl), 102 mDecoder(nullptr) { 103} 104 105C2SoftOpusDec::~C2SoftOpusDec() { 106 onRelease(); 107} 108 109c2_status_t C2SoftOpusDec::onInit() { 110 status_t err = initDecoder(); 111 return err == OK ? C2_OK : C2_NO_MEMORY; 112} 113 114c2_status_t C2SoftOpusDec::onStop() { 115 if (mDecoder) { 116 opus_multistream_decoder_destroy(mDecoder); 117 mDecoder = nullptr; 118 } 119 memset(&mHeader, 0, sizeof(mHeader)); 120 mCodecDelay = 0; 121 mSeekPreRoll = 0; 122 mSamplesToDiscard = 0; 123 mInputBufferCount = 0; 124 mSignalledError = false; 125 mSignalledOutputEos = false; 126 127 return C2_OK; 128} 129 130void C2SoftOpusDec::onReset() { 131 (void)onStop(); 132} 133 134void C2SoftOpusDec::onRelease() { 135 if (mDecoder) { 136 opus_multistream_decoder_destroy(mDecoder); 137 mDecoder = nullptr; 138 } 139} 140 141status_t C2SoftOpusDec::initDecoder() { 142 memset(&mHeader, 0, sizeof(mHeader)); 143 mCodecDelay = 0; 144 mSeekPreRoll = 0; 145 mSamplesToDiscard = 0; 146 mInputBufferCount = 0; 147 mSignalledError = false; 148 mSignalledOutputEos = false; 149 150 return OK; 151} 152 153c2_status_t C2SoftOpusDec::onFlush_sm() { 154 if (mDecoder) { 155 opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE); 156 mSamplesToDiscard = mSeekPreRoll; 157 mSignalledOutputEos = false; 158 } 159 return C2_OK; 160} 161 162c2_status_t C2SoftOpusDec::drain( 163 uint32_t drainMode, 164 const std::shared_ptr<C2BlockPool> &pool) { 165 (void) pool; 166 if (drainMode == NO_DRAIN) { 167 ALOGW("drain with NO_DRAIN: no-op"); 168 return C2_OK; 169 } 170 if (drainMode == DRAIN_CHAIN) { 171 ALOGW("DRAIN_CHAIN not supported"); 172 return C2_OMITTED; 173 } 174 175 return C2_OK; 176} 177 178static void fillEmptyWork(const std::unique_ptr<C2Work> &work) { 179 work->worklets.front()->output.flags = work->input.flags; 180 work->worklets.front()->output.buffers.clear(); 181 work->worklets.front()->output.ordinal = work->input.ordinal; 182 work->workletsProcessed = 1u; 183} 184 185static uint16_t ReadLE16(const uint8_t *data, size_t data_size, 186 uint32_t read_offset) { 187 if (read_offset + 1 > data_size) 188 return 0; 189 uint16_t val; 190 val = data[read_offset]; 191 val |= data[read_offset + 1] << 8; 192 return val; 193} 194 195static const int kRate = 48000; 196 197// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies 198// mappings for up to 8 channels. This information is part of the Vorbis I 199// Specification: 200// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html 201static const int kMaxChannels = 8; 202 203// Maximum packet size used in Xiph's opusdec. 204static const int kMaxOpusOutputPacketSizeSamples = 960 * 6; 205 206// Default audio output channel layout. Used to initialize |stream_map| in 207// OpusHeader, and passed to opus_multistream_decoder_create() when the header 208// does not contain mapping information. The values are valid only for mono and 209// stereo output: Opus streams with more than 2 channels require a stream map. 210static const int kMaxChannelsWithDefaultLayout = 2; 211static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 }; 212 213// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header 214static bool ParseOpusHeader(const uint8_t *data, size_t data_size, 215 OpusHeader* header) { 216 // Size of the Opus header excluding optional mapping information. 217 const size_t kOpusHeaderSize = 19; 218 219 // Offset to the channel count byte in the Opus header. 220 const size_t kOpusHeaderChannelsOffset = 9; 221 222 // Offset to the pre-skip value in the Opus header. 223 const size_t kOpusHeaderSkipSamplesOffset = 10; 224 225 // Offset to the gain value in the Opus header. 226 const size_t kOpusHeaderGainOffset = 16; 227 228 // Offset to the channel mapping byte in the Opus header. 229 const size_t kOpusHeaderChannelMappingOffset = 18; 230 231 // Opus Header contains a stream map. The mapping values are in the header 232 // beyond the always present |kOpusHeaderSize| bytes of data. The mapping 233 // data contains stream count, coupling information, and per channel mapping 234 // values: 235 // - Byte 0: Number of streams. 236 // - Byte 1: Number coupled. 237 // - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping 238 // values. 239 const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize; 240 const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1; 241 const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2; 242 243 if (data_size < kOpusHeaderSize) { 244 ALOGE("Header size is too small."); 245 return false; 246 } 247 header->channels = *(data + kOpusHeaderChannelsOffset); 248 if (header->channels <= 0 || header->channels > kMaxChannels) { 249 ALOGE("Invalid Header, wrong channel count: %d", header->channels); 250 return false; 251 } 252 253 header->skip_samples = ReadLE16(data, 254 data_size, 255 kOpusHeaderSkipSamplesOffset); 256 257 header->gain_db = static_cast<int16_t>(ReadLE16(data, 258 data_size, 259 kOpusHeaderGainOffset)); 260 261 header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset); 262 if (!header->channel_mapping) { 263 if (header->channels > kMaxChannelsWithDefaultLayout) { 264 ALOGE("Invalid Header, missing stream map."); 265 return false; 266 } 267 header->num_streams = 1; 268 header->num_coupled = header->channels > 1; 269 header->stream_map[0] = 0; 270 header->stream_map[1] = 1; 271 return true; 272 } 273 if (data_size < kOpusHeaderStreamMapOffset + header->channels) { 274 ALOGE("Invalid stream map; insufficient data for current channel " 275 "count: %d", header->channels); 276 return false; 277 } 278 header->num_streams = *(data + kOpusHeaderNumStreamsOffset); 279 header->num_coupled = *(data + kOpusHeaderNumCoupledOffset); 280 if (header->num_streams + header->num_coupled != header->channels) { 281 ALOGE("Inconsistent channel mapping."); 282 return false; 283 } 284 for (int i = 0; i < header->channels; ++i) 285 header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i); 286 return true; 287} 288 289// Convert nanoseconds to number of samples. 290static uint64_t ns_to_samples(uint64_t ns, int rate) { 291 return static_cast<double>(ns) * rate / 1000000000; 292} 293 294void C2SoftOpusDec::process( 295 const std::unique_ptr<C2Work> &work, 296 const std::shared_ptr<C2BlockPool> &pool) { 297 work->result = C2_OK; 298 work->workletsProcessed = 0u; 299 work->worklets.front()->output.configUpdate.clear(); 300 if (mSignalledError || mSignalledOutputEos) { 301 work->result = C2_BAD_VALUE; 302 return; 303 } 304 305 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0); 306 size_t inOffset = 0u; 307 size_t inSize = 0u; 308 C2ReadView rView = mDummyReadView; 309 if (!work->input.buffers.empty()) { 310 rView = work->input.buffers[0]->data().linearBlocks().front().map().get(); 311 inSize = rView.capacity(); 312 if (inSize && rView.error()) { 313 ALOGE("read view map failed %d", rView.error()); 314 work->result = C2_CORRUPTED; 315 return; 316 } 317 } 318 if (inSize == 0) { 319 fillEmptyWork(work); 320 if (eos) { 321 mSignalledOutputEos = true; 322 ALOGV("signalled EOS"); 323 } 324 return; 325 } 326 327 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize, 328 (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku()); 329 const uint8_t *data = rView.data() + inOffset; 330 if (mInputBufferCount < 3) { 331 if (mInputBufferCount == 0) { 332 if (!ParseOpusHeader(data, inSize, &mHeader)) { 333 ALOGE("Encountered error while Parsing Opus Header."); 334 mSignalledError = true; 335 work->result = C2_CORRUPTED; 336 return; 337 } 338 uint8_t channel_mapping[kMaxChannels] = {0}; 339 if (mHeader.channels <= kMaxChannelsWithDefaultLayout) { 340 memcpy(&channel_mapping, 341 kDefaultOpusChannelLayout, 342 kMaxChannelsWithDefaultLayout); 343 } else { 344 memcpy(&channel_mapping, 345 mHeader.stream_map, 346 mHeader.channels); 347 } 348 int status = OPUS_INVALID_STATE; 349 mDecoder = opus_multistream_decoder_create(kRate, 350 mHeader.channels, 351 mHeader.num_streams, 352 mHeader.num_coupled, 353 channel_mapping, 354 &status); 355 if (!mDecoder || status != OPUS_OK) { 356 ALOGE("opus_multistream_decoder_create failed status = %s", 357 opus_strerror(status)); 358 mSignalledError = true; 359 work->result = C2_CORRUPTED; 360 return; 361 } 362 status = opus_multistream_decoder_ctl(mDecoder, 363 OPUS_SET_GAIN(mHeader.gain_db)); 364 if (status != OPUS_OK) { 365 ALOGE("Failed to set OPUS header gain; status = %s", 366 opus_strerror(status)); 367 mSignalledError = true; 368 work->result = C2_CORRUPTED; 369 return; 370 } 371 } else { 372 if (inSize < 8) { 373 ALOGE("Input sample size is too small."); 374 mSignalledError = true; 375 work->result = C2_CORRUPTED; 376 return; 377 } 378 int64_t samples = ns_to_samples( *(reinterpret_cast<int64_t*> 379 (const_cast<uint8_t *> (data))), kRate); 380 if (mInputBufferCount == 1) { 381 mCodecDelay = samples; 382 mSamplesToDiscard = mCodecDelay; 383 } 384 else { 385 mSeekPreRoll = samples; 386 387 ALOGI("Configuring decoder: %d Hz, %d channels", 388 kRate, mHeader.channels); 389 C2StreamSampleRateInfo::output sampleRateInfo(0u, kRate); 390 C2StreamChannelCountInfo::output channelCountInfo(0u, mHeader.channels); 391 std::vector<std::unique_ptr<C2SettingResult>> failures; 392 c2_status_t err = mIntf->config( 393 { &sampleRateInfo, &channelCountInfo }, 394 C2_MAY_BLOCK, 395 &failures); 396 if (err == OK) { 397 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(sampleRateInfo)); 398 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(channelCountInfo)); 399 } else { 400 ALOGE("Config Update failed"); 401 mSignalledError = true; 402 work->result = C2_CORRUPTED; 403 return; 404 } 405 } 406 } 407 408 ++mInputBufferCount; 409 fillEmptyWork(work); 410 if (eos) { 411 mSignalledOutputEos = true; 412 ALOGV("signalled EOS"); 413 } 414 return; 415 } 416 417 // Ignore CSD re-submissions. 418 if ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) { 419 fillEmptyWork(work); 420 return; 421 } 422 423 // When seeking to zero, |mCodecDelay| samples has to be discarded 424 // instead of |mSeekPreRoll| samples (as we would when seeking to any 425 // other timestamp). 426 if (work->input.ordinal.timestamp.peeku() == 0) mSamplesToDiscard = mCodecDelay; 427 428 std::shared_ptr<C2LinearBlock> block; 429 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }; 430 c2_status_t err = pool->fetchLinearBlock( 431 kMaxNumSamplesPerBuffer * kMaxChannels * sizeof(int16_t), 432 usage, &block); 433 if (err != C2_OK) { 434 ALOGE("fetchLinearBlock for Output failed with status %d", err); 435 work->result = C2_NO_MEMORY; 436 return; 437 } 438 C2WriteView wView = block->map().get(); 439 if (wView.error()) { 440 ALOGE("write view map failed %d", wView.error()); 441 work->result = C2_CORRUPTED; 442 return; 443 } 444 445 int numSamples = opus_multistream_decode(mDecoder, 446 data, 447 inSize, 448 reinterpret_cast<int16_t *> (wView.data()), 449 kMaxOpusOutputPacketSizeSamples, 450 0); 451 if (numSamples < 0) { 452 ALOGE("opus_multistream_decode returned numSamples %d", numSamples); 453 numSamples = 0; 454 mSignalledError = true; 455 work->result = C2_CORRUPTED; 456 return; 457 } 458 459 int outOffset = 0; 460 if (mSamplesToDiscard > 0) { 461 if (mSamplesToDiscard > numSamples) { 462 mSamplesToDiscard -= numSamples; 463 numSamples = 0; 464 } else { 465 numSamples -= mSamplesToDiscard; 466 outOffset = mSamplesToDiscard * sizeof(int16_t) * mHeader.channels; 467 mSamplesToDiscard = 0; 468 } 469 } 470 471 if (numSamples) { 472 int outSize = numSamples * sizeof(int16_t) * mHeader.channels; 473 ALOGV("out buffer attr. offset %d size %d ", outOffset, outSize); 474 475 work->worklets.front()->output.flags = work->input.flags; 476 work->worklets.front()->output.buffers.clear(); 477 work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, outOffset, outSize)); 478 work->worklets.front()->output.ordinal = work->input.ordinal; 479 work->workletsProcessed = 1u; 480 } else { 481 fillEmptyWork(work); 482 block.reset(); 483 } 484 if (eos) { 485 mSignalledOutputEos = true; 486 ALOGV("signalled EOS"); 487 } 488} 489 490class C2SoftOpusDecFactory : public C2ComponentFactory { 491public: 492 C2SoftOpusDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>( 493 GetCodec2PlatformComponentStore()->getParamReflector())) { 494 } 495 496 virtual c2_status_t createComponent( 497 c2_node_id_t id, 498 std::shared_ptr<C2Component>* const component, 499 std::function<void(C2Component*)> deleter) override { 500 *component = std::shared_ptr<C2Component>( 501 new C2SoftOpusDec(COMPONENT_NAME, 502 id, 503 std::make_shared<C2SoftOpusDec::IntfImpl>(mHelper)), 504 deleter); 505 return C2_OK; 506 } 507 508 virtual c2_status_t createInterface( 509 c2_node_id_t id, 510 std::shared_ptr<C2ComponentInterface>* const interface, 511 std::function<void(C2ComponentInterface*)> deleter) override { 512 *interface = std::shared_ptr<C2ComponentInterface>( 513 new SimpleInterface<C2SoftOpusDec::IntfImpl>( 514 COMPONENT_NAME, id, std::make_shared<C2SoftOpusDec::IntfImpl>(mHelper)), 515 deleter); 516 return C2_OK; 517 } 518 519 virtual ~C2SoftOpusDecFactory() override = default; 520 521private: 522 std::shared_ptr<C2ReflectorHelper> mHelper; 523}; 524 525} // namespace android 526 527extern "C" ::C2ComponentFactory* CreateCodec2Factory() { 528 ALOGV("in %s", __func__); 529 return new ::android::C2SoftOpusDecFactory(); 530} 531 532extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) { 533 ALOGV("in %s", __func__); 534 delete factory; 535} 536