1 /* 2 * Copyright (C) 2012 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 "SoftFlacEncoder" 19 #include <utils/Log.h> 20 21 #include "SoftFlacEncoder.h" 22 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/MediaDefs.h> 25 26 #define FLAC_COMPRESSION_LEVEL_MIN 0 27 #define FLAC_COMPRESSION_LEVEL_DEFAULT 5 28 #define FLAC_COMPRESSION_LEVEL_MAX 8 29 30 #if LOG_NDEBUG 31 #define UNUSED_UNLESS_VERBOSE(x) (void)(x) 32 #else 33 #define UNUSED_UNLESS_VERBOSE(x) 34 #endif 35 36 namespace android { 37 38 template<class T> 39 static void InitOMXParams(T *params) { 40 params->nSize = sizeof(T); 41 params->nVersion.s.nVersionMajor = 1; 42 params->nVersion.s.nVersionMinor = 0; 43 params->nVersion.s.nRevision = 0; 44 params->nVersion.s.nStep = 0; 45 } 46 47 SoftFlacEncoder::SoftFlacEncoder( 48 const char *name, 49 const OMX_CALLBACKTYPE *callbacks, 50 OMX_PTR appData, 51 OMX_COMPONENTTYPE **component) 52 : SimpleSoftOMXComponent(name, callbacks, appData, component), 53 mSignalledError(false), 54 mNumChannels(1), 55 mSampleRate(44100), 56 mCompressionLevel(FLAC_COMPRESSION_LEVEL_DEFAULT), 57 mEncoderWriteData(false), 58 mEncoderReturnedEncodedData(false), 59 mSawInputEOS(false), 60 mSentOutputEOS(false), 61 mEncoderReturnedNbBytes(0), 62 mInputBufferPcm32(NULL), 63 mHeaderOffset(0), 64 mHeaderComplete(false), 65 mWroteHeader(false) 66 { 67 ALOGV("SoftFlacEncoder::SoftFlacEncoder(name=%s)", name); 68 initPorts(); 69 70 mFlacStreamEncoder = FLAC__stream_encoder_new(); 71 if (mFlacStreamEncoder == NULL) { 72 ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error instantiating FLAC encoder", name); 73 mSignalledError = true; 74 } 75 76 if (!mSignalledError) { // no use allocating input buffer if we had an error above 77 mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame); 78 if (mInputBufferPcm32 == NULL) { 79 ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name); 80 mSignalledError = true; 81 } 82 } 83 } 84 85 SoftFlacEncoder::~SoftFlacEncoder() { 86 ALOGV("SoftFlacEncoder::~SoftFlacEncoder()"); 87 if (mFlacStreamEncoder != NULL) { 88 FLAC__stream_encoder_delete(mFlacStreamEncoder); 89 mFlacStreamEncoder = NULL; 90 } 91 free(mInputBufferPcm32); 92 mInputBufferPcm32 = NULL; 93 } 94 95 OMX_ERRORTYPE SoftFlacEncoder::initCheck() const { 96 if (mSignalledError) { 97 if (mFlacStreamEncoder == NULL) { 98 ALOGE("initCheck() failed due to NULL encoder"); 99 } else if (mInputBufferPcm32 == NULL) { 100 ALOGE("initCheck() failed due to error allocating internal input buffer"); 101 } 102 return OMX_ErrorUndefined; 103 } else { 104 return SimpleSoftOMXComponent::initCheck(); 105 } 106 } 107 108 void SoftFlacEncoder::initPorts() { 109 ALOGV("SoftFlacEncoder::initPorts()"); 110 111 OMX_PARAM_PORTDEFINITIONTYPE def; 112 InitOMXParams(&def); 113 114 // configure input port of the encoder 115 def.nPortIndex = 0; 116 def.eDir = OMX_DirInput; 117 def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough 118 def.nBufferCountActual = def.nBufferCountMin; 119 def.nBufferSize = kMaxInputBufferSize; 120 def.bEnabled = OMX_TRUE; 121 def.bPopulated = OMX_FALSE; 122 def.eDomain = OMX_PortDomainAudio; 123 def.bBuffersContiguous = OMX_FALSE; 124 def.nBufferAlignment = 2; 125 126 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 127 def.format.audio.pNativeRender = NULL; 128 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 129 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 130 131 addPort(def); 132 133 // configure output port of the encoder 134 def.nPortIndex = 1; 135 def.eDir = OMX_DirOutput; 136 def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough 137 def.nBufferCountActual = def.nBufferCountMin; 138 def.nBufferSize = kMaxOutputBufferSize; 139 def.bEnabled = OMX_TRUE; 140 def.bPopulated = OMX_FALSE; 141 def.eDomain = OMX_PortDomainAudio; 142 def.bBuffersContiguous = OMX_FALSE; 143 def.nBufferAlignment = 1; 144 145 def.format.audio.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_AUDIO_FLAC); 146 def.format.audio.pNativeRender = NULL; 147 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 148 def.format.audio.eEncoding = OMX_AUDIO_CodingFLAC; 149 150 addPort(def); 151 } 152 153 OMX_ERRORTYPE SoftFlacEncoder::internalGetParameter( 154 OMX_INDEXTYPE index, OMX_PTR params) { 155 ALOGV("SoftFlacEncoder::internalGetParameter(index=0x%x)", index); 156 157 switch (index) { 158 case OMX_IndexParamAudioPortFormat: 159 { 160 OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 161 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 162 163 if (!isValidOMXParam(formatParams)) { 164 return OMX_ErrorBadParameter; 165 } 166 167 if (formatParams->nPortIndex > 1) { 168 return OMX_ErrorUndefined; 169 } 170 171 if (formatParams->nIndex > 0) { 172 return OMX_ErrorNoMore; 173 } 174 175 formatParams->eEncoding = 176 (formatParams->nPortIndex == 0) 177 ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingFLAC; 178 179 return OMX_ErrorNone; 180 } 181 182 case OMX_IndexParamAudioPcm: 183 { 184 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 185 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 186 187 if (!isValidOMXParam(pcmParams)) { 188 return OMX_ErrorBadParameter; 189 } 190 191 if (pcmParams->nPortIndex != 0) { 192 return OMX_ErrorUndefined; 193 } 194 195 pcmParams->eNumData = OMX_NumericalDataSigned; 196 pcmParams->eEndian = OMX_EndianBig; 197 pcmParams->bInterleaved = OMX_TRUE; 198 pcmParams->nBitPerSample = 16; 199 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 200 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 201 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 202 203 pcmParams->nChannels = mNumChannels; 204 pcmParams->nSamplingRate = mSampleRate; 205 206 return OMX_ErrorNone; 207 } 208 209 case OMX_IndexParamAudioFlac: 210 { 211 OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params; 212 213 if (!isValidOMXParam(flacParams)) { 214 return OMX_ErrorBadParameter; 215 } 216 217 if (flacParams->nPortIndex != 1) { 218 return OMX_ErrorUndefined; 219 } 220 221 flacParams->nCompressionLevel = mCompressionLevel; 222 flacParams->nChannels = mNumChannels; 223 flacParams->nSampleRate = mSampleRate; 224 return OMX_ErrorNone; 225 } 226 227 default: 228 return SimpleSoftOMXComponent::internalGetParameter(index, params); 229 } 230 } 231 232 OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter( 233 OMX_INDEXTYPE index, const OMX_PTR params) { 234 switch (index) { 235 case OMX_IndexParamAudioPortFormat: 236 { 237 const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 238 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 239 240 if (!isValidOMXParam(formatParams)) { 241 return OMX_ErrorBadParameter; 242 } 243 244 if (formatParams->nPortIndex > 1) { 245 return OMX_ErrorUndefined; 246 } 247 248 if ((formatParams->nPortIndex == 0 249 && formatParams->eEncoding != OMX_AUDIO_CodingPCM) 250 || (formatParams->nPortIndex == 1 251 && formatParams->eEncoding != OMX_AUDIO_CodingFLAC)) { 252 return OMX_ErrorUndefined; 253 } 254 255 return OMX_ErrorNone; 256 } 257 258 case OMX_IndexParamAudioPcm: 259 { 260 ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamAudioPcm)"); 261 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 262 263 if (!isValidOMXParam(pcmParams)) { 264 return OMX_ErrorBadParameter; 265 } 266 267 if (pcmParams->nPortIndex != 0) { 268 ALOGE("SoftFlacEncoder::internalSetParameter() Error #1"); 269 return OMX_ErrorUndefined; 270 } 271 272 if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) { 273 return OMX_ErrorUndefined; 274 } 275 276 mNumChannels = pcmParams->nChannels; 277 mSampleRate = pcmParams->nSamplingRate; 278 ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate); 279 280 return configureEncoder(); 281 } 282 283 case OMX_IndexParamStandardComponentRole: 284 { 285 ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamStandardComponentRole)"); 286 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 287 (const OMX_PARAM_COMPONENTROLETYPE *)params; 288 289 if (!isValidOMXParam(roleParams)) { 290 return OMX_ErrorBadParameter; 291 } 292 293 if (strncmp((const char *)roleParams->cRole, 294 "audio_encoder.flac", 295 OMX_MAX_STRINGNAME_SIZE - 1)) { 296 ALOGE("SoftFlacEncoder::internalSetParameter(OMX_IndexParamStandardComponentRole)" 297 "error"); 298 return OMX_ErrorUndefined; 299 } 300 301 return OMX_ErrorNone; 302 } 303 304 case OMX_IndexParamAudioFlac: 305 { 306 // used only for setting the compression level 307 OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params; 308 309 if (!isValidOMXParam(flacParams)) { 310 return OMX_ErrorBadParameter; 311 } 312 313 if (flacParams->nPortIndex != 1) { 314 return OMX_ErrorUndefined; 315 } 316 317 mCompressionLevel = flacParams->nCompressionLevel; // range clamping done inside encoder 318 return OMX_ErrorNone; 319 } 320 321 case OMX_IndexParamPortDefinition: 322 { 323 OMX_PARAM_PORTDEFINITIONTYPE *defParams = 324 (OMX_PARAM_PORTDEFINITIONTYPE *)params; 325 326 if (!isValidOMXParam(defParams)) { 327 return OMX_ErrorBadParameter; 328 } 329 330 if (defParams->nPortIndex == 0) { 331 if (defParams->nBufferSize > kMaxInputBufferSize) { 332 ALOGE("Input buffer size must be at most %d bytes", 333 kMaxInputBufferSize); 334 return OMX_ErrorUnsupportedSetting; 335 } 336 } 337 338 // fall through 339 } 340 341 default: 342 ALOGV("SoftFlacEncoder::internalSetParameter(default)"); 343 return SimpleSoftOMXComponent::internalSetParameter(index, params); 344 } 345 } 346 347 void SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) { 348 UNUSED_UNLESS_VERBOSE(portIndex); 349 ALOGV("SoftFlacEncoder::onQueueFilled(portIndex=%d)", portIndex); 350 351 if (mSignalledError) { 352 return; 353 } 354 355 List<BufferInfo *> &inQueue = getPortQueue(0); 356 List<BufferInfo *> &outQueue = getPortQueue(1); 357 358 FLAC__bool ok = true; 359 360 while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mSentOutputEOS) { 361 if (!inQueue.empty()) { 362 BufferInfo *inInfo = *inQueue.begin(); 363 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 364 365 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 366 ALOGV("saw EOS on buffer of size %u", inHeader->nFilledLen); 367 mSawInputEOS = true; 368 } 369 370 if (inHeader->nFilledLen > kMaxInputBufferSize) { 371 ALOGE("input buffer too large (%d).", inHeader->nFilledLen); 372 mSignalledError = true; 373 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 374 return; 375 } 376 377 assert(mNumChannels != 0); 378 mEncoderWriteData = true; 379 mEncoderReturnedEncodedData = false; 380 mEncoderReturnedNbBytes = 0; 381 mCurrentInputTimeStamp = inHeader->nTimeStamp; 382 383 const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels); 384 const unsigned nbInputSamples = inHeader->nFilledLen / 2; 385 const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer); 386 387 CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame); 388 for (unsigned i=0 ; i < nbInputSamples ; i++) { 389 mInputBufferPcm32[i] = (FLAC__int32) pcm16[i]; 390 } 391 ALOGV(" about to encode %u samples per channel", nbInputFrames); 392 ok = FLAC__stream_encoder_process_interleaved( 393 mFlacStreamEncoder, 394 mInputBufferPcm32, 395 nbInputFrames /*samples per channel*/ ); 396 397 inInfo->mOwnedByUs = false; 398 inQueue.erase(inQueue.begin()); 399 inInfo = NULL; 400 notifyEmptyBufferDone(inHeader); 401 inHeader = NULL; 402 } 403 404 BufferInfo *outInfo = *outQueue.begin(); 405 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 406 407 if (ok) { 408 if (mEncoderReturnedEncodedData && (mEncoderReturnedNbBytes != 0)) { 409 ALOGV(" dequeueing buffer on output port after writing data"); 410 outInfo->mOwnedByUs = false; 411 outQueue.erase(outQueue.begin()); 412 outInfo = NULL; 413 notifyFillBufferDone(outHeader); 414 outHeader = NULL; 415 mEncoderReturnedEncodedData = false; 416 } else { 417 ALOGV(" encoder process_interleaved returned without data to write"); 418 if (mSawInputEOS) { 419 ALOGV("finishing encoder"); 420 mSentOutputEOS = true; 421 FLAC__stream_encoder_finish(mFlacStreamEncoder); 422 if (mEncoderReturnedEncodedData && (mEncoderReturnedNbBytes != 0)) { 423 ALOGV(" dequeueing residual buffer on output port after writing data"); 424 outInfo->mOwnedByUs = false; 425 outQueue.erase(outQueue.begin()); 426 outInfo = NULL; 427 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 428 notifyFillBufferDone(outHeader); 429 outHeader = NULL; 430 mEncoderReturnedEncodedData = false; 431 } 432 } 433 } 434 } else { 435 ALOGE(" error encountered during encoding"); 436 mSignalledError = true; 437 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 438 return; 439 } 440 441 } 442 } 443 444 FLAC__StreamEncoderWriteStatus SoftFlacEncoder::onEncodedFlacAvailable( 445 const FLAC__byte buffer[], 446 size_t bytes, unsigned samples, 447 unsigned current_frame) { 448 UNUSED_UNLESS_VERBOSE(current_frame); 449 ALOGV("SoftFlacEncoder::onEncodedFlacAvailable(bytes=%zu, samples=%u, curr_frame=%u)", 450 bytes, samples, current_frame); 451 452 if (samples == 0) { 453 ALOGV("saving %zu bytes of header", bytes); 454 if (mHeaderOffset + bytes > sizeof(mHeader) || mHeaderComplete) { 455 ALOGW("header is too big, or header already received"); 456 mSignalledError = true; 457 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 458 } else { 459 memcpy(mHeader + mHeaderOffset, buffer, bytes); 460 mHeaderOffset += bytes;// will contain header size when finished receiving header 461 if (buffer[0] & 0x80) { 462 mHeaderComplete = true; 463 } 464 } 465 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; 466 } 467 468 if ((samples == 0) || !mEncoderWriteData) { 469 // called by the encoder because there's header data to save, but it's not the role 470 // of this component (unless WRITE_FLAC_HEADER_IN_FIRST_BUFFER is defined) 471 ALOGV("ignoring %zu bytes of header data (samples=%d)", bytes, samples); 472 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; 473 } 474 475 List<BufferInfo *> &outQueue = getPortQueue(1); 476 CHECK(!outQueue.empty()); 477 BufferInfo *outInfo = *outQueue.begin(); 478 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 479 480 if (mHeaderComplete && !mWroteHeader) { 481 ALOGV(" writing %d bytes of header on output port", mHeaderOffset); 482 memcpy(outHeader->pBuffer + outHeader->nOffset + outHeader->nFilledLen, 483 mHeader, mHeaderOffset); 484 outHeader->nFilledLen += mHeaderOffset; 485 mWroteHeader = true; 486 outInfo->mOwnedByUs = false; 487 outQueue.erase(outQueue.begin()); 488 outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG; 489 notifyFillBufferDone(outHeader); 490 outInfo = NULL; 491 outHeader = NULL; 492 // get the next buffer for the rest of the data 493 CHECK(!outQueue.empty()); 494 outInfo = *outQueue.begin(); 495 outHeader = outInfo->mHeader; 496 } 497 498 // write encoded data 499 ALOGV(" writing %zu bytes of encoded data on output port", bytes); 500 if (bytes > outHeader->nAllocLen - outHeader->nOffset - outHeader->nFilledLen) { 501 ALOGE(" not enough space left to write encoded data, dropping %zu bytes", bytes); 502 // a fatal error would stop the encoding 503 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; 504 } 505 memcpy(outHeader->pBuffer + outHeader->nOffset, buffer, bytes); 506 507 outHeader->nTimeStamp = mCurrentInputTimeStamp; 508 outHeader->nOffset = 0; 509 outHeader->nFilledLen += bytes; 510 outHeader->nFlags = 0; 511 512 mEncoderReturnedEncodedData = true; 513 mEncoderReturnedNbBytes += bytes; 514 515 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; 516 } 517 518 519 OMX_ERRORTYPE SoftFlacEncoder::configureEncoder() { 520 ALOGV("SoftFlacEncoder::configureEncoder() numChannel=%d, sampleRate=%d", 521 mNumChannels, mSampleRate); 522 523 if (mSignalledError || (mFlacStreamEncoder == NULL)) { 524 ALOGE("can't configure encoder: no encoder or invalid state"); 525 return OMX_ErrorInvalidState; 526 } 527 528 FLAC__bool ok = true; 529 ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels); 530 ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate); 531 ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16); 532 ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, 533 (unsigned)mCompressionLevel); 534 ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false); 535 if (!ok) { goto return_result; } 536 537 ok &= FLAC__STREAM_ENCODER_INIT_STATUS_OK == 538 FLAC__stream_encoder_init_stream(mFlacStreamEncoder, 539 flacEncoderWriteCallback /*write_callback*/, 540 NULL /*seek_callback*/, 541 NULL /*tell_callback*/, 542 NULL /*metadata_callback*/, 543 (void *) this /*client_data*/); 544 545 return_result: 546 if (ok) { 547 ALOGV("encoder successfully configured"); 548 return OMX_ErrorNone; 549 } else { 550 ALOGE("unknown error when configuring encoder"); 551 return OMX_ErrorUndefined; 552 } 553 } 554 555 556 // static 557 FLAC__StreamEncoderWriteStatus SoftFlacEncoder::flacEncoderWriteCallback( 558 const FLAC__StreamEncoder * /* encoder */, 559 const FLAC__byte buffer[], 560 size_t bytes, 561 unsigned samples, 562 unsigned current_frame, 563 void *client_data) { 564 return ((SoftFlacEncoder*) client_data)->onEncodedFlacAvailable( 565 buffer, bytes, samples, current_frame); 566 } 567 568 } // namespace android 569 570 571 android::SoftOMXComponent *createSoftOMXComponent( 572 const char *name, const OMX_CALLBACKTYPE *callbacks, 573 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 574 return new android::SoftFlacEncoder(name, callbacks, appData, component); 575 } 576 577