void GonkDecoderManager::ProcessInput(bool aEndOfStream) { MOZ_ASSERT(OnTaskLooper()); status_t rv = ProcessQueuedSamples(); if (rv >= 0) { if (!aEndOfStream && rv <= MIN_QUEUED_SAMPLES) { mDecodeCallback->InputExhausted(); } if (mToDo.get() == nullptr) { mToDo = new AMessage(kNotifyDecoderActivity, id()); if (aEndOfStream) { mToDo->setInt32("input-eos", 1); } mDecoder->requestActivityNotification(mToDo); } else if (aEndOfStream) { mToDo->setInt32("input-eos", 1); } } else { GMDD_LOG("input processed: error#%d", rv); mDecodeCallback->Error(MediaDataDecoderError::FATAL_ERROR); } }
nsresult GonkDecoderManager::Flush() { if (mDecoder == nullptr) { GMDD_LOG("Decoder is not initialized"); return NS_ERROR_UNEXPECTED; } if (!mInitPromise.IsEmpty()) { return NS_OK; } { MutexAutoLock lock(mMutex); mQueuedSamples.Clear(); } MonitorAutoLock lock(mFlushMonitor); mIsFlushing = true; sp<AMessage> flush = new AMessage(kNotifyProcessFlush, id()); flush->post(); while (mIsFlushing) { lock.Wait(); } return NS_OK; }
void GonkMediaDataDecoder::ProcessOutput() { nsRefPtr<MediaData> output; nsresult rv = NS_ERROR_ABORT; while (!mDrainComplete) { // There are samples in queue, try to send them into decoder when EOS. if (mSignaledEOS && mManager->HasQueuedSample()) { GMDD_LOG("ProcessOutput: drain all input samples"); rv = mManager->Input(nullptr); } rv = mManager->Output(mLastStreamOffset, output); if (rv == NS_OK) { mCallback->Output(output); continue; } else if (rv == NS_ERROR_NOT_AVAILABLE && mSignaledEOS) { // Try to get more frames before getting EOS frame continue; } else { break; } } if (rv == NS_ERROR_NOT_AVAILABLE && !mSignaledEOS) { mCallback->InputExhausted(); return; } if (rv != NS_OK) { NS_WARNING("GonkMediaDataDecoder failed to output data"); GMDD_LOG("Failed to output data"); // GonkDecoderManangers report NS_ERROR_ABORT when EOS is reached. if (rv == NS_ERROR_ABORT) { if (output) { mCallback->Output(output); } mCallback->DrainComplete(); MOZ_ASSERT_IF(mSignaledEOS, !mManager->HasQueuedSample()); mSignaledEOS = false; mDrainComplete = true; return; } GMDD_LOG("Callback error!"); mCallback->Error(); } }
void GonkDecoderManager::ResetEOS() { // After eos, android::MediaCodec needs to be flushed to receive next input mWaitOutput.Clear(); if (mDecoder->flush() != OK) { GMDD_LOG("flush error"); mDecodeCallback->Error(MediaDataDecoderError::FATAL_ERROR); } }
void GonkDecoderManager::ResetEOS() { // After eos, android::MediaCodec needs to be flushed to receive next input mWaitOutput.Clear(); if (mDecoder->flush() != OK) { GMDD_LOG("flush error"); mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__)); } }
void GonkMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample) { nsresult rv = mManager->Input(aSample); if (rv != NS_OK) { NS_WARNING("GonkAudioDecoder failed to input data"); GMDD_LOG("Failed to input data err: %d",rv); mCallback->Error(); return; } if (aSample) { mLastStreamOffset = aSample->byte_offset; } ProcessOutput(); }
void GonkDecoderManager::ProcessFlush() { MOZ_ASSERT(OnTaskLooper()); mLastTime = INT64_MIN; MonitorAutoLock lock(mFlushMonitor); mWaitOutput.Clear(); if (mDecoder->flush() != OK) { GMDD_LOG("flush error"); mDecodeCallback->Error(MediaDataDecoderError::FATAL_ERROR); } mIsFlushing = false; lock.NotifyAll(); }