1/* 2 * Copyright (C) 2014 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 "SoftOpus" 19#include <utils/Log.h> 20 21#include "SoftOpus.h" 22#include <OMX_AudioExt.h> 23#include <OMX_IndexExt.h> 24 25#include <media/stagefright/foundation/ADebug.h> 26#include <media/stagefright/MediaDefs.h> 27 28extern "C" { 29 #include <opus.h> 30 #include <opus_multistream.h> 31} 32 33namespace android { 34 35static const int kRate = 48000; 36 37template<class T> 38static void InitOMXParams(T *params) { 39 params->nSize = sizeof(T); 40 params->nVersion.s.nVersionMajor = 1; 41 params->nVersion.s.nVersionMinor = 0; 42 params->nVersion.s.nRevision = 0; 43 params->nVersion.s.nStep = 0; 44} 45 46SoftOpus::SoftOpus( 47 const char *name, 48 const OMX_CALLBACKTYPE *callbacks, 49 OMX_PTR appData, 50 OMX_COMPONENTTYPE **component) 51 : SimpleSoftOMXComponent(name, callbacks, appData, component), 52 mInputBufferCount(0), 53 mDecoder(NULL), 54 mHeader(NULL), 55 mCodecDelay(0), 56 mSeekPreRoll(0), 57 mAnchorTimeUs(0), 58 mNumFramesOutput(0), 59 mOutputPortSettingsChange(NONE) { 60 initPorts(); 61 CHECK_EQ(initDecoder(), (status_t)OK); 62} 63 64SoftOpus::~SoftOpus() { 65 if (mDecoder != NULL) { 66 opus_multistream_decoder_destroy(mDecoder); 67 mDecoder = NULL; 68 } 69 if (mHeader != NULL) { 70 delete mHeader; 71 mHeader = NULL; 72 } 73} 74 75void SoftOpus::initPorts() { 76 OMX_PARAM_PORTDEFINITIONTYPE def; 77 InitOMXParams(&def); 78 79 def.nPortIndex = 0; 80 def.eDir = OMX_DirInput; 81 def.nBufferCountMin = kNumBuffers; 82 def.nBufferCountActual = def.nBufferCountMin; 83 def.nBufferSize = 960 * 6; 84 def.bEnabled = OMX_TRUE; 85 def.bPopulated = OMX_FALSE; 86 def.eDomain = OMX_PortDomainAudio; 87 def.bBuffersContiguous = OMX_FALSE; 88 def.nBufferAlignment = 1; 89 90 def.format.audio.cMIMEType = 91 const_cast<char *>(MEDIA_MIMETYPE_AUDIO_OPUS); 92 93 def.format.audio.pNativeRender = NULL; 94 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 95 def.format.audio.eEncoding = 96 (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS; 97 98 addPort(def); 99 100 def.nPortIndex = 1; 101 def.eDir = OMX_DirOutput; 102 def.nBufferCountMin = kNumBuffers; 103 def.nBufferCountActual = def.nBufferCountMin; 104 def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t); 105 def.bEnabled = OMX_TRUE; 106 def.bPopulated = OMX_FALSE; 107 def.eDomain = OMX_PortDomainAudio; 108 def.bBuffersContiguous = OMX_FALSE; 109 def.nBufferAlignment = 2; 110 111 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 112 def.format.audio.pNativeRender = NULL; 113 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 114 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 115 116 addPort(def); 117} 118 119status_t SoftOpus::initDecoder() { 120 return OK; 121} 122 123OMX_ERRORTYPE SoftOpus::internalGetParameter( 124 OMX_INDEXTYPE index, OMX_PTR params) { 125 switch ((int)index) { 126 case OMX_IndexParamAudioAndroidOpus: 127 { 128 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 129 (OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 130 131 if (opusParams->nPortIndex != 0) { 132 return OMX_ErrorUndefined; 133 } 134 135 opusParams->nAudioBandWidth = 0; 136 opusParams->nSampleRate = kRate; 137 opusParams->nBitRate = 0; 138 139 if (!isConfigured()) { 140 opusParams->nChannels = 1; 141 } else { 142 opusParams->nChannels = mHeader->channels; 143 } 144 145 return OMX_ErrorNone; 146 } 147 148 case OMX_IndexParamAudioPcm: 149 { 150 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 151 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 152 153 if (pcmParams->nPortIndex != 1) { 154 return OMX_ErrorUndefined; 155 } 156 157 pcmParams->eNumData = OMX_NumericalDataSigned; 158 pcmParams->eEndian = OMX_EndianBig; 159 pcmParams->bInterleaved = OMX_TRUE; 160 pcmParams->nBitPerSample = 16; 161 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 162 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 163 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 164 pcmParams->nSamplingRate = kRate; 165 166 if (!isConfigured()) { 167 pcmParams->nChannels = 1; 168 } else { 169 pcmParams->nChannels = mHeader->channels; 170 } 171 172 return OMX_ErrorNone; 173 } 174 175 default: 176 return SimpleSoftOMXComponent::internalGetParameter(index, params); 177 } 178} 179 180OMX_ERRORTYPE SoftOpus::internalSetParameter( 181 OMX_INDEXTYPE index, const OMX_PTR params) { 182 switch ((int)index) { 183 case OMX_IndexParamStandardComponentRole: 184 { 185 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 186 (const OMX_PARAM_COMPONENTROLETYPE *)params; 187 188 if (strncmp((const char *)roleParams->cRole, 189 "audio_decoder.opus", 190 OMX_MAX_STRINGNAME_SIZE - 1)) { 191 return OMX_ErrorUndefined; 192 } 193 194 return OMX_ErrorNone; 195 } 196 197 case OMX_IndexParamAudioAndroidOpus: 198 { 199 const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 200 (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 201 202 if (opusParams->nPortIndex != 0) { 203 return OMX_ErrorUndefined; 204 } 205 206 return OMX_ErrorNone; 207 } 208 209 default: 210 return SimpleSoftOMXComponent::internalSetParameter(index, params); 211 } 212} 213 214bool SoftOpus::isConfigured() const { 215 return mInputBufferCount >= 1; 216} 217 218static uint16_t ReadLE16(const uint8_t *data, size_t data_size, 219 uint32_t read_offset) { 220 if (read_offset + 1 > data_size) 221 return 0; 222 uint16_t val; 223 val = data[read_offset]; 224 val |= data[read_offset + 1] << 8; 225 return val; 226} 227 228// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies 229// mappings for up to 8 channels. This information is part of the Vorbis I 230// Specification: 231// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html 232static const int kMaxChannels = 8; 233 234// Maximum packet size used in Xiph's opusdec. 235static const int kMaxOpusOutputPacketSizeSamples = 960 * 6; 236 237// Default audio output channel layout. Used to initialize |stream_map| in 238// OpusHeader, and passed to opus_multistream_decoder_create() when the header 239// does not contain mapping information. The values are valid only for mono and 240// stereo output: Opus streams with more than 2 channels require a stream map. 241static const int kMaxChannelsWithDefaultLayout = 2; 242static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 }; 243 244// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header 245static bool ParseOpusHeader(const uint8_t *data, size_t data_size, 246 OpusHeader* header) { 247 // Size of the Opus header excluding optional mapping information. 248 const size_t kOpusHeaderSize = 19; 249 250 // Offset to the channel count byte in the Opus header. 251 const size_t kOpusHeaderChannelsOffset = 9; 252 253 // Offset to the pre-skip value in the Opus header. 254 const size_t kOpusHeaderSkipSamplesOffset = 10; 255 256 // Offset to the gain value in the Opus header. 257 const size_t kOpusHeaderGainOffset = 16; 258 259 // Offset to the channel mapping byte in the Opus header. 260 const size_t kOpusHeaderChannelMappingOffset = 18; 261 262 // Opus Header contains a stream map. The mapping values are in the header 263 // beyond the always present |kOpusHeaderSize| bytes of data. The mapping 264 // data contains stream count, coupling information, and per channel mapping 265 // values: 266 // - Byte 0: Number of streams. 267 // - Byte 1: Number coupled. 268 // - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping 269 // values. 270 const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize; 271 const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1; 272 const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2; 273 274 if (data_size < kOpusHeaderSize) { 275 ALOGV("Header size is too small."); 276 return false; 277 } 278 header->channels = *(data + kOpusHeaderChannelsOffset); 279 280 if (header->channels <= 0 || header->channels > kMaxChannels) { 281 ALOGV("Invalid Header, wrong channel count: %d", header->channels); 282 return false; 283 } 284 header->skip_samples = ReadLE16(data, data_size, 285 kOpusHeaderSkipSamplesOffset); 286 header->gain_db = static_cast<int16_t>( 287 ReadLE16(data, data_size, 288 kOpusHeaderGainOffset)); 289 header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset); 290 if (!header->channel_mapping) { 291 if (header->channels > kMaxChannelsWithDefaultLayout) { 292 ALOGV("Invalid Header, missing stream map."); 293 return false; 294 } 295 header->num_streams = 1; 296 header->num_coupled = header->channels > 1; 297 header->stream_map[0] = 0; 298 header->stream_map[1] = 1; 299 return true; 300 } 301 if (data_size < kOpusHeaderStreamMapOffset + header->channels) { 302 ALOGV("Invalid stream map; insufficient data for current channel " 303 "count: %d", header->channels); 304 return false; 305 } 306 header->num_streams = *(data + kOpusHeaderNumStreamsOffset); 307 header->num_coupled = *(data + kOpusHeaderNumCoupledOffset); 308 if (header->num_streams + header->num_coupled != header->channels) { 309 ALOGV("Inconsistent channel mapping."); 310 return false; 311 } 312 for (int i = 0; i < header->channels; ++i) 313 header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i); 314 return true; 315} 316 317// Convert nanoseconds to number of samples. 318static uint64_t ns_to_samples(uint64_t ns, int kRate) { 319 return static_cast<double>(ns) * kRate / 1000000000; 320} 321 322void SoftOpus::onQueueFilled(OMX_U32 portIndex) { 323 List<BufferInfo *> &inQueue = getPortQueue(0); 324 List<BufferInfo *> &outQueue = getPortQueue(1); 325 326 if (mOutputPortSettingsChange != NONE) { 327 return; 328 } 329 330 if (portIndex == 0 && mInputBufferCount < 3) { 331 BufferInfo *info = *inQueue.begin(); 332 OMX_BUFFERHEADERTYPE *header = info->mHeader; 333 334 const uint8_t *data = header->pBuffer + header->nOffset; 335 size_t size = header->nFilledLen; 336 337 if (mInputBufferCount == 0) { 338 CHECK(mHeader == NULL); 339 mHeader = new OpusHeader(); 340 memset(mHeader, 0, sizeof(*mHeader)); 341 if (!ParseOpusHeader(data, size, mHeader)) { 342 ALOGV("Parsing Opus Header failed."); 343 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 344 return; 345 } 346 347 uint8_t channel_mapping[kMaxChannels] = {0}; 348 memcpy(&channel_mapping, 349 kDefaultOpusChannelLayout, 350 kMaxChannelsWithDefaultLayout); 351 352 int status = OPUS_INVALID_STATE; 353 mDecoder = opus_multistream_decoder_create(kRate, 354 mHeader->channels, 355 mHeader->num_streams, 356 mHeader->num_coupled, 357 channel_mapping, 358 &status); 359 if (!mDecoder || status != OPUS_OK) { 360 ALOGV("opus_multistream_decoder_create failed status=%s", 361 opus_strerror(status)); 362 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 363 return; 364 } 365 status = 366 opus_multistream_decoder_ctl(mDecoder, 367 OPUS_SET_GAIN(mHeader->gain_db)); 368 if (status != OPUS_OK) { 369 ALOGV("Failed to set OPUS header gain; status=%s", 370 opus_strerror(status)); 371 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 372 return; 373 } 374 } else if (mInputBufferCount == 1) { 375 mCodecDelay = ns_to_samples( 376 *(reinterpret_cast<int64_t*>(header->pBuffer + 377 header->nOffset)), 378 kRate); 379 mSamplesToDiscard = mCodecDelay; 380 } else { 381 mSeekPreRoll = ns_to_samples( 382 *(reinterpret_cast<int64_t*>(header->pBuffer + 383 header->nOffset)), 384 kRate); 385 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 386 mOutputPortSettingsChange = AWAITING_DISABLED; 387 } 388 389 inQueue.erase(inQueue.begin()); 390 info->mOwnedByUs = false; 391 notifyEmptyBufferDone(header); 392 ++mInputBufferCount; 393 return; 394 } 395 396 while (!inQueue.empty() && !outQueue.empty()) { 397 BufferInfo *inInfo = *inQueue.begin(); 398 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 399 400 BufferInfo *outInfo = *outQueue.begin(); 401 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 402 403 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 404 inQueue.erase(inQueue.begin()); 405 inInfo->mOwnedByUs = false; 406 notifyEmptyBufferDone(inHeader); 407 408 outHeader->nFilledLen = 0; 409 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 410 411 outQueue.erase(outQueue.begin()); 412 outInfo->mOwnedByUs = false; 413 notifyFillBufferDone(outHeader); 414 return; 415 } 416 417 if (inHeader->nOffset == 0) { 418 mAnchorTimeUs = inHeader->nTimeStamp; 419 mNumFramesOutput = 0; 420 } 421 422 // When seeking to zero, |mCodecDelay| samples has to be discarded 423 // instead of |mSeekPreRoll| samples (as we would when seeking to any 424 // other timestamp). 425 if (inHeader->nTimeStamp == 0) { 426 mSamplesToDiscard = mCodecDelay; 427 } 428 429 const uint8_t *data = inHeader->pBuffer + inHeader->nOffset; 430 const uint32_t size = inHeader->nFilledLen; 431 432 int numFrames = opus_multistream_decode(mDecoder, 433 data, 434 size, 435 (int16_t *)outHeader->pBuffer, 436 kMaxOpusOutputPacketSizeSamples, 437 0); 438 if (numFrames < 0) { 439 ALOGE("opus_multistream_decode returned %d", numFrames); 440 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 441 return; 442 } 443 444 outHeader->nOffset = 0; 445 if (mSamplesToDiscard > 0) { 446 if (mSamplesToDiscard > numFrames) { 447 mSamplesToDiscard -= numFrames; 448 numFrames = 0; 449 } else { 450 numFrames -= mSamplesToDiscard; 451 outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) * 452 mHeader->channels; 453 mSamplesToDiscard = 0; 454 } 455 } 456 457 outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels; 458 outHeader->nFlags = 0; 459 460 outHeader->nTimeStamp = mAnchorTimeUs + 461 (mNumFramesOutput * 1000000ll) / 462 kRate; 463 464 mNumFramesOutput += numFrames; 465 466 inInfo->mOwnedByUs = false; 467 inQueue.erase(inQueue.begin()); 468 inInfo = NULL; 469 notifyEmptyBufferDone(inHeader); 470 inHeader = NULL; 471 472 outInfo->mOwnedByUs = false; 473 outQueue.erase(outQueue.begin()); 474 outInfo = NULL; 475 notifyFillBufferDone(outHeader); 476 outHeader = NULL; 477 478 ++mInputBufferCount; 479 } 480} 481 482void SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) { 483 if (portIndex == 0 && mDecoder != NULL) { 484 // Make sure that the next buffer output does not still 485 // depend on fragments from the last one decoded. 486 mNumFramesOutput = 0; 487 opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE); 488 mAnchorTimeUs = 0; 489 mSamplesToDiscard = mSeekPreRoll; 490 } 491} 492 493void SoftOpus::onReset() { 494 mInputBufferCount = 0; 495 mNumFramesOutput = 0; 496 if (mDecoder != NULL) { 497 opus_multistream_decoder_destroy(mDecoder); 498 mDecoder = NULL; 499 } 500 if (mHeader != NULL) { 501 delete mHeader; 502 mHeader = NULL; 503 } 504 505 mOutputPortSettingsChange = NONE; 506} 507 508void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 509 if (portIndex != 1) { 510 return; 511 } 512 513 switch (mOutputPortSettingsChange) { 514 case NONE: 515 break; 516 517 case AWAITING_DISABLED: 518 { 519 CHECK(!enabled); 520 mOutputPortSettingsChange = AWAITING_ENABLED; 521 break; 522 } 523 524 default: 525 { 526 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 527 CHECK(enabled); 528 mOutputPortSettingsChange = NONE; 529 break; 530 } 531 } 532} 533 534} // namespace android 535 536android::SoftOMXComponent *createSoftOMXComponent( 537 const char *name, const OMX_CALLBACKTYPE *callbacks, 538 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 539 return new android::SoftOpus(name, callbacks, appData, component); 540} 541