コード例 #1
0
int32_t
GonkDecoderManager::ProcessQueuedSamples()
{
  MOZ_ASSERT(OnTaskLooper());

  MutexAutoLock lock(mMutex);
  status_t rv;
  while (mQueuedSamples.Length()) {
    RefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0);
    rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
                         data->Size(),
                         data->mTime,
                         0,
                         INPUT_TIMEOUT_US);
    if (rv == OK) {
      mQueuedSamples.RemoveElementAt(0);
      mWaitOutput.AppendElement(WaitOutputInfo(data->mOffset, data->mTime,
                                               /* eos */ data->Data() == nullptr));
    } else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
      // In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
      // buffer on time.
      break;
    } else {
      return rv;
    }
  }
  return mQueuedSamples.Length();
}
コード例 #2
0
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);
  }
}
コード例 #3
0
void
GonkDecoderManager::ProcessToDo(bool aEndOfStream)
{
  MOZ_ASSERT(OnTaskLooper());

  MOZ_ASSERT(mToDo.get() != nullptr);
  mToDo.clear();

  if (NumQueuedSamples() > 0 && ProcessQueuedSamples() < 0) {
    mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                                            __func__));
    return;
  }

  while (mWaitOutput.Length() > 0) {
    RefPtr<MediaData> output;
    WaitOutputInfo wait = mWaitOutput.ElementAt(0);
    nsresult rv = Output(wait.mOffset, output);
    if (rv == NS_OK) {
      MOZ_ASSERT(output);
      mDecodeCallback->Output(output);
      UpdateWaitingList(output->mTime);
    } else if (rv == NS_ERROR_ABORT) {
      // EOS
      MOZ_ASSERT(mQueuedSamples.IsEmpty());
      if (output) {
        mDecodeCallback->Output(output);
        UpdateWaitingList(output->mTime);
      }
      MOZ_ASSERT(mWaitOutput.Length() == 1);
      mWaitOutput.RemoveElementAt(0);
      mDecodeCallback->DrainComplete();
      ResetEOS();
      return;
    } else if (rv == NS_ERROR_NOT_AVAILABLE) {
      break;
    } else {
      mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                                              __func__));
      return;
    }
  }

  if (!aEndOfStream && NumQueuedSamples() <= MIN_QUEUED_SAMPLES) {
    mDecodeCallback->InputExhausted();
    // No need to shedule todo task this time because InputExhausted() will
    // cause Input() to be invoked and do it for us.
    return;
  }

  if (NumQueuedSamples() || mWaitOutput.Length() > 0) {
    mToDo = new AMessage(kNotifyDecoderActivity, id());
    if (aEndOfStream) {
      mToDo->setInt32("input-eos", 1);
    }
    mDecoder->requestActivityNotification(mToDo);
  }
}
コード例 #4
0
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();
}
コード例 #5
0
// Use output timestamp to determine which output buffer is already returned
// and remove corresponding info, except for EOS, from the waiting list.
// This method handles the cases that audio decoder sends multiple output
// buffers for one input.
void
GonkDecoderManager::UpdateWaitingList(int64_t aForgetUpTo)
{
  MOZ_ASSERT(OnTaskLooper());

  size_t i;
  for (i = 0; i < mWaitOutput.Length(); i++) {
    const auto& item = mWaitOutput.ElementAt(i);
    if (item.mEOS || item.mTimestamp > aForgetUpTo) {
      break;
    }
  }
  if (i > 0) {
    mWaitOutput.RemoveElementsAt(0, i);
  }
}