SoftOpus.cpp revision 3179e3b3531b5fe93dc7f5b2c378e27010a406d5
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 37// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies 38// mappings for up to 8 channels. This information is part of the Vorbis I 39// Specification: 40// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html 41static const int kMaxChannels = 8; 42 43template<class T> 44static void InitOMXParams(T *params) { 45 params->nSize = sizeof(T); 46 params->nVersion.s.nVersionMajor = 1; 47 params->nVersion.s.nVersionMinor = 0; 48 params->nVersion.s.nRevision = 0; 49 params->nVersion.s.nStep = 0; 50} 51 52SoftOpus::SoftOpus( 53 const char *name, 54 const OMX_CALLBACKTYPE *callbacks, 55 OMX_PTR appData, 56 OMX_COMPONENTTYPE **component) 57 : SimpleSoftOMXComponent(name, callbacks, appData, component), 58 mInputBufferCount(0), 59 mDecoder(NULL), 60 mHeader(NULL), 61 mCodecDelay(0), 62 mSeekPreRoll(0), 63 mAnchorTimeUs(0), 64 mNumFramesOutput(0), 65 mOutputPortSettingsChange(NONE) { 66 initPorts(); 67 CHECK_EQ(initDecoder(), (status_t)OK); 68} 69 70SoftOpus::~SoftOpus() { 71 if (mDecoder != NULL) { 72 opus_multistream_decoder_destroy(mDecoder); 73 mDecoder = NULL; 74 } 75 if (mHeader != NULL) { 76 delete mHeader; 77 mHeader = NULL; 78 } 79} 80 81void SoftOpus::initPorts() { 82 OMX_PARAM_PORTDEFINITIONTYPE def; 83 InitOMXParams(&def); 84 85 def.nPortIndex = 0; 86 def.eDir = OMX_DirInput; 87 def.nBufferCountMin = kNumBuffers; 88 def.nBufferCountActual = def.nBufferCountMin; 89 def.nBufferSize = 960 * 6; 90 def.bEnabled = OMX_TRUE; 91 def.bPopulated = OMX_FALSE; 92 def.eDomain = OMX_PortDomainAudio; 93 def.bBuffersContiguous = OMX_FALSE; 94 def.nBufferAlignment = 1; 95 96 def.format.audio.cMIMEType = 97 const_cast<char *>(MEDIA_MIMETYPE_AUDIO_OPUS); 98 99 def.format.audio.pNativeRender = NULL; 100 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 101 def.format.audio.eEncoding = 102 (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS; 103 104 addPort(def); 105 106 def.nPortIndex = 1; 107 def.eDir = OMX_DirOutput; 108 def.nBufferCountMin = kNumBuffers; 109 def.nBufferCountActual = def.nBufferCountMin; 110 def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t) * kMaxChannels; 111 def.bEnabled = OMX_TRUE; 112 def.bPopulated = OMX_FALSE; 113 def.eDomain = OMX_PortDomainAudio; 114 def.bBuffersContiguous = OMX_FALSE; 115 def.nBufferAlignment = 2; 116 117 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 118 def.format.audio.pNativeRender = NULL; 119 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 120 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 121 122 addPort(def); 123} 124 125status_t SoftOpus::initDecoder() { 126 return OK; 127} 128 129OMX_ERRORTYPE SoftOpus::internalGetParameter( 130 OMX_INDEXTYPE index, OMX_PTR params) { 131 switch ((int)index) { 132 case OMX_IndexParamAudioAndroidOpus: 133 { 134 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 135 (OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 136 137 if (opusParams->nPortIndex != 0) { 138 return OMX_ErrorUndefined; 139 } 140 141 opusParams->nAudioBandWidth = 0; 142 opusParams->nSampleRate = kRate; 143 opusParams->nBitRate = 0; 144 145 if (!isConfigured()) { 146 opusParams->nChannels = 1; 147 } else { 148 opusParams->nChannels = mHeader->channels; 149 } 150 151 return OMX_ErrorNone; 152 } 153 154 case OMX_IndexParamAudioPcm: 155 { 156 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 157 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 158 159 if (pcmParams->nPortIndex != 1) { 160 return OMX_ErrorUndefined; 161 } 162 163 pcmParams->eNumData = OMX_NumericalDataSigned; 164 pcmParams->eEndian = OMX_EndianBig; 165 pcmParams->bInterleaved = OMX_TRUE; 166 pcmParams->nBitPerSample = 16; 167 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 168 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 169 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 170 pcmParams->nSamplingRate = kRate; 171 172 if (!isConfigured()) { 173 pcmParams->nChannels = 1; 174 } else { 175 pcmParams->nChannels = mHeader->channels; 176 } 177 178 return OMX_ErrorNone; 179 } 180 181 default: 182 return SimpleSoftOMXComponent::internalGetParameter(index, params); 183 } 184} 185 186OMX_ERRORTYPE SoftOpus::internalSetParameter( 187 OMX_INDEXTYPE index, const OMX_PTR params) { 188 switch ((int)index) { 189 case OMX_IndexParamStandardComponentRole: 190 { 191 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 192 (const OMX_PARAM_COMPONENTROLETYPE *)params; 193 194 if (strncmp((const char *)roleParams->cRole, 195 "audio_decoder.opus", 196 OMX_MAX_STRINGNAME_SIZE - 1)) { 197 return OMX_ErrorUndefined; 198 } 199 200 return OMX_ErrorNone; 201 } 202 203 case OMX_IndexParamAudioAndroidOpus: 204 { 205 const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 206 (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 207 208 if (opusParams->nPortIndex != 0) { 209 return OMX_ErrorUndefined; 210 } 211 212 return OMX_ErrorNone; 213 } 214 215 default: 216 return SimpleSoftOMXComponent::internalSetParameter(index, params); 217 } 218} 219 220bool SoftOpus::isConfigured() const { 221 return mInputBufferCount >= 1; 222} 223 224static uint16_t ReadLE16(const uint8_t *data, size_t data_size, 225 uint32_t read_offset) { 226 if (read_offset + 1 > data_size) 227 return 0; 228 uint16_t val; 229 val = data[read_offset]; 230 val |= data[read_offset + 1] << 8; 231 return val; 232} 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