status_t AACDecoder::read( MediaBuffer **out, const ReadOptions *options) { /* ** end of aac audio stream in the case of initCheck is not OK, ** avoid abnormal playing later. @Jun 16, 2011. by hbb */ if(mInitCheck != OK) { ALOGE("mInitCheck is not OK, so end aac audio stream"); return ERROR_END_OF_STREAM; } status_t err; *out = NULL; int64_t seekTimeUs; ReadOptions::SeekMode mode; if (options && options->getSeekTo(&seekTimeUs, &mode)) { CHECK(seekTimeUs >= 0); mNumSamplesOutput = 0; if (mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } // Make sure that the next buffer output does not still // depend on fragments from the last one decoded. PVMP4AudioDecoderResetBuffer(mDecoderBuf); } else { seekTimeUs = -1; } repeat: if (mInputBuffer == NULL) { err = mSource->read(&mInputBuffer, options); if (err != OK) { return err; } int64_t timeUs; if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { if(mAnchorTimeUs != timeUs) { mAnchorTimeUs = timeUs; mNumSamplesOutput = 0; } } else { // We must have a new timestamp after seeking. CHECK(seekTimeUs < 0); } } MediaBuffer *buffer; CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); mConfig->pInputBuffer = (UChar *)mInputBuffer->data() + mInputBuffer->range_offset(); mConfig->inputBufferCurrentLength = mInputBuffer->range_length(); mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; mConfig->remainderBits = 0; mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data()); mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048]; #if WRITE_FILE if(aacFp) fwrite(mConfig->pInputBuffer,1, mConfig->inputBufferCurrentLength,aacFp); #endif //ALOGE("inputlen %d input[0] = %x input[1]%x", mConfig->inputBufferCurrentLength,(mConfig->pInputBuffer)[0],(mConfig->pInputBuffer)[1]); Int decoderErr = MP4AUDEC_SUCCESS; if(mConfig->isMutilChannle) { decoderErr = PVMP4AudioDecodeFrameSixChannel(mConfig, mDecoderBuf); } else { decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf); } if (mInputBuffer != NULL) { mInputBuffer->set_range( mInputBuffer->range_offset() + mConfig->inputBufferUsedLength, mInputBuffer->range_length() - mConfig->inputBufferUsedLength); if (mInputBuffer->range_length() <= 3) { mInputBuffer->release(); mInputBuffer = NULL; } } //if the input data no enough,will drop this frame inputdata. get the next frame data. if(decoderErr != MP4AUDEC_SUCCESS) { if(mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } if(buffer) { buffer->release(); buffer = NULL; } goto repeat; } /* * AAC+/eAAC+ streams can be signalled in two ways: either explicitly * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual * rate system and the sampling rate in the final output is actually * doubled compared with the core AAC decoder sampling rate. * * Explicit signalling is done by explicitly defining SBR audio object * type in the bitstream. Implicit signalling is done by embedding * SBR content in AAC extension payload specific to SBR, and hence * requires an AAC decoder to perform pre-checks on actual audio frames. * * Thus, we could not say for sure whether a stream is * AAC+/eAAC+ until the first data frame is decoded. */ if (++mNumDecodedBuffers <= 2) { ALOGV("audio/extended audio object type: %d + %d", mConfig->audioObjectType, mConfig->extendedAudioObjectType); ALOGV("aac+ upsampling factor: %d desired channels: %d", mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels); CHECK(mNumDecodedBuffers > 0); if (mNumDecodedBuffers == 1) { mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor; // Check on the sampling rate to see whether it is changed. int32_t sampleRate; CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate)); ALOGV("--->aac samplerae %d",sampleRate); if (mConfig->samplingRate != sampleRate) { mMeta->setInt32(kKeySampleRate, mConfig->samplingRate); ALOGV("Sample rate was %d Hz, but now is %d Hz", sampleRate, mConfig->samplingRate); buffer->release(); // mInputBuffer->release(); // mInputBuffer = NULL; return INFO_FORMAT_CHANGED; } } else { // mNumDecodedBuffers == 2 if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC || mConfig->extendedAudioObjectType == MP4AUDIO_LTP) { if (mUpsamplingFactor == 2) { // The stream turns out to be not aacPlus mode anyway ALOGV("Disable AAC+/eAAC+ since extended audio object type is %d", mConfig->extendedAudioObjectType); mConfig->aacPlusEnabled = 0; } } else { if (mUpsamplingFactor == 1) { // aacPlus mode does not buy us anything, but to cause // 1. CPU load to increase, and // 2. a half speed of decoding ALOGV("Disable AAC+/eAAC+ since upsampling factor is 1"); mConfig->aacPlusEnabled = 0; } } } } size_t numOutBytes = mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels; if (mUpsamplingFactor == 2) { if (mConfig->desiredChannels == 1) { memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2); } numOutBytes *= 2; } if (decoderErr != MP4AUDEC_SUCCESS) { ALOGW("AAC decoder returned error %d, substituting silence", decoderErr); memset(buffer->data(), 0, numOutBytes); // Discard input buffer. if(mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } // fall through } buffer->set_range(0, numOutBytes); buffer->meta_data()->setInt64( kKeyTime, mAnchorTimeUs + (mNumSamplesOutput * 1000000) / mConfig->samplingRate); mNumSamplesOutput += mConfig->frameLength; *out = buffer; return OK; }
status_t WAVEWriter::threadFunc() { mEstimatedDurationUs = 0; mEstimatedSizeBytes = 0; bool stoppedPrematurely = true; int64_t previousPausedDurationUs = 0; int64_t maxTimestampUs = 0; status_t err = OK; prctl(PR_SET_NAME, (unsigned long)"WAVEWriter", 0, 0, 0); hdr.data_sz = 0; while (!mDone) { MediaBuffer *buffer; err = mSource->read(&buffer); if (err != OK) { break; } if (mPaused) { buffer->release(); buffer = NULL; continue; } mEstimatedSizeBytes += buffer->range_length(); if (exceedsFileSizeLimit()) { buffer->release(); buffer = NULL; notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); break; } int64_t timestampUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); if (timestampUs > mEstimatedDurationUs) { mEstimatedDurationUs = timestampUs; } if (mResumed) { previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000); mResumed = false; } timestampUs -= previousPausedDurationUs; ALOGV("time stamp: %lld, previous paused duration: %lld", timestampUs, previousPausedDurationUs); if (timestampUs > maxTimestampUs) { maxTimestampUs = timestampUs; } if (exceedsFileDurationLimit()) { buffer->release(); buffer = NULL; notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); break; } ssize_t n = write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), buffer->range_length()); hdr.data_sz += (ssize_t)buffer->range_length(); hdr.riff_sz = hdr.data_sz + 44 - 8; if (n < (ssize_t)buffer->range_length()) { buffer->release(); buffer = NULL; break; } if (stoppedPrematurely) { stoppedPrematurely = false; } buffer->release(); buffer = NULL; } if (stoppedPrematurely) { notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR); } lseek(mFd, 0, SEEK_SET); write(mFd, &hdr, sizeof(hdr)); lseek(mFd, 0, SEEK_END); close(mFd); mFd = -1; mReachedEOS = true; if (err == ERROR_END_OF_STREAM) { return OK; } return err; }
status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { *out = NULL; MediaBuffer *buffer = NULL; int64_t timeUs = -1; for (;;) { size_t i; size_t packetSize = 0; bool gotFullPacket = false; for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { uint8_t lace = mCurrentPage.mLace[i]; packetSize += lace; if (lace < 255) { gotFullPacket = true; ++i; break; } } if (mNextLaceIndex < mCurrentPage.mNumSegments) { off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; for (size_t j = 0; j < mNextLaceIndex; ++j) { dataOffset += mCurrentPage.mLace[j]; } size_t fullSize = packetSize; if (buffer != NULL) { fullSize += buffer->range_length(); } MediaBuffer *tmp = new MediaBuffer(fullSize); if (buffer != NULL) { memcpy(tmp->data(), buffer->data(), buffer->range_length()); tmp->set_range(0, buffer->range_length()); buffer->release(); } else { // XXX Not only is this not technically the correct time for // this packet, we also stamp every packet in this page // with the same time. This needs fixing later. if (mVi.rate) { // Rate may not have been initialized yet if we're currently // reading the configuration packets... // Fortunately, the timestamp doesn't matter for those. timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate; } tmp->set_range(0, 0); } buffer = tmp; ssize_t n = mSource->readAt( dataOffset, (uint8_t *)buffer->data() + buffer->range_length(), packetSize); if (n < (ssize_t)packetSize) { LOGV("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); return ERROR_IO; } buffer->set_range(0, fullSize); mNextLaceIndex = i; if (gotFullPacket) { // We've just read the entire packet. if (timeUs >= 0) { buffer->meta_data()->setInt64(kKeyTime, timeUs); } if (mFirstPacketInPage) { buffer->meta_data()->setInt32( kKeyValidSamples, mCurrentPageSamples); mFirstPacketInPage = false; } *out = buffer; return OK; } // fall through, the buffer now contains the start of the packet. } CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); mOffset += mCurrentPageSize; ssize_t n = readPage(mOffset, &mCurrentPage); if (n <= 0) { if (buffer) { buffer->release(); buffer = NULL; } LOGV("readPage returned %ld", n); return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; } mCurrentPageSamples = mCurrentPage.mGranulePosition - mPrevGranulePosition; mFirstPacketInPage = true; mPrevGranulePosition = mCurrentPage.mGranulePosition; mCurrentPageSize = n; mNextLaceIndex = 0; if (buffer != NULL) { if ((mCurrentPage.mFlags & 1) == 0) { // This page does not continue the packet, i.e. the packet // is already complete. if (timeUs >= 0) { buffer->meta_data()->setInt64(kKeyTime, timeUs); } buffer->meta_data()->setInt32( kKeyValidSamples, mCurrentPageSamples); mFirstPacketInPage = false; *out = buffer; return OK; } } } }
bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aSeekTimeUs, BufferCallback *aBufferCallback) { MOZ_ASSERT(aSeekTimeUs >= -1); if (!mVideoSource.get()) return false; ReleaseVideoBuffer(); status_t err; if (aSeekTimeUs != -1) { ReadOptions options; options.setSeekTo(aSeekTimeUs); err = mVideoSource->read(&mVideoBuffer, &options); } else { err = mVideoSource->read(&mVideoBuffer); } aFrame->mSize = 0; if (err == OK && mVideoBuffer->range_length() > 0) { int64_t timeUs; int32_t keyFrame; if (!mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs) ) { LOG("no frame time"); return false; } if (timeUs < 0) { LOG("frame time %lld must be nonnegative", timeUs); return false; } if (!mVideoBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) { keyFrame = 0; } char *data = reinterpret_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset(); size_t length = mVideoBuffer->range_length(); if (!ToVideoFrame(aFrame, timeUs, data, length, keyFrame, aBufferCallback)) { return false; } } else if (err == INFO_FORMAT_CHANGED) { // If the format changed, update our cached info. LOG("mVideoSource INFO_FORMAT_CHANGED"); if (!SetVideoFormat()) return false; else return ReadVideo(aFrame, aSeekTimeUs, aBufferCallback); } else if (err == ERROR_END_OF_STREAM) { LOG("mVideoSource END_OF_STREAM"); } else if (err != OK) { LOG("mVideoSource ERROR %#x", err); } return err == OK; }
status_t ExtendedWriter::threadFunc() { mEstimatedDurationUs = 0; mEstimatedSizeBytes = 0; bool stoppedPrematurely = true; int64_t previousPausedDurationUs = 0; int64_t maxTimestampUs = 0; status_t err = OK; pid_t tid = gettid(); androidSetThreadPriority(tid, ANDROID_PRIORITY_AUDIO); prctl(PR_SET_NAME, (unsigned long)"ExtendedWriter", 0, 0, 0); while (!mDone) { MediaBuffer *buffer; err = mSource->read(&buffer); if (err != OK) { break; } if (mPaused) { buffer->release(); buffer = NULL; continue; } mEstimatedSizeBytes += buffer->range_length(); if (exceedsFileSizeLimit()) { buffer->release(); buffer = NULL; notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); break; } int64_t timestampUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); if (timestampUs > mEstimatedDurationUs) { mEstimatedDurationUs = timestampUs; } if (mResumed) { previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000); mResumed = false; } timestampUs -= previousPausedDurationUs; if (timestampUs > maxTimestampUs) { maxTimestampUs = timestampUs; } if (exceedsFileDurationLimit()) { buffer->release(); buffer = NULL; notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); break; } ssize_t n = fwrite( (const uint8_t *)buffer->data() + buffer->range_offset(), 1, buffer->range_length(), mFile); mOffset += n; if (n < (ssize_t)buffer->range_length()) { buffer->release(); buffer = NULL; break; } // XXX: How to tell it is stopped prematurely? if (stoppedPrematurely) { stoppedPrematurely = false; } buffer->release(); buffer = NULL; } if (stoppedPrematurely) { notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR); } if ( mFormat == AUDIO_FORMAT_QCELP ) { writeQCPHeader( ); } else if ( mFormat == AUDIO_FORMAT_EVRC ) { writeEVRCHeader( ); } fflush(mFile); fclose(mFile); mFile = NULL; mReachedEOS = true; if (err == ERROR_END_OF_STREAM || (err == -ETIMEDOUT)) { return OK; } return err; }