Esempio n. 1
0
void
DecoderCallbackFuzzingWrapper::InputExhausted()
{
  if (!mTaskQueue->IsCurrentThreadIn()) {
    nsCOMPtr<nsIRunnable> task =
      NS_NewRunnableMethod(this, &DecoderCallbackFuzzingWrapper::InputExhausted);
    mTaskQueue->Dispatch(task.forget());
    return;
  }
  if (!mDontDelayInputExhausted && !mDelayedOutput.empty()) {
    MediaDataAndInputExhausted& last = mDelayedOutput.back();
    CFW_LOGD("InputExhausted delayed until after output of sample@%lld",
             last.first()->mTime);
    last.second() = true;
    return;
  }
  CFW_LOGV("");
  MOZ_ASSERT(mCallback);
  mCallback->InputExhausted();
}
Esempio n. 2
0
void
DecoderCallbackFuzzingWrapper::DrainComplete()
{
  if (!mTaskQueue->IsCurrentThreadIn()) {
    nsCOMPtr<nsIRunnable> task =
      NS_NewRunnableMethod(this, &DecoderCallbackFuzzingWrapper::DrainComplete);
    mTaskQueue->Dispatch(task.forget());
    return;
  }
  MOZ_ASSERT(mCallback);
  if (mDelayedOutput.empty()) {
    // No queued output -> Draining is complete now.
    CFW_LOGV("No delayed output -> DrainComplete now");
    mCallback->DrainComplete();
  } else {
    // Queued output waiting -> Make sure we call DrainComplete when it's empty.
    CFW_LOGD("Delayed output -> DrainComplete later");
    mDraining = true;
  }
}
nsresult
LazyIdleThread::EnsureThread()
{
  ASSERT_OWNING_THREAD();

  if (mShutdown) {
    return NS_ERROR_UNEXPECTED;
  }

  if (mThread) {
    return NS_OK;
  }

  MOZ_ASSERT(!mPendingEventCount, "Shouldn't have events yet!");
  MOZ_ASSERT(!mIdleNotificationCount, "Shouldn't have idle events yet!");
  MOZ_ASSERT(!mIdleTimer, "Should have killed this long ago!");
  MOZ_ASSERT(!mThreadIsShuttingDown, "Should have cleared that!");

  nsresult rv;

  if (mShutdownMethod == AutomaticShutdown && NS_IsMainThread()) {
    nsCOMPtr<nsIObserverService> obs =
      do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = obs->AddObserver(this, "xpcom-shutdown-threads", false);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  mIdleTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
  NS_ENSURE_TRUE(mIdleTimer, NS_ERROR_FAILURE);

  nsCOMPtr<nsIRunnable> runnable =
    NS_NewRunnableMethod(this, &LazyIdleThread::InitThread);
  NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE);

  rv = NS_NewThread(getter_AddRefs(mThread), runnable);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
Esempio n. 4
0
NS_IMETHODIMP_(MozExternalRefCountType) SharedThreadPool::Release(void)
{
  MOZ_ASSERT(sMonitor);
  bool dispatchShutdownEvent;
  {
    ReentrantMonitorAutoEnter mon(*sMonitor);
    nsrefcnt count = --mRefCnt;
    NS_LOG_RELEASE(this, count, "SharedThreadPool");
    if (count) {
      return count;
    }

    // Zero refcount. Must shutdown and then delete the thread pool.

    // First, dispatch an event to the main thread to call Shutdown() on
    // the nsIThreadPool. The Runnable here  will add a refcount to the pool,
    // and when the Runnable releases the nsIThreadPool it will be deleted.
    RefPtr<nsIRunnable> r = NS_NewRunnableMethod(mPool, &nsIThreadPool::Shutdown);
    NS_DispatchToMainThread(r);

    // Remove SharedThreadPool from table of pools.
    sPools->Remove(mName);
    MOZ_ASSERT(!sPools->Get(mName));

    // Stabilize refcount, so that if something in the dtor QIs,
    // it won't explode.
    mRefCnt = 1;

    delete this;

    dispatchShutdownEvent = sPools->Count() == 0;
  }
  if (dispatchShutdownEvent) {
    // No more SharedThreadPools alive. Destroy the hash table.
    // Ensure that we only run on the main thread.
    // Do this in an event so that if something holds the monitor we won't
    // be deleting the monitor while it's held.
    NS_DispatchToMainThread(new ShutdownPoolsEvent());
  }
  return 0;
}
Esempio n. 5
0
nsresult
AudioSink::Init()
{
  nsresult rv = NS_NewNamedThread("Media Audio",
                                  getter_AddRefs(mThread),
                                  nullptr,
                                  MEDIA_THREAD_STACK_SIZE);
  if (NS_FAILED(rv)) {
    mStateMachine->OnAudioSinkError();
    return rv;
  }

  nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &AudioSink::AudioLoop);
  rv =  mThread->Dispatch(event, NS_DISPATCH_NORMAL);
  if (NS_FAILED(rv)) {
    mStateMachine->OnAudioSinkError();
    return rv;
  }

  return NS_OK;
}
nsresult
MediaCodecDataDecoder::InitDecoder(Surface::Param aSurface)
{
  mDecoder = CreateDecoder(mMimeType);
  if (!mDecoder) {
    INVOKE_CALLBACK(Error);
    return NS_ERROR_FAILURE;
  }

  nsresult rv;
  NS_ENSURE_SUCCESS(rv = mDecoder->Configure(mFormat, aSurface, nullptr, 0), rv);
  NS_ENSURE_SUCCESS(rv = mDecoder->Start(), rv);

  NS_ENSURE_SUCCESS(rv = ResetInputBuffers(), rv);
  NS_ENSURE_SUCCESS(rv = ResetOutputBuffers(), rv);

  NS_NewNamedThread("MC Decoder", getter_AddRefs(mThread),
                    NS_NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop));

  return NS_OK;
}
// Called on the control thread.
nsresult
BackgroundFileSaver::GetWorkerThreadAttention(bool aShouldInterruptCopy)
{
  nsresult rv;

  MutexAutoLock lock(mLock);

  // We only require attention one time.  If this function is called two times
  // before the worker thread wakes up, and the first has aShouldInterruptCopy
  // false and the second true, we won't forcibly interrupt the copy from the
  // control thread.  However, that never happens, because calling Finish with a
  // success code is the only case that may result in aShouldInterruptCopy being
  // false.  In that case, we won't call this function again, because consumers
  // should not invoke other methods on the control thread after calling Finish.
  // And in any case, Finish already closes one end of the pipe, causing the
  // copy to finish properly on its own.
  if (mWorkerThreadAttentionRequested) {
    return NS_OK;
  }

  if (!mAsyncCopyContext) {
    // Copy is not in progress, post an event to handle the change manually.
    nsCOMPtr<nsIRunnable> event =
      NS_NewRunnableMethod(this, &BackgroundFileSaver::ProcessAttention);
    NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);

    rv = mWorkerThread->Dispatch(event, NS_DISPATCH_NORMAL);
    NS_ENSURE_SUCCESS(rv, rv);
  } else if (aShouldInterruptCopy) {
    // Interrupt the copy.  The copy will be resumed, if needed, by the
    // ProcessAttention function, invoked by the AsyncCopyCallback function.
    NS_CancelAsyncCopy(mAsyncCopyContext, NS_ERROR_ABORT);
  }

  // Indicate that attention has been requested successfully, there is no need
  // to post another event until the worker thread processes the current one.
  mWorkerThreadAttentionRequested = true;

  return NS_OK;
}
void
CacheStorageService::OnMemoryConsumptionChange(CacheMemoryConsumer* aConsumer,
                                               uint32_t aCurrentMemoryConsumption)
{
  LOG(("CacheStorageService::OnMemoryConsumptionChange [consumer=%p, size=%u]",
    aConsumer, aCurrentMemoryConsumption));

  uint32_t savedMemorySize = aConsumer->mReportedMemoryConsumption;
  if (savedMemorySize == aCurrentMemoryConsumption)
    return;

  // Exchange saved size with current one.
  aConsumer->mReportedMemoryConsumption = aCurrentMemoryConsumption;

  mMemorySize -= savedMemorySize;
  mMemorySize += aCurrentMemoryConsumption;

  LOG(("  mMemorySize=%u (+%u,-%u)", uint32_t(mMemorySize), aCurrentMemoryConsumption, savedMemorySize));

  // Bypass purging when memory has not grew up significantly
  if (aCurrentMemoryConsumption <= savedMemorySize)
    return;

  if (mPurging) {
    LOG(("  already purging"));
    return;
  }

  if (mMemorySize <= CacheObserver::MemoryLimit())
    return;

  // Throw the oldest data or whole entries away when over certain limits
  mPurging = true;

  // Must always dipatch, since this can be called under e.g. a CacheFile's lock.
  nsCOMPtr<nsIRunnable> event =
    NS_NewRunnableMethod(this, &CacheStorageService::PurgeOverMemoryLimit);

  Dispatch(event);
}
Esempio n. 9
0
nsRefPtr<GenericPromise>
AudioSink::Init()
{
  nsRefPtr<GenericPromise> p = mEndPromise.Ensure(__func__);
  nsresult rv = NS_NewNamedThread("Media Audio",
                                  getter_AddRefs(mThread),
                                  nullptr,
                                  MEDIA_THREAD_STACK_SIZE);
  if (NS_FAILED(rv)) {
    mEndPromise.Reject(rv, __func__);
    return p;
  }

  nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &AudioSink::AudioLoop);
  rv =  mThread->Dispatch(event, NS_DISPATCH_NORMAL);
  if (NS_FAILED(rv)) {
    mEndPromise.Reject(rv, __func__);
    return p;
  }

  return p;
}
Esempio n. 10
0
nsresult
MediaSourceDecoder::SetCDMProxy(CDMProxy* aProxy)
{
  nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = mReader->SetCDMProxy(aProxy);
  NS_ENSURE_SUCCESS(rv, rv);

  if (aProxy) {
    // The sub readers can't decrypt EME content until they have a CDMProxy,
    // and the CDMProxy knows the capabilities of the CDM. The MediaSourceReader
    // remains in "waiting for resources" state until then. We need to kick the
    // reader out of waiting if the CDM gets added with known capabilities.
    CDMCaps::AutoLock caps(aProxy->Capabilites());
    if (!caps.AreCapsKnown()) {
      nsCOMPtr<nsIRunnable> task(
        NS_NewRunnableMethod(this, &MediaDecoder::NotifyWaitingForResourcesStatusChanged));
      caps.CallOnMainThreadWhenCapsAvailable(task);
    }
  }
  return NS_OK;
}
Esempio n. 11
0
NS_IMETHODIMP
LazyIdleThread::AfterProcessNextEvent(nsIThreadInternal* /* aThread */,
                                      uint32_t /* aRecursionDepth */,
                                      bool aEventWasProcessed)
{
    bool shouldNotifyIdle;
    {
        MutexAutoLock lock(mMutex);

        if (aEventWasProcessed) {
            MOZ_ASSERT(mPendingEventCount, "Mismatched calls to observer methods!");
            --mPendingEventCount;
        }

        if (mThreadIsShuttingDown) {
            // We're shutting down, no need to fire any timer.
            return NS_OK;
        }

        shouldNotifyIdle = !mPendingEventCount;
        if (shouldNotifyIdle) {
            MOZ_ASSERT(mIdleNotificationCount < UINT32_MAX, "Way too many!");
            mIdleNotificationCount++;
        }
    }

    if (shouldNotifyIdle) {
        nsCOMPtr<nsIRunnable> runnable =
            NS_NewRunnableMethod(this, &LazyIdleThread::ScheduleTimer);
        if (NS_WARN_IF(!runnable))
            return NS_ERROR_UNEXPECTED;

        nsresult rv = mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
        if (NS_WARN_IF(NS_FAILED(rv)))
            return rv;
    }

    return NS_OK;
}
Esempio n. 12
0
void CacheStorageService::Shutdown()
{
  if (mShutdown)
    return;

  LOG(("CacheStorageService::Shutdown - start"));

  mShutdown = true;

  nsCOMPtr<nsIRunnable> event =
    NS_NewRunnableMethod(this, &CacheStorageService::ShutdownBackground);

  if (mThread)
    mThread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);

  mozilla::MutexAutoLock lock(mLock);
  sGlobalEntryTables->Clear();
  delete sGlobalEntryTables;
  sGlobalEntryTables = nullptr;

  LOG(("CacheStorageService::Shutdown - done"));
}
Esempio n. 13
0
void Tickler::MaybeStartTickler()
{
  mLock.AssertCurrentThreadOwns();
  if (!NS_IsMainThread()) {
    NS_DispatchToMainThread(
      NS_NewRunnableMethod(this, &Tickler::MaybeStartTicklerUnlocked),
      NS_DISPATCH_NORMAL);
    return;
  }

  if (!mPrefs)
    mPrefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  if (mPrefs) {
    int32_t val;
    bool boolVal;

    if (NS_SUCCEEDED(mPrefs->GetBoolPref("network.tickle-wifi.enabled", &boolVal)))
      mEnabled = boolVal;

    if (NS_SUCCEEDED(mPrefs->GetIntPref("network.tickle-wifi.duration", &val))) {
      if (val < 1)
        val = 1;
      if (val > 100000)
        val = 100000;
      mDuration = TimeDuration::FromMilliseconds(val);
    }

    if (NS_SUCCEEDED(mPrefs->GetIntPref("network.tickle-wifi.delay", &val))) {
      if (val < 1)
        val = 1;
      if (val > 1000)
        val = 1000;
      mDelay = static_cast<uint32_t>(val);
    }
  }

  PostCheckTickler();
}
Esempio n. 14
0
void
CacheStorageService::OnMemoryConsumptionChange(CacheMemoryConsumer* aConsumer,
                                               uint32_t aCurrentMemoryConsumption)
{
  LOG(("CacheStorageService::OnMemoryConsumptionChange [consumer=%p, size=%u]",
    aConsumer, aCurrentMemoryConsumption));

  uint32_t savedMemorySize = aConsumer->mReportedMemoryConsumption;
  if (savedMemorySize == aCurrentMemoryConsumption)
    return;

  // Exchange saved size with current one.
  aConsumer->mReportedMemoryConsumption = aCurrentMemoryConsumption;

  bool usingDisk = !(aConsumer->mFlags & CacheMemoryConsumer::MEMORY_ONLY);
  bool overLimit = Pool(usingDisk).OnMemoryConsumptionChange(
    savedMemorySize, aCurrentMemoryConsumption);

  if (!overLimit)
    return;

  // It's likely the timer has already been set when we get here,
  // check outside the lock to save resources.
  if (mPurgeTimer)
    return;

  // We don't know if this is called under the service lock or not,
  // hence rather dispatch.
  nsRefPtr<nsIEventTarget> cacheIOTarget = Thread();
  if (!cacheIOTarget)
    return;

  // Dispatch as a priority task, we want to set the purge timer
  // ASAP to prevent vain redispatch of this event.
  nsCOMPtr<nsIRunnable> event =
    NS_NewRunnableMethod(this, &CacheStorageService::SchedulePurgeOverMemoryLimit);
  cacheIOTarget->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
}
Esempio n. 15
0
void
MediaSourceDecoder::ScheduleDurationChange(double aOldDuration,
                                           double aNewDuration,
                                           MSRangeRemovalAction aAction)
{
  if (aAction == MSRangeRemovalAction::SKIP) {
    if (NS_IsMainThread()) {
      MediaDecoder::DurationChanged();
    } else {
      nsCOMPtr<nsIRunnable> task =
        NS_NewRunnableMethod(this, &MediaDecoder::DurationChanged);
      NS_DispatchToMainThread(task);
    }
  } else {
    if (NS_IsMainThread()) {
      DurationChanged(aOldDuration, aNewDuration);
    } else {
      nsCOMPtr<nsIRunnable> task =
        new DurationChangedRunnable(this, aOldDuration, aNewDuration);
      NS_DispatchToMainThread(task);
    }
  }
}
Esempio n. 16
0
nsresult
HTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                            nsIContent* aBindingParent,
                            bool aCompileEventHandlers)
{
    Link::ResetLinkState(false, Link::ElementHasHref());

    nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                  aBindingParent,
                  aCompileEventHandlers);
    NS_ENSURE_SUCCESS(rv, rv);

    if (aDocument) {
        aDocument->RegisterPendingLinkUpdate(this);
    }

    void (HTMLLinkElement::*update)() = &HTMLLinkElement::UpdateStyleSheetInternal;
    nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, update));

    CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded"));

    return rv;
}
Esempio n. 17
0
  NS_IMETHOD Run()
  {
    MOZ_ASSERT(!NS_IsMainThread());

    bool continueThread;

    do {
      continueThread = mDBusWatcher->Poll();
    } while (continueThread);

    mDBusWatcher->CleanUp();

    nsIThread* thread;
    nsresult rv = NS_GetCurrentThread(&thread);
    NS_ENSURE_SUCCESS(rv, rv);

    nsRefPtr<nsIRunnable> runnable =
      NS_NewRunnableMethod(thread, &nsIThread::Shutdown);
    rv = NS_DispatchToMainThread(runnable);
    NS_ENSURE_SUCCESS(rv, rv);

    return NS_OK;
  }
Esempio n. 18
0
MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder,
                                       MediaTaskQueue* aBorrowedTaskQueue)
  : mAudioCompactor(mAudioQueue)
  , mDecoder(aDecoder)
  , mTaskQueue(aBorrowedTaskQueue ? aBorrowedTaskQueue
                                  : new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
                                                       /* aSupportsTailDispatch = */ true))
  , mDuration(mTaskQueue, NullableTimeUnit(), "MediaDecoderReader::mDuration (Mirror)")
  , mIgnoreAudioOutputFormat(false)
  , mStartTime(-1)
  , mHitAudioDecodeError(false)
  , mShutdown(false)
  , mTaskQueueIsBorrowed(!!aBorrowedTaskQueue)
  , mAudioDiscontinuity(false)
  , mVideoDiscontinuity(false)
{
  MOZ_COUNT_CTOR(MediaDecoderReader);
  MOZ_ASSERT(NS_IsMainThread());

  // Dispatch initialization that needs to happen on that task queue.
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(this, &MediaDecoderReader::InitializationTask);
  mTaskQueue->Dispatch(r.forget());
}
MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
  : mAudioCompactor(mAudioQueue)
  , mDecoder(aDecoder)
  , mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
                             /* aSupportsTailDispatch = */ true))
  , mWatchManager(this, mTaskQueue)
  , mTimer(new MediaTimer())
  , mBuffered(mTaskQueue, TimeIntervals(), "MediaDecoderReader::mBuffered (Canonical)")
  , mDuration(mTaskQueue, NullableTimeUnit(), "MediaDecoderReader::mDuration (Mirror)")
  , mThrottleDuration(TimeDuration::FromMilliseconds(500))
  , mLastThrottledNotify(TimeStamp::Now() - mThrottleDuration)
  , mIgnoreAudioOutputFormat(false)
  , mHitAudioDecodeError(false)
  , mShutdown(false)
  , mAudioDiscontinuity(false)
  , mVideoDiscontinuity(false)
{
  MOZ_COUNT_CTOR(MediaDecoderReader);
  MOZ_ASSERT(NS_IsMainThread());

  // Dispatch initialization that needs to happen on that task queue.
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(this, &MediaDecoderReader::InitializationTask);
  mTaskQueue->Dispatch(r.forget());
}
nsresult
HTMLTrackElement::BindToTree(nsIDocument* aDocument,
                             nsIContent* aParent,
                             nsIContent* aBindingParent,
                             bool aCompileEventHandlers)
{
  nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
                                                 aParent,
                                                 aBindingParent,
                                                 aCompileEventHandlers);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!aDocument) {
    return NS_OK;
  }

  LOG(PR_LOG_DEBUG, ("Track Element bound to tree."));
  if (!aParent || !aParent->IsNodeOfType(nsINode::eMEDIA)) {
    return NS_OK;
  }

  // Store our parent so we can look up its frame for display.
  if (!mMediaParent) {
    mMediaParent = static_cast<HTMLMediaElement*>(aParent);

    HTMLMediaElement* media = static_cast<HTMLMediaElement*>(aParent);
    // TODO: separate notification for 'alternate' tracks?
    media->NotifyAddedSource();
    LOG(PR_LOG_DEBUG, ("Track element sent notification to parent."));

    mMediaParent->RunInStableState(
      NS_NewRunnableMethod(this, &HTMLTrackElement::LoadResource));
  }

  return NS_OK;
}
Esempio n. 21
0
nsresult
nsPACMan::LoadPACFromURI(nsIURI *pacURI)
{
  NS_ENSURE_STATE(!mShutdown);
  NS_ENSURE_ARG(pacURI || mPACURI);

  nsCOMPtr<nsIStreamLoader> loader =
      do_CreateInstance(NS_STREAMLOADER_CONTRACTID);
  NS_ENSURE_STATE(loader);

  // Since we might get called from nsProtocolProxyService::Init, we need to
  // post an event back to the main thread before we try to use the IO service.
  //
  // But, we need to flag ourselves as loading, so that we queue up any PAC
  // queries the enter between now and when we actually load the PAC file.

  if (!mLoadPending) {
    nsCOMPtr<nsIRunnable> event =
      NS_NewRunnableMethod(this, &nsPACMan::StartLoading);
    nsresult rv;
    if (NS_FAILED(rv = NS_DispatchToCurrentThread(event)))
      return rv;
    mLoadPending = true;
  }

  CancelExistingLoad();

  mLoader = loader;
  if (pacURI) {
    mPACURI = pacURI;
    mLoadFailureCount = 0;  // reset
  }
  mScheduledReload = LL_MAXINT;
  mPAC = nsnull;
  return NS_OK;
}
Esempio n. 22
0
NS_IMETHODIMP
EventSource::OnStopRequest(nsIRequest *aRequest,
                           nsISupports *aContext,
                           nsresult aStatusCode)
{
  mWaitingForOnStopRequest = false;

  if (mReadyState == CLOSED) {
    return NS_ERROR_ABORT;
  }

  if (NS_FAILED(aStatusCode)) {
    DispatchFailConnection();
    return aStatusCode;
  }

  nsresult rv;
  nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest);
  if (NS_SUCCEEDED(healthOfRequestResult) &&
      mLastConvertionResult == NS_PARTIAL_MORE_INPUT) {
    // we had an incomplete UTF8 char at the end of the stream
    rv = ParseCharacter(REPLACEMENT_CHAR);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  ClearFields();

  nsCOMPtr<nsIRunnable> event =
    NS_NewRunnableMethod(this, &EventSource::ReestablishConnection);
  NS_ENSURE_STATE(event);

  rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
  NS_ENSURE_SUCCESS(rv, rv);

  return healthOfRequestResult;
}
Esempio n. 23
0
nsresult
EMEAudioDecoder::Flush()
{
  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.

  {
    MonitorAutoLock mon(mMonitor);
    mFlushComplete = false;
  }

  nsRefPtr<nsIRunnable> task;
  task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpFlush);
  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
  NS_ENSURE_SUCCESS(rv, rv);

  {
    MonitorAutoLock mon(mMonitor);
    while (!mFlushComplete) {
      mon.Wait();
    }
  }

  return NS_OK;
}
Esempio n. 24
0
void AudioOffloadPlayer::NotifyAudioEOS()
{
  nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
      &MediaDecoder::PlaybackEnded);
  NS_DispatchToMainThread(nsEvent);
}
nsresult
GonkMediaDataDecoder::Drain()
{
  mTaskQueue->Dispatch(NS_NewRunnableMethod(this, &GonkMediaDataDecoder::ProcessDrain));
  return NS_OK;
}
Esempio n. 26
0
void
nsPicoService::Init()
{
  MOZ_ASSERT(!NS_IsMainThread());
  MOZ_ASSERT(!mInitialized);

  if (!sPicoApi.Init()) {
    NS_WARNING("Failed to initialize pico library");
    return;
  }

  // Use environment variable, or default android/b2g path
  nsAutoCString langPath(PR_GetEnv("PICO_LANG_PATH"));

  if (langPath.IsEmpty()) {
    langPath.AssignLiteral(GONK_PICO_LANG_PATH);
  }

  nsCOMPtr<nsIFile> voicesDir;
  NS_NewNativeLocalFile(langPath, true, getter_AddRefs(voicesDir));

  nsCOMPtr<nsISimpleEnumerator> dirIterator;
  nsresult rv = voicesDir->GetDirectoryEntries(getter_AddRefs(dirIterator));

  if (NS_FAILED(rv)) {
    NS_WARNING(nsPrintfCString("Failed to get contents of directory: %s", langPath.get()).get());
    return;
  }

  bool hasMoreElements = false;
  rv = dirIterator->HasMoreElements(&hasMoreElements);
  MOZ_ASSERT(NS_SUCCEEDED(rv));

  MonitorAutoLock autoLock(mVoicesMonitor);

  while (hasMoreElements && NS_SUCCEEDED(rv)) {
    nsCOMPtr<nsISupports> supports;
    rv = dirIterator->GetNext(getter_AddRefs(supports));
    MOZ_ASSERT(NS_SUCCEEDED(rv));

    nsCOMPtr<nsIFile> voiceFile = do_QueryInterface(supports);
    MOZ_ASSERT(voiceFile);

    nsAutoCString leafName;
    voiceFile->GetNativeLeafName(leafName);

    nsAutoString lang;

    if (GetVoiceFileLanguage(leafName, lang)) {
      nsAutoString uri;
      uri.AssignLiteral("urn:moz-tts:pico:");
      uri.Append(lang);

      bool found = false;
      PicoVoice* voice = mVoices.GetWeak(uri, &found);

      if (!found) {
        voice = new PicoVoice(lang);
        mVoices.Put(uri, voice);
      }

      // Each voice consists of two lingware files: A language resource file,
      // suffixed by _ta.bin, and a speaker resource file, suffixed by _sb.bin.
      // We currently assume that there is a pair of files for each language.
      if (StringEndsWith(leafName, NS_LITERAL_CSTRING("_ta.bin"))) {
        rv = voiceFile->GetPersistentDescriptor(voice->mTaFile);
        MOZ_ASSERT(NS_SUCCEEDED(rv));
      } else if (StringEndsWith(leafName, NS_LITERAL_CSTRING("_sg.bin"))) {
        rv = voiceFile->GetPersistentDescriptor(voice->mSgFile);
        MOZ_ASSERT(NS_SUCCEEDED(rv));
      }
    }

    rv = dirIterator->HasMoreElements(&hasMoreElements);
  }

  NS_DispatchToMainThread(NS_NewRunnableMethod(this, &nsPicoService::RegisterVoices));
}
Esempio n. 27
0
void AudioOffloadPlayer::NotifyPositionChanged()
{
  nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
      &MediaOmxCommonDecoder::PlaybackPositionChanged);
  NS_DispatchToMainThread(nsEvent);
}
Esempio n. 28
0
void
DASHRepDecoder::LoadNextByteRange()
{
  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
  NS_ASSERTION(mResource, "Error: resource is reported as null!");

  // Return silently if shutting down.
  if (mShuttingDown) {
    LOG1("Shutting down! Ignoring LoadNextByteRange().");
    return;
  }

  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
  NS_ASSERTION(mMainDecoder, "Error: main decoder is null!");
  NS_ASSERTION(mMainDecoder->IsDecoderAllowedToDownloadData(this),
               "Should not be called on non-active decoders!");

  // Cannot have empty byte ranges.
  if (mByteRanges.IsEmpty()) {
    LOG1("Error getting list of subsegment byte ranges.");
    DecodeError();
    return;
  }

  // Get byte range for subsegment.
  int32_t subsegmentIdx = mMainDecoder->GetSubsegmentIndex(this);
  NS_ASSERTION(0 <= subsegmentIdx,
               "Subsegment index should be >= 0 for active decoders");
  if (subsegmentIdx >= 0 && (uint32_t)subsegmentIdx < mByteRanges.Length()) {
    mCurrentByteRange = mByteRanges[subsegmentIdx];
    mSubsegmentIdx = subsegmentIdx;
  } else {
    mCurrentByteRange.Clear();
    mSubsegmentIdx = -1;
    LOG("End of subsegments: index [%d] out of range.", subsegmentIdx);
    return;
  }

  // Request a seek for the first reader. Required so that the reader is
  // primed to start here, and will block subsequent subsegment seeks unless
  // the subsegment has been read.
  if (subsegmentIdx == 0) {
    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    mReader->RequestSeekToSubsegment(0);
  }

  // Query resource for cached ranges; only download if it's not there.
  if (IsSubsegmentCached(mSubsegmentIdx)) {
    LOG("Subsegment [%d] bytes [%lld] to [%lld] already cached. No need to "
        "download.", mSubsegmentIdx,
        mCurrentByteRange.mStart, mCurrentByteRange.mEnd);
    nsCOMPtr<nsIRunnable> event =
      NS_NewRunnableMethod(this, &DASHRepDecoder::DoNotifyDownloadEnded);
    nsresult rv = NS_DispatchToMainThread(event);
    if (NS_FAILED(rv)) {
      LOG("Error notifying subsegment [%d] cached: rv[0x%x].",
          mSubsegmentIdx, rv);
      NetworkError();
    }
    return;
  }

  // Open byte range corresponding to subsegment.
  nsresult rv = mResource->OpenByteRange(nullptr, mCurrentByteRange);
  if (NS_FAILED(rv)) {
    LOG("Error opening byte range [%lld - %lld]: subsegmentIdx [%d] rv [%x].",
        mCurrentByteRange.mStart, mCurrentByteRange.mEnd, mSubsegmentIdx, rv);
    NetworkError();
    return;
  }
}
Esempio n. 29
0
size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize)
{
  CHECK(mAudioSink.get());

  if (mReachedEOS) {
    return 0;
  }

  size_t sizeDone = 0;
  size_t sizeRemaining = aSize;
  while (sizeRemaining > 0) {
    MediaSource::ReadOptions options;
    bool refreshSeekTime = false;

    {
      android::Mutex::Autolock autoLock(mLock);

      if (mSeeking) {
        options.setSeekTo(mSeekTimeUs);
        refreshSeekTime = true;

        if (mInputBuffer) {
          mInputBuffer->release();
          mInputBuffer = nullptr;
        }
        mSeeking = false;
      }
    }

    if (!mInputBuffer) {

      status_t err;
      err = mSource->read(&mInputBuffer, &options);

      CHECK((!err && mInputBuffer) || (err && !mInputBuffer));

      android::Mutex::Autolock autoLock(mLock);

      if (err != OK) {
        AUDIO_OFFLOAD_LOG(PR_LOG_ERROR, ("Error while reading media source %d "
            "Ok to receive EOS error at end", err));
        if (!mReachedEOS) {
          // After seek there is a possible race condition if
          // OffloadThread is observing state_stopping_1 before
          // framesReady() > 0. Ensure sink stop is called
          // after last buffer is released. This ensures the
          // partial buffer is written to the driver before
          // stopping one is observed.The drawback is that
          // there will be an unnecessary call to the parser
          // after parser signalled EOS.
          if (sizeDone > 0) {
            AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("send Partial buffer down"));
            AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("skip calling stop till next"
                " fillBuffer"));
            break;
          }
          // no more buffers to push - stop() and wait for STREAM_END
          // don't set mReachedEOS until stream end received
          mAudioSink->Stop();
        }
        break;
      }

      if(mInputBuffer->range_length() != 0) {
        CHECK(mInputBuffer->meta_data()->findInt64(
            kKeyTime, &mPositionTimeMediaUs));
      }

      if (refreshSeekTime) {
        if (mDispatchSeekEvents && !mSeekDuringPause) {
          mDispatchSeekEvents = false;
          AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("FillBuffer posting SEEK_COMPLETE"));
          nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
              &MediaDecoder::SeekingStopped);
          NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);

        } else if (mSeekDuringPause) {
          // Callback is already called for seek during pause. Just reset the
          // flag
          AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Not posting seek complete as its"
              " already faked"));
          mSeekDuringPause = false;
        }

        NotifyPositionChanged();

        // need to adjust the mStartPosUs for offload decoding since parser
        // might not be able to get the exact seek time requested.
        mStartPosUs = mPositionTimeMediaUs;
        AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Adjust seek time to: %.2f",
            mStartPosUs / 1E6));

        // clear seek time with mLock locked and once we have valid
        // mPositionTimeMediaUs
        // before clearing mSeekTimeUs check if a new seek request has been
        // received while we were reading from the source with mLock released.
        if (!mSeeking) {
          mSeekTimeUs = 0;
        }
      }
    }

    if (mInputBuffer->range_length() == 0) {
      mInputBuffer->release();
      mInputBuffer = nullptr;
      continue;
    }

    size_t copy = sizeRemaining;
    if (copy > mInputBuffer->range_length()) {
      copy = mInputBuffer->range_length();
    }

    memcpy((char *)aData + sizeDone,
        (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
        copy);

    mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
        mInputBuffer->range_length() - copy);

    sizeDone += copy;
    sizeRemaining -= copy;
  }
  return sizeDone;
}
Esempio n. 30
0
void AudioOffloadPlayer::NotifyAudioTearDown()
{
  nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
      &MediaOmxCommonDecoder::AudioOffloadTearDown);
  NS_DispatchToMainThread(nsEvent);
}