dom/camera/DOMCameraControlListener.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/camera/DOMCameraControlListener.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,406 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 +* License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 +* You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "DOMCameraControlListener.h"
     1.9 +#include "nsThreadUtils.h"
    1.10 +#include "nsDOMFile.h"
    1.11 +#include "CameraCommon.h"
    1.12 +#include "DOMCameraControl.h"
    1.13 +#include "CameraPreviewMediaStream.h"
    1.14 +#include "mozilla/dom/CameraManagerBinding.h"
    1.15 +
    1.16 +using namespace mozilla;
    1.17 +using namespace mozilla::dom;
    1.18 +
    1.19 +DOMCameraControlListener::DOMCameraControlListener(nsDOMCameraControl* aDOMCameraControl,
    1.20 +                                                   CameraPreviewMediaStream* aStream)
    1.21 +  : mDOMCameraControl(new nsMainThreadPtrHolder<nsDOMCameraControl>(aDOMCameraControl))
    1.22 +  , mStream(aStream)
    1.23 +{
    1.24 +  DOM_CAMERA_LOGT("%s:%d : this=%p, camera=%p, stream=%p\n",
    1.25 +    __func__, __LINE__, this, aDOMCameraControl, aStream);
    1.26 +}
    1.27 +
    1.28 +DOMCameraControlListener::~DOMCameraControlListener()
    1.29 +{
    1.30 +  DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
    1.31 +}
    1.32 +
    1.33 +// Boilerplate callback runnable
    1.34 +class DOMCameraControlListener::DOMCallback : public nsRunnable
    1.35 +{
    1.36 +public:
    1.37 +  DOMCallback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl)
    1.38 +    : mDOMCameraControl(aDOMCameraControl)
    1.39 +  {
    1.40 +    MOZ_COUNT_CTOR(DOMCameraControlListener::DOMCallback);
    1.41 +  }
    1.42 +  virtual ~DOMCallback()
    1.43 +  {
    1.44 +    MOZ_COUNT_DTOR(DOMCameraControlListener::DOMCallback);
    1.45 +  }
    1.46 +
    1.47 +  virtual void RunCallback(nsDOMCameraControl* aDOMCameraControl) = 0;
    1.48 +
    1.49 +  NS_IMETHOD
    1.50 +  Run() MOZ_OVERRIDE
    1.51 +  {
    1.52 +    MOZ_ASSERT(NS_IsMainThread());
    1.53 +
    1.54 +    nsRefPtr<nsDOMCameraControl> camera = mDOMCameraControl.get();
    1.55 +    if (camera) {
    1.56 +      RunCallback(camera);
    1.57 +    }
    1.58 +    return NS_OK;
    1.59 +  }
    1.60 +
    1.61 +protected:
    1.62 +  nsMainThreadPtrHandle<nsDOMCameraControl> mDOMCameraControl;
    1.63 +};
    1.64 +
    1.65 +// Specific callback handlers
    1.66 +void
    1.67 +DOMCameraControlListener::OnHardwareStateChange(HardwareState aState)
    1.68 +{
    1.69 +  class Callback : public DOMCallback
    1.70 +  {
    1.71 +  public:
    1.72 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
    1.73 +             HardwareState aState)
    1.74 +      : DOMCallback(aDOMCameraControl)
    1.75 +      , mState(aState)
    1.76 +    { }
    1.77 +
    1.78 +    void
    1.79 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
    1.80 +    {
    1.81 +      aDOMCameraControl->OnHardwareStateChange(mState);
    1.82 +    }
    1.83 +
    1.84 +  protected:
    1.85 +    HardwareState mState;
    1.86 +  };
    1.87 +
    1.88 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
    1.89 +}
    1.90 +
    1.91 +void
    1.92 +DOMCameraControlListener::OnPreviewStateChange(PreviewState aState)
    1.93 +{
    1.94 +  class Callback : public DOMCallback
    1.95 +  {
    1.96 +  public:
    1.97 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
    1.98 +             PreviewState aState)
    1.99 +      : DOMCallback(aDOMCameraControl)
   1.100 +      , mState(aState)
   1.101 +    { }
   1.102 +
   1.103 +    void
   1.104 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.105 +    {
   1.106 +      aDOMCameraControl->OnPreviewStateChange(mState);
   1.107 +    }
   1.108 +
   1.109 +  protected:
   1.110 +    PreviewState mState;
   1.111 +  };
   1.112 +
   1.113 +  switch (aState) {
   1.114 +    case kPreviewStopped:
   1.115 +      // Clear the current frame right away, without dispatching a
   1.116 +      //  runnable. This is an ugly coupling between the camera's
   1.117 +      //  SurfaceTextureClient and the MediaStream/ImageContainer,
   1.118 +      //  but without it, the preview can fail to start.
   1.119 +      DOM_CAMERA_LOGI("Preview stopped, clearing current frame\n");
   1.120 +      mStream->ClearCurrentFrame();
   1.121 +      break;
   1.122 +
   1.123 +    case kPreviewPaused:
   1.124 +      // In the paused state, we still want to reflect the change
   1.125 +      //  in preview state, but we don't want to clear the current
   1.126 +      //  frame as above, since doing so seems to cause genlock
   1.127 +      //  problems when we restart the preview. See bug 957749.
   1.128 +      DOM_CAMERA_LOGI("Preview paused\n");
   1.129 +      break;
   1.130 +
   1.131 +    case kPreviewStarted:
   1.132 +      DOM_CAMERA_LOGI("Preview started\n");
   1.133 +      break;
   1.134 +
   1.135 +    default:
   1.136 +      DOM_CAMERA_LOGE("Unknown preview state %d\n", aState);
   1.137 +      MOZ_ASSUME_UNREACHABLE("Invalid preview state");
   1.138 +      return;
   1.139 +  }
   1.140 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
   1.141 +}
   1.142 +
   1.143 +void
   1.144 +DOMCameraControlListener::OnRecorderStateChange(RecorderState aState,
   1.145 +                                                int32_t aStatus, int32_t aTrackNum)
   1.146 +{
   1.147 +  class Callback : public DOMCallback
   1.148 +  {
   1.149 +  public:
   1.150 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
   1.151 +             RecorderState aState,
   1.152 +             int32_t aStatus,
   1.153 +             int32_t aTrackNum)
   1.154 +      : DOMCallback(aDOMCameraControl)
   1.155 +      , mState(aState)
   1.156 +      , mStatus(aStatus)
   1.157 +      , mTrackNum(aTrackNum)
   1.158 +    { }
   1.159 +
   1.160 +    void
   1.161 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.162 +    {
   1.163 +      aDOMCameraControl->OnRecorderStateChange(mState, mStatus, mTrackNum);
   1.164 +    }
   1.165 +
   1.166 +  protected:
   1.167 +    RecorderState mState;
   1.168 +    int32_t mStatus;
   1.169 +    int32_t mTrackNum;
   1.170 +  };
   1.171 +
   1.172 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState, aStatus, aTrackNum));
   1.173 +}
   1.174 +
   1.175 +void
   1.176 +DOMCameraControlListener::OnConfigurationChange(const CameraListenerConfiguration& aConfiguration)
   1.177 +{
   1.178 +  class Callback : public DOMCallback
   1.179 +  {
   1.180 +  public:
   1.181 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
   1.182 +             const CameraListenerConfiguration& aConfiguration)
   1.183 +      : DOMCallback(aDOMCameraControl)
   1.184 +      , mConfiguration(aConfiguration)
   1.185 +    { }
   1.186 +
   1.187 +    void
   1.188 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.189 +    {
   1.190 +      nsRefPtr<nsDOMCameraControl::DOMCameraConfiguration> config =
   1.191 +        new nsDOMCameraControl::DOMCameraConfiguration();
   1.192 +
   1.193 +      switch (mConfiguration.mMode) {
   1.194 +        case ICameraControl::kVideoMode:
   1.195 +          config->mMode = CameraMode::Video;
   1.196 +          break;
   1.197 +
   1.198 +        case ICameraControl::kPictureMode:
   1.199 +          config->mMode = CameraMode::Picture;
   1.200 +          break;
   1.201 +
   1.202 +        default:
   1.203 +          DOM_CAMERA_LOGI("Camera mode still unspecified, nothing to do\n");
   1.204 +          return;
   1.205 +      }
   1.206 +
   1.207 +      // Map CameraControl parameters to their DOM-facing equivalents
   1.208 +      config->mRecorderProfile = mConfiguration.mRecorderProfile;
   1.209 +      config->mPreviewSize.mWidth = mConfiguration.mPreviewSize.width;
   1.210 +      config->mPreviewSize.mHeight = mConfiguration.mPreviewSize.height;
   1.211 +      config->mMaxMeteringAreas = mConfiguration.mMaxMeteringAreas;
   1.212 +      config->mMaxFocusAreas = mConfiguration.mMaxFocusAreas;
   1.213 +
   1.214 +      aDOMCameraControl->OnConfigurationChange(config);
   1.215 +    }
   1.216 +
   1.217 +  protected:
   1.218 +    const CameraListenerConfiguration mConfiguration;
   1.219 +  };
   1.220 +
   1.221 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aConfiguration));
   1.222 +}
   1.223 +
   1.224 +void
   1.225 +DOMCameraControlListener::OnAutoFocusMoving(bool aIsMoving)
   1.226 +{
   1.227 +  class Callback : public DOMCallback
   1.228 +  {
   1.229 +  public:
   1.230 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl, bool aIsMoving)
   1.231 +      : DOMCallback(aDOMCameraControl)
   1.232 +      , mIsMoving(aIsMoving)
   1.233 +    { }
   1.234 +
   1.235 +    void
   1.236 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.237 +    {
   1.238 +      aDOMCameraControl->OnAutoFocusMoving(mIsMoving);
   1.239 +    }
   1.240 +
   1.241 +  protected:
   1.242 +    bool mIsMoving;
   1.243 +  };
   1.244 +
   1.245 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aIsMoving));
   1.246 +}
   1.247 +
   1.248 +void
   1.249 +DOMCameraControlListener::OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces)
   1.250 +{
   1.251 +  class Callback : public DOMCallback
   1.252 +  {
   1.253 +  public:
   1.254 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
   1.255 +             const nsTArray<ICameraControl::Face>& aFaces)
   1.256 +      : DOMCallback(aDOMCameraControl)
   1.257 +      , mFaces(aFaces)
   1.258 +    { }
   1.259 +
   1.260 +    void
   1.261 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.262 +    {
   1.263 +      aDOMCameraControl->OnFacesDetected(mFaces);
   1.264 +    }
   1.265 +
   1.266 +  protected:
   1.267 +    const nsTArray<ICameraControl::Face> mFaces;
   1.268 +  };
   1.269 +
   1.270 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aFaces));
   1.271 +}
   1.272 +
   1.273 +void
   1.274 +DOMCameraControlListener::OnShutter()
   1.275 +{
   1.276 +  class Callback : public DOMCallback
   1.277 +  {
   1.278 +  public:
   1.279 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl)
   1.280 +      : DOMCallback(aDOMCameraControl)
   1.281 +    { }
   1.282 +
   1.283 +    void
   1.284 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.285 +    {
   1.286 +      aDOMCameraControl->OnShutter();
   1.287 +    }
   1.288 +  };
   1.289 +
   1.290 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl));
   1.291 +}
   1.292 +
   1.293 +bool
   1.294 +DOMCameraControlListener::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
   1.295 +{
   1.296 +  DOM_CAMERA_LOGI("OnNewPreviewFrame: got %d x %d frame\n", aWidth, aHeight);
   1.297 +
   1.298 +  mStream->SetCurrentFrame(gfxIntSize(aWidth, aHeight), aImage);
   1.299 +  return true;
   1.300 +}
   1.301 +
   1.302 +void
   1.303 +DOMCameraControlListener::OnAutoFocusComplete(bool aAutoFocusSucceeded)
   1.304 +{
   1.305 +  class Callback : public DOMCallback
   1.306 +  {
   1.307 +  public:
   1.308 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
   1.309 +             bool aAutoFocusSucceeded)
   1.310 +      : DOMCallback(aDOMCameraControl)
   1.311 +      , mAutoFocusSucceeded(aAutoFocusSucceeded)
   1.312 +    { }
   1.313 +
   1.314 +    void
   1.315 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.316 +    {
   1.317 +      aDOMCameraControl->OnAutoFocusComplete(mAutoFocusSucceeded);
   1.318 +    }
   1.319 +
   1.320 +  protected:
   1.321 +    bool mAutoFocusSucceeded;
   1.322 +  };
   1.323 +
   1.324 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aAutoFocusSucceeded));
   1.325 +}
   1.326 +
   1.327 +void
   1.328 +DOMCameraControlListener::OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
   1.329 +{
   1.330 +  class Callback : public DOMCallback
   1.331 +  {
   1.332 +  public:
   1.333 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
   1.334 +             uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
   1.335 +      : DOMCallback(aDOMCameraControl)
   1.336 +      , mData(aData)
   1.337 +      , mLength(aLength)
   1.338 +      , mMimeType(aMimeType)
   1.339 +    { }
   1.340 +
   1.341 +    void
   1.342 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.343 +    {
   1.344 +      nsCOMPtr<nsIDOMBlob> picture = new nsDOMMemoryFile(static_cast<void*>(mData),
   1.345 +                                                         static_cast<uint64_t>(mLength),
   1.346 +                                                         mMimeType);
   1.347 +      aDOMCameraControl->OnTakePictureComplete(picture);
   1.348 +    }
   1.349 +
   1.350 +  protected:
   1.351 +    uint8_t* mData;
   1.352 +    uint32_t mLength;
   1.353 +    nsString mMimeType;
   1.354 +  };
   1.355 +
   1.356 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aData, aLength, aMimeType));
   1.357 +}
   1.358 +
   1.359 +void
   1.360 +DOMCameraControlListener::OnError(CameraErrorContext aContext, CameraError aError)
   1.361 +{
   1.362 +  class Callback : public DOMCallback
   1.363 +  {
   1.364 +  public:
   1.365 +    Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
   1.366 +             CameraErrorContext aContext,
   1.367 +             CameraError aError)
   1.368 +      : DOMCallback(aDOMCameraControl)
   1.369 +      , mContext(aContext)
   1.370 +      , mError(aError)
   1.371 +    { }
   1.372 +
   1.373 +    virtual void
   1.374 +    RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
   1.375 +    {
   1.376 +      nsString error;
   1.377 +
   1.378 +      switch (mError) {
   1.379 +        case kErrorServiceFailed:
   1.380 +          error = NS_LITERAL_STRING("ErrorServiceFailed");
   1.381 +          break;
   1.382 +
   1.383 +        case kErrorSetPictureSizeFailed:
   1.384 +          error = NS_LITERAL_STRING("ErrorSetPictureSizeFailed");
   1.385 +          break;
   1.386 +
   1.387 +        case kErrorSetThumbnailSizeFailed:
   1.388 +          error = NS_LITERAL_STRING("ErrorSetThumbnailSizeFailed");
   1.389 +          break;
   1.390 +
   1.391 +        case kErrorApiFailed:
   1.392 +          // XXXmikeh legacy error placeholder
   1.393 +          error = NS_LITERAL_STRING("FAILURE");
   1.394 +          break;
   1.395 +
   1.396 +        default:
   1.397 +          error = NS_LITERAL_STRING("ErrorUnknown");
   1.398 +          break;
   1.399 +      }
   1.400 +      aDOMCameraControl->OnError(mContext, error);
   1.401 +    }
   1.402 +
   1.403 +  protected:
   1.404 +    CameraErrorContext mContext;
   1.405 +    CameraError mError;
   1.406 +  };
   1.407 +
   1.408 +  NS_DispatchToMainThread(new Callback(mDOMCameraControl, aContext, aError));
   1.409 +}

mercurial