dom/camera/GonkCameraParameters.h
author Chris H-C <chutten@mozilla.com>
Mon, 04 Jul 2016 11:16:05 -0400
changeset 312997 df28918fe2361f0b54ca9ce4773a29c4c0675d06
parent 274642 58c11f8db0b1e70cdc941c79ddf216e6436a8afe
permissions -rw-r--r--
bug 1218576 - Support remote accumulation via JS histograms. r=gfritzsche The JS histograms, too, need to dispatch their accumulations from child to parent. JSHistograms_Add now only supports histograms that are in gHistogramsMap or that were created in the parent process. After bug 1288745, maybe we'll be able to change this to be less convoluted. MozReview-Commit-ID: 3qTH89YKbGP

/*
 * Copyright (C) 2013-2015 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef DOM_CAMERA_GONKCAMERAPARAMETERS_H
#define DOM_CAMERA_GONKCAMERAPARAMETERS_H

#include <math.h>
#include "nsTArray.h"
#include "nsString.h"
#include "mozilla/Mutex.h"
#include "nsClassHashtable.h"
#include "ICameraControl.h"

#ifdef MOZ_WIDGET_GONK
#include <camera/CameraParameters.h>
#else
#include "FallbackCameraPlatform.h"
#endif

namespace mozilla {

class GonkCameraParameters
{
public:
  GonkCameraParameters();
  virtual ~GonkCameraParameters();

  // IMPORTANT: This class is read and written by multiple threads --
  // ALL public methods must hold mLock, for either reading or writing,
  // for the life of their operation. Not doing so was the cause of
  // bug 928856, which was -painful- to track down.
  //
  // Return values:
  //  - see return values for GetTranslated() and SetTranslated() below.
  template<class T> nsresult
  Set(uint32_t aKey, const T& aValue)
  {
    MutexAutoLock lock(mLock);
    nsresult rv = SetTranslated(aKey, aValue);
    mDirty = mDirty || NS_SUCCEEDED(rv);
    return rv;
  }

  template<class T> nsresult
  Get(uint32_t aKey, T& aValue)
  {
    MutexAutoLock lock(mLock);
    return GetTranslated(aKey, aValue);
  }

  bool
  TestAndClearDirtyFlag()
  {
    bool dirty;

    MutexAutoLock lock(mLock);
    dirty = mDirty;
    mDirty = false;
    return dirty;
  }

  android::String8 Flatten() const;
  nsresult Unflatten(const android::String8& aFlatParameters);

protected:
  mutable Mutex mLock;
  bool mDirty;
  bool mInitialized;

  // Required internal properties
  double mExposureCompensationStep;
  int32_t mExposureCompensationMinIndex;
  int32_t mExposureCompensationMaxIndex;
  const char* mVendorSpecificKeyIsoMode;
  const char* mVendorSpecificKeySupportedIsoModes;
  nsTArray<int> mZoomRatios;
  nsTArray<nsString> mIsoModes;
  nsTArray<nsString> mSceneModes;
  nsTArray<nsString> mMeteringModes;
  nsClassHashtable<nsStringHashKey, nsCString> mIsoModeMap;
  nsClassHashtable<nsCStringHashKey, nsCString> mParams;

  nsresult SetImpl(const char* aKey, const char* aValue)
  {
    if (!aValue || strchr(aValue, ';') || strchr(aValue, '=')) {
      return NS_ERROR_ILLEGAL_VALUE;
    }
    nsDependentCString key(aKey);
    mParams.Put(key, new nsCString(aValue));
    return NS_OK;
  }

  nsresult SetImpl(const char* aKey, int aValue)
  {
    nsDependentCString key(aKey);
    nsCString* value = new nsCString();
    value->AppendInt(aValue);
    mParams.Put(key, value);
    return NS_OK;
  }

  nsresult SetImpl(const char* aKey, double aValue)
  {
    nsDependentCString key(aKey);
    nsCString* value = new nsCString();
    value->AppendFloat(aValue);
    mParams.Put(key, value);
    return NS_OK;
  }

  nsresult SetImpl(const char* aKey, float aValue)
  {
    nsDependentCString key(aKey);
    nsCString* value = new nsCString();
    value->AppendFloat(aValue);
    mParams.Put(key, value);
    return NS_OK;
  }

  nsresult SetImpl(const char* aKey, bool aValue)
  {
    nsDependentCString key(aKey);
    mParams.Put(key, new nsCString(aValue ? "true" : "false"));
    return NS_OK;
  }

  nsresult GetImpl(const char* aKey, const char*& aRet)
  {
    nsDependentCString key(aKey);
    nsCString* value;
    if (!mParams.Get(key, &value)) {
      aRet = nullptr;
      return NS_ERROR_FAILURE;
    }
    aRet = value->Data();
    return NS_OK;
  }

  nsresult GetImpl(const char* aKey, float& aRet)
  {
    nsDependentCString key(aKey);
    nsCString* value;
    nsresult rv = NS_ERROR_FAILURE;
    if (mParams.Get(key, &value)) {
      aRet = value->ToFloat(&rv);
    } else {
      aRet = 0.0;
    }
    return rv;
  }

  nsresult GetImpl(const char* aKey, double& aRet)
  {
    nsDependentCString key(aKey);
    nsCString* value;
    nsresult rv = NS_ERROR_FAILURE;
    if (mParams.Get(key, &value)) {
      aRet = value->ToFloat(&rv);
    } else {
      aRet = 0.0;
    }
    return rv;
  }

  nsresult GetImpl(const char* aKey, int& aRet)
  {
    nsDependentCString key(aKey);
    nsCString* value;
    nsresult rv = NS_ERROR_FAILURE;
    if (mParams.Get(key, &value)) {
      aRet = value->ToInteger(&rv);
    } else {
      aRet = 0.0;
    }
    return rv;
  }

  nsresult GetImpl(const char* aKey, bool& aRet)
  {
    nsDependentCString key(aKey);
    nsCString* value;
    if (!mParams.Get(key, &value)) {
      aRet = false;
      return NS_ERROR_FAILURE;
    }
    aRet = value->EqualsLiteral("true");
    return NS_OK;
  }

  const char* GetTextKey(uint32_t aKey);
  const char* FindVendorSpecificKey(const char* aPotentialKeys[], size_t aPotentialKeyCount);

  // The *Impl() templates handle converting the parameter keys from
  // their enum values to string types, if necessary. These are the
  // bottom layer accessors to mParams.
  //
  // Return values:
  //  - NS_OK on success;
  //  - NS_ERROR_NOT_IMPLEMENTED if the numeric 'aKey' value is invalid.
  template<typename T> nsresult
  SetImpl(uint32_t aKey, const T& aValue)
  {
    const char* key = GetTextKey(aKey);
    NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED);
    return SetImpl(key, aValue);
  }

  template<typename T> nsresult
  GetImpl(uint32_t aKey, T& aValue)
  {
    const char* key = GetTextKey(aKey);
    NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED);
    return GetImpl(key, aValue);
  }

  nsresult
  ClearImpl(const char* aKey)
  {
    nsDependentCString key(aKey);
    mParams.Remove(key);
    return NS_OK;
  }

  // The *Translated() functions allow us to handle special cases;
  // for example, where the thumbnail size setting is exposed as an
  // ICameraControl::Size object, but is handled by the AOSP layer
  // as two separate parameters.
  //
  // Return values:
  //  - NS_OK on success;
  //  - NS_ERROR_INVALID_ARG if 'aValue' contains an invalid value;
  //  - NS_ERROR_NOT_IMPLEMENTED if 'aKey' is invalid;
  //  - NS_ERROR_NOT_AVAILABLE if the getter fails to retrieve a valid value,
  //      or if a setter fails because it requires one or more values that
  //      could not be retrieved;
  //  - NS_ERROR_FAILURE on unexpected internal failures.
  nsresult SetTranslated(uint32_t aKey, const nsAString& aValue);
  nsresult GetTranslated(uint32_t aKey, nsAString& aValue);
  nsresult SetTranslated(uint32_t aKey, const ICameraControl::Size& aSize);
  nsresult GetTranslated(uint32_t aKey, ICameraControl::Size& aSize);
  nsresult GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Size>& aSizes);
  nsresult SetTranslated(uint32_t aKey, const nsTArray<ICameraControl::Region>& aRegions);
  nsresult GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Region>& aRegions);
  nsresult SetTranslated(uint32_t aKey, const ICameraControl::Position& aPosition);
  nsresult SetTranslated(uint32_t aKey, const int64_t& aValue);
  nsresult GetTranslated(uint32_t aKey, int64_t& aValue);
  nsresult SetTranslated(uint32_t aKey, const double& aValue);
  nsresult GetTranslated(uint32_t aKey, double& aValue);
  nsresult SetTranslated(uint32_t aKey, const int& aValue);
  nsresult GetTranslated(uint32_t aKey, int& aValue);
  nsresult SetTranslated(uint32_t aKey, const uint32_t& aValue);
  nsresult GetTranslated(uint32_t aKey, uint32_t& aValue);
  nsresult SetTranslated(uint32_t aKey, const bool& aValue);
  nsresult GetTranslated(uint32_t aKey, bool& aValue);
  nsresult GetTranslated(uint32_t aKey, nsTArray<nsString>& aValues);
  nsresult GetTranslated(uint32_t aKey, nsTArray<double>& aValues);

  // Converts a string of multiple, comma-separated values into an array
  // of the appropriate type.
  //
  // Return values:
  //  - NS_OK on success;
  //  - NS_ERROR_NOT_IMPLEMENTED if 'aKey' is invalid;
  //  - NS_ERROR_NOT_AVAILABLE if a valid value could not be returned.
  template<class T> nsresult GetListAsArray(uint32_t aKey, nsTArray<T>& aArray);

  // Converts ISO values (e.g., "auto", "hjr", "100", "200", etc.) to and from
  // values understood by Gonk (e.g., "auto", "ISO_HJR", "ISO100", "ISO200",
  // respectively).
  //
  // Return values:
  //  - NS_OK on success;
  //  - NS_ERROR_INVALID_ARG if the 'aIso' argument is not a valid form.
  nsresult MapIsoToGonk(const nsAString& aIso, nsACString& aIsoOut);
  nsresult MapIsoFromGonk(const char* aIso, nsAString& aIsoOut);

  // Call once to initialize local cached values used in translating other
  // arguments between Gecko and Gonk. Always returns NS_OK.
  nsresult Initialize();

  // Returns true if we're a memory-constrained platform that requires
  // certain features to be disabled; returns false otherwise.
  static bool IsLowMemoryPlatform();
};

} // namespace mozilla

#endif // DOM_CAMERA_GONKCAMERAPARAMETERS_H