nsresult
MediaEngineGonkVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
{
  LOG((__FUNCTION__));
  if (!mInitDone || !aStream) {
    return NS_ERROR_FAILURE;
  }

  mSources.AppendElement(aStream);

  aStream->AddTrack(aID, 0, new VideoSegment());
  aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);

  ReentrantMonitorAutoEnter sync(mCallbackMonitor);

  if (mState == kStarted) {
    return NS_OK;
  }
  mTrackID = aID;
  mImageContainer = layers::LayerManager::CreateImageContainer();

  NS_DispatchToMainThread(WrapRunnable(nsRefPtr<MediaEngineGonkVideoSource>(this),
                                       &MediaEngineGonkVideoSource::StartImpl,
                                       mCapability));
  mCallbackMonitor.Wait();
  if (mState != kStarted) {
    return NS_ERROR_FAILURE;
  }

  if (NS_FAILED(InitDirectMediaBuffer())) {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
nsresult
MediaEngineGonkVideoSource::Start(SourceMediaStream* aStream, TrackID aID,
                                  const PrincipalHandle& aPrincipalHandle)
{
  LOG((__FUNCTION__));
  if (!mInitDone || !aStream) {
    return NS_ERROR_FAILURE;
  }

  {
    MonitorAutoLock lock(mMonitor);
    mSources.AppendElement(aStream);
  }

  aStream->AddTrack(aID, 0, new VideoSegment());

  ReentrantMonitorAutoEnter sync(mCallbackMonitor);

  MOZ_ASSERT(mCameraControl, "mCameraControl is nullptr");
  if (mState == kStarted) {
    return NS_OK;
  } else if (!mCameraControl) {
    return NS_ERROR_FAILURE;
  }
  mTrackID = aID;
  mImageContainer = layers::LayerManager::CreateImageContainer();

  NS_DispatchToMainThread(WrapRunnable(RefPtr<MediaEngineGonkVideoSource>(this),
                                       &MediaEngineGonkVideoSource::StartImpl,
                                       mCapability));
  mCallbackMonitor.Wait();
  if (mState != kStarted) {
    return NS_ERROR_FAILURE;
  }

  nsTArray<nsString> focusModes;
  mCameraControl->Get(CAMERA_PARAM_SUPPORTED_FOCUSMODES, focusModes);
  for (nsTArray<nsString>::index_type i = 0; i < focusModes.Length(); ++i) {
    if (focusModes[i].EqualsASCII("continuous-video")) {
      mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, focusModes[i]);
      mCameraControl->ResumeContinuousFocus();
      break;
    }
  }

  // XXX some devices support recording camera frame only in metadata mode.
  // But GonkCameraSource requests non-metadata recording mode.
#if ANDROID_VERSION < 21
  if (NS_FAILED(InitDirectMediaBuffer())) {
    return NS_ERROR_FAILURE;
  }
#endif

  return NS_OK;
}
nsresult
MediaEngineGonkVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
{
  LOG((__FUNCTION__));
  if (!mInitDone || !aStream) {
    return NS_ERROR_FAILURE;
  }

  {
    MonitorAutoLock lock(mMonitor);
    mSources.AppendElement(aStream);
  }

  aStream->AddTrack(aID, 0, new VideoSegment());
  aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);

  ReentrantMonitorAutoEnter sync(mCallbackMonitor);

  if (mState == kStarted) {
    return NS_OK;
  }
  mTrackID = aID;
  mImageContainer = layers::LayerManager::CreateImageContainer();

  NS_DispatchToMainThread(WrapRunnable(nsRefPtr<MediaEngineGonkVideoSource>(this),
                                       &MediaEngineGonkVideoSource::StartImpl,
                                       mCapability));
  mCallbackMonitor.Wait();
  if (mState != kStarted) {
    return NS_ERROR_FAILURE;
  }

  nsTArray<nsString> focusModes;
  mCameraControl->Get(CAMERA_PARAM_SUPPORTED_FOCUSMODES, focusModes);
  for (nsTArray<nsString>::index_type i = 0; i < focusModes.Length(); ++i) {
    if (focusModes[i].EqualsASCII("continuous-video")) {
      mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, focusModes[i]);
      mCameraControl->ResumeContinuousFocus();
      break;
    }
  }

  if (NS_FAILED(InitDirectMediaBuffer())) {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}