зеркало из https://github.com/mozilla/gecko-dev.git
Bug 779139 - Make DOM-facing camera objects cycle collection participants. r=jst
--HG-- rename : dom/camera/CameraControl.h => dom/camera/CameraControlImpl.h rename : dom/camera/GonkCameraCapabilities.cpp => dom/camera/DOMCameraCapabilities.cpp
This commit is contained in:
Родитель
9d666dfae5
Коммит
6ae700c29b
|
@ -529,8 +529,8 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
|
|||
#include "mozilla/dom/Activity.h"
|
||||
|
||||
#include "DOMCameraManager.h"
|
||||
#include "CameraControl.h"
|
||||
#include "CameraCapabilities.h"
|
||||
#include "DOMCameraControl.h"
|
||||
#include "DOMCameraCapabilities.h"
|
||||
|
||||
#include "DOMError.h"
|
||||
#include "DOMRequest.h"
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_CAMERA_NSCAMERACAPABILITIES_H
|
||||
#define DOM_CAMERA_NSCAMERACAPABILITIES_H
|
||||
|
||||
#include "CameraControl.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef nsresult (*ParseItemAndAddFunc)(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd);
|
||||
|
||||
class nsCameraCapabilities MOZ_FINAL : public nsICameraCapabilities
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICAMERACAPABILITIES
|
||||
|
||||
nsCameraCapabilities(nsCameraControl* aCamera);
|
||||
|
||||
nsresult ParameterListToNewArray(
|
||||
JSContext* cx,
|
||||
JSObject** aArray,
|
||||
uint32_t aKey,
|
||||
ParseItemAndAddFunc aParseItemAndAdd
|
||||
);
|
||||
nsresult StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
|
||||
nsresult DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
|
||||
|
||||
private:
|
||||
nsCameraCapabilities(const nsCameraCapabilities&) MOZ_DELETE;
|
||||
nsCameraCapabilities& operator=(const nsCameraCapabilities&) MOZ_DELETE;
|
||||
|
||||
protected:
|
||||
/* additional members */
|
||||
~nsCameraCapabilities();
|
||||
nsCOMPtr<nsCameraControl> mCamera;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_NSCAMERACAPABILITIES_H
|
|
@ -21,26 +21,80 @@
|
|||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMCameraManager.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#define DOM_CAMERA_LOG( l, ... ) \
|
||||
do { \
|
||||
if ( DOM_CAMERA_LOG_LEVEL >= (l) ) { \
|
||||
printf_stderr (__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gCameraLog;
|
||||
#define DOM_CAMERA_LOG( type, ... ) PR_LOG(gCameraLog, (PRLogModuleLevel)type, ( __VA_ARGS__ ))
|
||||
#else
|
||||
#define DOM_CAMERA_LOG( type, ... )
|
||||
#endif
|
||||
|
||||
#define DOM_CAMERA_LOGA( ... ) DOM_CAMERA_LOG( 0, __VA_ARGS__ )
|
||||
#define DOM_CAMERA_LOGA( ... ) DOM_CAMERA_LOG( 0, __VA_ARGS__ )
|
||||
|
||||
/**
|
||||
* From the least to the most output.
|
||||
*/
|
||||
enum {
|
||||
DOM_CAMERA_LOG_NOTHING,
|
||||
DOM_CAMERA_LOG_ERROR,
|
||||
DOM_CAMERA_LOG_WARNING,
|
||||
DOM_CAMERA_LOG_INFO
|
||||
DOM_CAMERA_LOG_INFO,
|
||||
DOM_CAMERA_LOG_TRACE,
|
||||
DOM_CAMERA_LOG_REFERENCES
|
||||
};
|
||||
|
||||
#define DOM_CAMERA_LOGI( ... ) DOM_CAMERA_LOG( DOM_CAMERA_LOG_INFO, __VA_ARGS__ )
|
||||
#define DOM_CAMERA_LOGW( ... ) DOM_CAMERA_LOG( DOM_CAMERA_LOG_WARNING, __VA_ARGS__ )
|
||||
#define DOM_CAMERA_LOGE( ... ) DOM_CAMERA_LOG( DOM_CAMERA_LOG_ERROR, __VA_ARGS__ )
|
||||
/**
|
||||
* DOM_CAMERA_LOGR() can be called before 'gCameraLog' is set, so
|
||||
* we need to handle this one a little differently.
|
||||
*/
|
||||
#ifdef PR_LOGGING
|
||||
#define DOM_CAMERA_LOGR( ... ) \
|
||||
do { \
|
||||
if (gCameraLog) { \
|
||||
DOM_CAMERA_LOG( DOM_CAMERA_LOG_REFERENCES, __VA_ARGS__ ); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define DOM_CAMERA_LOGR( ... )
|
||||
#endif
|
||||
#define DOM_CAMERA_LOGT( ... ) DOM_CAMERA_LOG( DOM_CAMERA_LOG_TRACE, __VA_ARGS__ )
|
||||
#define DOM_CAMERA_LOGI( ... ) DOM_CAMERA_LOG( DOM_CAMERA_LOG_INFO, __VA_ARGS__ )
|
||||
#define DOM_CAMERA_LOGW( ... ) DOM_CAMERA_LOG( DOM_CAMERA_LOG_WARNING, __VA_ARGS__ )
|
||||
#define DOM_CAMERA_LOGE( ... ) DOM_CAMERA_LOG( DOM_CAMERA_LOG_ERROR, __VA_ARGS__ )
|
||||
|
||||
enum {
|
||||
CAMERA_PARAM_EFFECT,
|
||||
CAMERA_PARAM_WHITEBALANCE,
|
||||
CAMERA_PARAM_SCENEMODE,
|
||||
CAMERA_PARAM_FLASHMODE,
|
||||
CAMERA_PARAM_FOCUSMODE,
|
||||
CAMERA_PARAM_ZOOM,
|
||||
CAMERA_PARAM_METERINGAREAS,
|
||||
CAMERA_PARAM_FOCUSAREAS,
|
||||
CAMERA_PARAM_FOCALLENGTH,
|
||||
CAMERA_PARAM_FOCUSDISTANCENEAR,
|
||||
CAMERA_PARAM_FOCUSDISTANCEOPTIMUM,
|
||||
CAMERA_PARAM_FOCUSDISTANCEFAR,
|
||||
CAMERA_PARAM_EXPOSURECOMPENSATION,
|
||||
|
||||
CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
|
||||
CAMERA_PARAM_SUPPORTED_VIDEOSIZES,
|
||||
CAMERA_PARAM_SUPPORTED_PICTURESIZES,
|
||||
CAMERA_PARAM_SUPPORTED_PICTUREFORMATS,
|
||||
CAMERA_PARAM_SUPPORTED_WHITEBALANCES,
|
||||
CAMERA_PARAM_SUPPORTED_SCENEMODES,
|
||||
CAMERA_PARAM_SUPPORTED_EFFECTS,
|
||||
CAMERA_PARAM_SUPPORTED_FLASHMODES,
|
||||
CAMERA_PARAM_SUPPORTED_FOCUSMODES,
|
||||
CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS,
|
||||
CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS,
|
||||
CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION,
|
||||
CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION,
|
||||
CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP,
|
||||
CAMERA_PARAM_SUPPORTED_ZOOM,
|
||||
CAMERA_PARAM_SUPPORTED_ZOOMRATIOS
|
||||
};
|
||||
|
||||
class CameraErrorResult : public nsRunnable
|
||||
{
|
||||
|
@ -65,4 +119,43 @@ protected:
|
|||
const nsString mErrorMsg;
|
||||
};
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
||||
static inline void nsLogAddRefCamera(const char *file, uint32_t line, void* p, uint32_t count, const char *clazz, uint32_t size)
|
||||
{
|
||||
if (count == 1) {
|
||||
DOM_CAMERA_LOGR("++++++++++++++++++++++++++++++++++++++++");
|
||||
}
|
||||
DOM_CAMERA_LOGR("%s:%d : CAMREF-ADD(%s): this=%p, mRefCnt=%d\n", file, line, clazz, p, count);
|
||||
}
|
||||
|
||||
static inline void nsLogReleaseCamera(const char *file, uint32_t line, void* p, uint32_t count, const char *clazz, bool abortOnDelete)
|
||||
{
|
||||
DOM_CAMERA_LOGR("%s:%d : CAMREF-REL(%s): this=%p, mRefCnt=%d\n", file, line, clazz, p, count);
|
||||
if (count == 0) {
|
||||
if (!abortOnDelete) {
|
||||
DOM_CAMERA_LOGR("----------------------------------------");
|
||||
} else {
|
||||
DOM_CAMERA_LOGR("---------- ABORTING ON DELETE ----------");
|
||||
*((uint32_t *)0xdeadbeef) = 0x266230;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NS_LOG_ADDREF
|
||||
#undef NS_LOG_ADDREF
|
||||
#endif
|
||||
#ifdef NS_LOG_RELEASE
|
||||
#undef NS_LOG_RELEASE
|
||||
#endif
|
||||
|
||||
#define NS_LOG_ADDREF( p, n, c, s ) nsLogAddRefCamera(__FILE__, __LINE__, (p), (n), (c), (s))
|
||||
#ifdef DOM_CAMERA_DEBUG_REFS_ABORT_ON_DELETE
|
||||
#define NS_LOG_RELEASE( p, n, c ) nsLogReleaseCamera(__FILE__, __LINE__, (p), (n), (c), DOM_CAMERA_DEBUG_REFS_ABORT_ON_DELETE)
|
||||
#else
|
||||
#define NS_LOG_RELEASE( p, n, c ) nsLogReleaseCamera(__FILE__, __LINE__, (p), (n), (c), false)
|
||||
#endif
|
||||
|
||||
#endif // PR_LOGGING
|
||||
|
||||
#endif // DOM_CAMERA_CAMERACOMMON_H
|
||||
|
|
|
@ -1,506 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsThread.h"
|
||||
#include "DOMCameraManager.h"
|
||||
#include "CameraControl.h"
|
||||
#include "CameraCapabilities.h"
|
||||
#include "CameraControl.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace dom;
|
||||
|
||||
DOMCI_DATA(CameraControl, nsICameraControl)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsCameraControl)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICameraControl)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraControl)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsCameraControl)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsCameraControl)
|
||||
|
||||
// Helpers for string properties.
|
||||
nsresult
|
||||
nsCameraControl::SetHelper(uint32_t aKey, const nsAString& aValue)
|
||||
{
|
||||
SetParameter(aKey, NS_ConvertUTF16toUTF8(aValue).get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCameraControl::GetHelper(uint32_t aKey, nsAString& aValue)
|
||||
{
|
||||
const char* value = GetParameterConstChar(aKey);
|
||||
if (!value) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aValue.AssignASCII(value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Helpers for doubles.
|
||||
nsresult
|
||||
nsCameraControl::SetHelper(uint32_t aKey, double aValue)
|
||||
{
|
||||
SetParameter(aKey, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCameraControl::GetHelper(uint32_t aKey, double* aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue);
|
||||
*aValue = GetParameterDouble(aKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Helper for weighted regions.
|
||||
nsresult
|
||||
nsCameraControl::SetHelper(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit)
|
||||
{
|
||||
if (aLimit == 0) {
|
||||
DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!aValue.isObject()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint32_t length = 0;
|
||||
|
||||
JSObject* regions = &aValue.toObject();
|
||||
if (!JS_GetArrayLength(aCx, regions, &length)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit);
|
||||
if (length > aLimit) {
|
||||
length = aLimit;
|
||||
}
|
||||
|
||||
nsTArray<CameraRegion> regionArray;
|
||||
regionArray.SetCapacity(length);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
JS::Value v;
|
||||
|
||||
if (!JS_GetElement(aCx, regions, i, &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CameraRegion* r = regionArray.AppendElement();
|
||||
/**
|
||||
* These are the default values. We can remove these when the xpidl
|
||||
* dictionary parser gains the ability to grok default values.
|
||||
*/
|
||||
r->top = -1000;
|
||||
r->left = -1000;
|
||||
r->bottom = 1000;
|
||||
r->right = 1000;
|
||||
r->weight = 1000;
|
||||
|
||||
nsresult rv = r->Init(aCx, &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%d\n",
|
||||
i,
|
||||
r->top,
|
||||
r->left,
|
||||
r->bottom,
|
||||
r->right,
|
||||
r->weight
|
||||
);
|
||||
}
|
||||
SetParameter(aKey, regionArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCameraControl::GetHelper(JSContext* aCx, uint32_t aKey, JS::Value* aValue)
|
||||
{
|
||||
nsTArray<CameraRegion> regionArray;
|
||||
|
||||
GetParameter(aKey, regionArray);
|
||||
|
||||
JSObject* array = JS_NewArrayObject(aCx, 0, nullptr);
|
||||
if (!array) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
uint32_t length = regionArray.Length();
|
||||
DOM_CAMERA_LOGI("%s:%d : got %d regions\n", __func__, __LINE__, length);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
CameraRegion* r = ®ionArray[i];
|
||||
JS::Value v;
|
||||
|
||||
JSObject* o = JS_NewObject(aCx, nullptr, nullptr, nullptr);
|
||||
if (!o) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("top=%d\n", r->top);
|
||||
v = INT_TO_JSVAL(r->top);
|
||||
if (!JS_SetProperty(aCx, o, "top", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("left=%d\n", r->left);
|
||||
v = INT_TO_JSVAL(r->left);
|
||||
if (!JS_SetProperty(aCx, o, "left", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("bottom=%d\n", r->bottom);
|
||||
v = INT_TO_JSVAL(r->bottom);
|
||||
if (!JS_SetProperty(aCx, o, "bottom", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("right=%d\n", r->right);
|
||||
v = INT_TO_JSVAL(r->right);
|
||||
if (!JS_SetProperty(aCx, o, "right", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("weight=%d\n", r->weight);
|
||||
v = INT_TO_JSVAL(r->weight);
|
||||
if (!JS_SetProperty(aCx, o, "weight", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
v = OBJECT_TO_JSVAL(o);
|
||||
if (!JS_SetElement(aCx, array, i, &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
*aValue = JS::ObjectValue(*array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsICameraCapabilities capabilities; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetCapabilities(nsICameraCapabilities** aCapabilities)
|
||||
{
|
||||
if (!mCapabilities) {
|
||||
mCapabilities = new nsCameraCapabilities(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICameraCapabilities> capabilities = mCapabilities;
|
||||
capabilities.forget(aCapabilities);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute DOMString effect; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetEffect(nsAString& aEffect)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_EFFECT, aEffect);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetEffect(const nsAString& aEffect)
|
||||
{
|
||||
return SetHelper(CAMERA_PARAM_EFFECT, aEffect);
|
||||
}
|
||||
|
||||
/* attribute DOMString whiteBalanceMode; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetWhiteBalanceMode(nsAString& aWhiteBalanceMode)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode)
|
||||
{
|
||||
return SetHelper(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString sceneMode; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetSceneMode(nsAString& aSceneMode)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetSceneMode(const nsAString& aSceneMode)
|
||||
{
|
||||
return SetHelper(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString flashMode; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetFlashMode(nsAString& aFlashMode)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetFlashMode(const nsAString& aFlashMode)
|
||||
{
|
||||
return SetHelper(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString focusMode; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetFocusMode(nsAString& aFocusMode)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetFocusMode(const nsAString& aFocusMode)
|
||||
{
|
||||
return SetHelper(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
}
|
||||
|
||||
/* attribute double zoom; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetZoom(double* aZoom)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_ZOOM, aZoom);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetZoom(double aZoom)
|
||||
{
|
||||
return SetHelper(CAMERA_PARAM_ZOOM, aZoom);
|
||||
}
|
||||
|
||||
/* attribute jsval meteringAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetMeteringAreas(JSContext* cx, JS::Value* aMeteringAreas)
|
||||
{
|
||||
return GetHelper(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetMeteringAreas(JSContext* cx, const JS::Value& aMeteringAreas)
|
||||
{
|
||||
return SetHelper(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas, mMaxMeteringAreas);
|
||||
}
|
||||
|
||||
/* attribute jsval focusAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetFocusAreas(JSContext* cx, JS::Value* aFocusAreas)
|
||||
{
|
||||
return GetHelper(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetFocusAreas(JSContext* cx, const JS::Value& aFocusAreas)
|
||||
{
|
||||
return SetHelper(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas, mMaxFocusAreas);
|
||||
}
|
||||
|
||||
/* readonly attribute double focalLength; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetFocalLength(double* aFocalLength)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_FOCALLENGTH, aFocalLength);
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceNear; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetFocusDistanceNear(double* aFocusDistanceNear)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_FOCUSDISTANCENEAR, aFocusDistanceNear);
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceOptimum; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetFocusDistanceOptimum(double* aFocusDistanceOptimum)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, aFocusDistanceOptimum);
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceFar; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetFocusDistanceFar(double* aFocusDistanceFar)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_FOCUSDISTANCEFAR, aFocusDistanceFar);
|
||||
}
|
||||
|
||||
/* void setExposureCompensation (const JS::Value& aCompensation, JSContext* cx); */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetExposureCompensation(const JS::Value& aCompensation, JSContext* cx)
|
||||
{
|
||||
if (aCompensation.isNullOrUndefined()) {
|
||||
// use NaN to switch the camera back into auto mode
|
||||
return SetHelper(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN);
|
||||
}
|
||||
|
||||
double compensation;
|
||||
if (!JS_ValueToNumber(cx, aCompensation, &compensation)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return SetHelper(CAMERA_PARAM_EXPOSURECOMPENSATION, compensation);
|
||||
}
|
||||
|
||||
/* readonly attribute double exposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetExposureCompensation(double* aExposureCompensation)
|
||||
{
|
||||
return GetHelper(CAMERA_PARAM_EXPOSURECOMPENSATION, aExposureCompensation);
|
||||
}
|
||||
|
||||
/* attribute nsICameraShutterCallback onShutter; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetOnShutter(nsICameraShutterCallback** aOnShutter)
|
||||
{
|
||||
*aOnShutter = mOnShutterCb;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter)
|
||||
{
|
||||
mOnShutterCb = aOnShutter;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void startRecording (in jsval aOptions, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::StartRecording(const JS::Value& aOptions, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
CameraSize size;
|
||||
nsresult rv = size.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> startRecordingTask = new StartRecordingTask(this, size, onSuccess, onError);
|
||||
mCameraThread->Dispatch(startRecordingTask, NS_DISPATCH_NORMAL);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
NS_WARNING("Could not get the Observer service for CameraControl::StartRecording.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
obs->NotifyObservers(nullptr,
|
||||
"recording-device-events",
|
||||
NS_LITERAL_STRING("starting").get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void stopRecording (); */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::StopRecording()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> stopRecordingTask = new StopRecordingTask(this);
|
||||
mCameraThread->Dispatch(stopRecordingTask, NS_DISPATCH_NORMAL);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
NS_WARNING("Could not get the Observer service for CameraControl::StopRecording.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
obs->NotifyObservers(nullptr,
|
||||
"recording-device-events",
|
||||
NS_LITERAL_STRING("shutdown").get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] void getPreviewStream (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::GetPreviewStream(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
CameraSize size;
|
||||
nsresult rv = size.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> getPreviewStreamTask = new GetPreviewStreamTask(this, size, onSuccess, onError);
|
||||
return NS_DispatchToMainThread(getPreviewStreamTask);
|
||||
}
|
||||
|
||||
/* void autoFocus (in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsCOMPtr<nsIRunnable> autoFocusTask = new AutoFocusTask(this, onSuccess, onError);
|
||||
mCameraThread->Dispatch(autoFocusTask, NS_DISPATCH_NORMAL);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void takePicture (in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP nsCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
CameraPictureOptions options;
|
||||
CameraSize size;
|
||||
CameraPosition pos;
|
||||
|
||||
nsresult rv = options.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = size.Init(cx, &options.pictureSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
/**
|
||||
* Default values, until the dictionary parser can handle them.
|
||||
* NaN indicates no value provided.
|
||||
*/
|
||||
pos.latitude = NAN;
|
||||
pos.longitude = NAN;
|
||||
pos.altitude = NAN;
|
||||
pos.timestamp = NAN;
|
||||
rv = pos.Init(cx, &options.position);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> takePictureTask = new TakePictureTask(this, size, options.rotation, options.fileFormat, pos, onSuccess, onError);
|
||||
mCameraThread->Dispatch(takePictureTask, NS_DISPATCH_NORMAL);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsCameraControl::AutoFocusComplete(bool aSuccess)
|
||||
{
|
||||
/**
|
||||
* Auto focusing can change some of the camera's parameters, so
|
||||
* we need to pull a new set before sending the result to the
|
||||
* main thread.
|
||||
*/
|
||||
PullParametersImpl(nullptr);
|
||||
|
||||
nsCOMPtr<nsIRunnable> autoFocusResult = new AutoFocusResult(aSuccess, mAutoFocusOnSuccessCb);
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(autoFocusResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to dispatch autoFocus() onSuccess callback to main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCameraControl::TakePictureComplete(uint8_t* aData, uint32_t aLength)
|
||||
{
|
||||
uint8_t* data = new uint8_t[aLength];
|
||||
|
||||
memcpy(data, aData, aLength);
|
||||
|
||||
/**
|
||||
* TODO: pick up the actual specified picture format for the MIME type;
|
||||
* for now, assume we'll be using JPEGs.
|
||||
*/
|
||||
nsIDOMBlob* blob = new nsDOMMemoryFile(static_cast<void*>(data), static_cast<uint64_t>(aLength), NS_LITERAL_STRING("image/jpeg"));
|
||||
nsCOMPtr<nsIRunnable> takePictureResult = new TakePictureResult(blob, mTakePictureOnSuccessCb);
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(takePictureResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to dispatch takePicture() onSuccess callback to main thread!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "DOMCameraPreview.h"
|
||||
#include "CameraControlImpl.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// Helpers for string properties.
|
||||
nsresult
|
||||
CameraControlImpl::Set(uint32_t aKey, const nsAString& aValue)
|
||||
{
|
||||
SetParameter(aKey, NS_ConvertUTF16toUTF8(aValue).get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::Get(uint32_t aKey, nsAString& aValue)
|
||||
{
|
||||
const char* value = GetParameterConstChar(aKey);
|
||||
if (!value) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aValue.AssignASCII(value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Helpers for doubles.
|
||||
nsresult
|
||||
CameraControlImpl::Set(uint32_t aKey, double aValue)
|
||||
{
|
||||
SetParameter(aKey, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::Get(uint32_t aKey, double* aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue);
|
||||
*aValue = GetParameterDouble(aKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Helper for weighted regions.
|
||||
nsresult
|
||||
CameraControlImpl::Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit)
|
||||
{
|
||||
if (aLimit == 0) {
|
||||
DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!aValue.isObject()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint32_t length = 0;
|
||||
|
||||
JSObject* regions = &aValue.toObject();
|
||||
if (!JS_GetArrayLength(aCx, regions, &length)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit);
|
||||
if (length > aLimit) {
|
||||
length = aLimit;
|
||||
}
|
||||
|
||||
nsTArray<CameraRegion> regionArray;
|
||||
regionArray.SetCapacity(length);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
JS::Value v;
|
||||
|
||||
if (!JS_GetElement(aCx, regions, i, &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CameraRegion* r = regionArray.AppendElement();
|
||||
/**
|
||||
* These are the default values. We can remove these when the xpidl
|
||||
* dictionary parser gains the ability to grok default values.
|
||||
*/
|
||||
r->top = -1000;
|
||||
r->left = -1000;
|
||||
r->bottom = 1000;
|
||||
r->right = 1000;
|
||||
r->weight = 1000;
|
||||
|
||||
nsresult rv = r->Init(aCx, &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%d\n",
|
||||
i,
|
||||
r->top,
|
||||
r->left,
|
||||
r->bottom,
|
||||
r->right,
|
||||
r->weight
|
||||
);
|
||||
}
|
||||
SetParameter(aKey, regionArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::Get(JSContext* aCx, uint32_t aKey, JS::Value* aValue)
|
||||
{
|
||||
nsTArray<CameraRegion> regionArray;
|
||||
|
||||
GetParameter(aKey, regionArray);
|
||||
|
||||
JSObject* array = JS_NewArrayObject(aCx, 0, nullptr);
|
||||
if (!array) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
uint32_t length = regionArray.Length();
|
||||
DOM_CAMERA_LOGI("%s:%d : got %d regions\n", __func__, __LINE__, length);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
CameraRegion* r = ®ionArray[i];
|
||||
JS::Value v;
|
||||
|
||||
JSObject* o = JS_NewObject(aCx, nullptr, nullptr, nullptr);
|
||||
if (!o) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("top=%d\n", r->top);
|
||||
v = INT_TO_JSVAL(r->top);
|
||||
if (!JS_SetProperty(aCx, o, "top", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("left=%d\n", r->left);
|
||||
v = INT_TO_JSVAL(r->left);
|
||||
if (!JS_SetProperty(aCx, o, "left", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("bottom=%d\n", r->bottom);
|
||||
v = INT_TO_JSVAL(r->bottom);
|
||||
if (!JS_SetProperty(aCx, o, "bottom", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("right=%d\n", r->right);
|
||||
v = INT_TO_JSVAL(r->right);
|
||||
if (!JS_SetProperty(aCx, o, "right", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
DOM_CAMERA_LOGI("weight=%d\n", r->weight);
|
||||
v = INT_TO_JSVAL(r->weight);
|
||||
if (!JS_SetProperty(aCx, o, "weight", &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
v = OBJECT_TO_JSVAL(o);
|
||||
if (!JS_SetElement(aCx, array, i, &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
*aValue = JS::ObjectValue(*array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::GetPreviewStream(CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
/**
|
||||
* The camera preview stream object is DOM-facing, and as such
|
||||
* must be a cycle-collection participant created on the main
|
||||
* thread.
|
||||
*/
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIRunnable> getPreviewStreamTask = new GetPreviewStreamTask(this, aSize, onSuccess, onError);
|
||||
return NS_DispatchToCurrentThread(getPreviewStreamTask);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> autoFocusTask = new AutoFocusTask(this, onSuccess, onError);
|
||||
return mCameraThread->Dispatch(autoFocusTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> takePictureTask = new TakePictureTask(this, aSize, aRotation, aFileFormat, aPosition, onSuccess, onError);
|
||||
return mCameraThread->Dispatch(takePictureTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::StartRecording(CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> startRecordingTask = new StartRecordingTask(this, aSize, onSuccess, onError);
|
||||
return mCameraThread->Dispatch(startRecordingTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::StopRecording()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> stopRecordingTask = new StopRecordingTask(this);
|
||||
return mCameraThread->Dispatch(stopRecordingTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::StartPreview(DOMCameraPreview* aDOMPreview)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> startPreviewTask = new StartPreviewTask(this, aDOMPreview);
|
||||
return mCameraThread->Dispatch(startPreviewTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
CameraControlImpl::StopPreview()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> stopPreviewTask = new StopPreviewTask(this);
|
||||
mCameraThread->Dispatch(stopPreviewTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
CameraControlImpl::ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder)
|
||||
{
|
||||
if (mDOMPreview) {
|
||||
mDOMPreview->ReceiveFrame(aBuffer, aFormat, aBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetPreviewStreamResult::Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mOnSuccessCb) {
|
||||
nsCOMPtr<nsIDOMMediaStream> stream = new DOMCameraPreview(mCameraControl, mWidth, mHeight, mFramesPerSecond);
|
||||
mOnSuccessCb->HandleEvent(stream);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
|
@ -2,18 +2,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_CAMERA_NSCAMERACONTROL_H
|
||||
#define DOM_CAMERA_NSCAMERACONTROL_H
|
||||
#ifndef DOM_CAMERA_CAMERACONTROLIMPL_H
|
||||
#define DOM_CAMERA_CAMERACONTROLIMPL_H
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsThread.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "CameraPreview.h"
|
||||
#include "nsIDOMCameraManager.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "ICameraControl.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -21,64 +17,73 @@ namespace mozilla {
|
|||
using namespace dom;
|
||||
|
||||
class GetPreviewStreamTask;
|
||||
class StartPreviewTask;
|
||||
class StopPreviewTask;
|
||||
class AutoFocusTask;
|
||||
class TakePictureTask;
|
||||
class StartRecordingTask;
|
||||
class StopRecordingTask;
|
||||
class SetParameterTask;
|
||||
class GetParameterTask;
|
||||
class PushParametersTask;
|
||||
class PullParametersTask;
|
||||
|
||||
// Main camera control.
|
||||
class nsCameraControl : public nsICameraControl
|
||||
class DOMCameraPreview;
|
||||
|
||||
class CameraControlImpl : public ICameraControl
|
||||
{
|
||||
friend class GetPreviewStreamTask;
|
||||
friend class StartPreviewTask;
|
||||
friend class StopPreviewTask;
|
||||
friend class AutoFocusTask;
|
||||
friend class TakePictureTask;
|
||||
friend class StartRecordingTask;
|
||||
friend class StopRecordingTask;
|
||||
friend class SetParameterTask;
|
||||
friend class GetParameterTask;
|
||||
friend class PushParametersTask;
|
||||
friend class PullParametersTask;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICAMERACONTROL
|
||||
CameraControlImpl(uint32_t aCameraId, nsIThread* aCameraThread)
|
||||
: mCameraId(aCameraId)
|
||||
, mCameraThread(aCameraThread)
|
||||
, mFileFormat()
|
||||
, mMaxMeteringAreas(0)
|
||||
, mMaxFocusAreas(0)
|
||||
, mDOMPreview(nullptr)
|
||||
, mAutoFocusOnSuccessCb(nullptr)
|
||||
, mAutoFocusOnErrorCb(nullptr)
|
||||
, mTakePictureOnSuccessCb(nullptr)
|
||||
, mTakePictureOnErrorCb(nullptr)
|
||||
, mStartRecordingOnSuccessCb(nullptr)
|
||||
, mStartRecordingOnErrorCb(nullptr)
|
||||
, mOnShutterCb(nullptr)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
enum {
|
||||
CAMERA_PARAM_EFFECT,
|
||||
CAMERA_PARAM_WHITEBALANCE,
|
||||
CAMERA_PARAM_SCENEMODE,
|
||||
CAMERA_PARAM_FLASHMODE,
|
||||
CAMERA_PARAM_FOCUSMODE,
|
||||
CAMERA_PARAM_ZOOM,
|
||||
CAMERA_PARAM_METERINGAREAS,
|
||||
CAMERA_PARAM_FOCUSAREAS,
|
||||
CAMERA_PARAM_FOCALLENGTH,
|
||||
CAMERA_PARAM_FOCUSDISTANCENEAR,
|
||||
CAMERA_PARAM_FOCUSDISTANCEOPTIMUM,
|
||||
CAMERA_PARAM_FOCUSDISTANCEFAR,
|
||||
CAMERA_PARAM_EXPOSURECOMPENSATION,
|
||||
nsresult GetPreviewStream(CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult StartPreview(DOMCameraPreview* aDOMPreview);
|
||||
void StopPreview();
|
||||
nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult StartRecording(CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult StopRecording();
|
||||
|
||||
nsresult Set(uint32_t aKey, const nsAString& aValue);
|
||||
nsresult Get(uint32_t aKey, nsAString& aValue);
|
||||
nsresult Set(uint32_t aKey, double aValue);
|
||||
nsresult Get(uint32_t aKey, double* aValue);
|
||||
nsresult Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit);
|
||||
nsresult Get(JSContext* aCx, uint32_t aKey, JS::Value* aValue);
|
||||
|
||||
nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue)
|
||||
{
|
||||
return Set(aCx, CAMERA_PARAM_FOCUSAREAS, aValue, mMaxFocusAreas);
|
||||
}
|
||||
|
||||
nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue)
|
||||
{
|
||||
return Set(aCx, CAMERA_PARAM_METERINGAREAS, aValue, mMaxMeteringAreas);
|
||||
}
|
||||
|
||||
CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
|
||||
CAMERA_PARAM_SUPPORTED_VIDEOSIZES,
|
||||
CAMERA_PARAM_SUPPORTED_PICTURESIZES,
|
||||
CAMERA_PARAM_SUPPORTED_PICTUREFORMATS,
|
||||
CAMERA_PARAM_SUPPORTED_WHITEBALANCES,
|
||||
CAMERA_PARAM_SUPPORTED_SCENEMODES,
|
||||
CAMERA_PARAM_SUPPORTED_EFFECTS,
|
||||
CAMERA_PARAM_SUPPORTED_FLASHMODES,
|
||||
CAMERA_PARAM_SUPPORTED_FOCUSMODES,
|
||||
CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS,
|
||||
CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS,
|
||||
CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION,
|
||||
CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION,
|
||||
CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP,
|
||||
CAMERA_PARAM_SUPPORTED_ZOOM,
|
||||
CAMERA_PARAM_SUPPORTED_ZOOMRATIOS
|
||||
};
|
||||
virtual const char* GetParameter(const char* aKey) = 0;
|
||||
virtual const char* GetParameterConstChar(uint32_t aKey) = 0;
|
||||
virtual double GetParameterDouble(uint32_t aKey) = 0;
|
||||
|
@ -87,61 +92,41 @@ public:
|
|||
virtual void SetParameter(uint32_t aKey, const char* aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, double aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, const nsTArray<CameraRegion>& aRegions) = 0;
|
||||
virtual void PushParameters() = 0;
|
||||
virtual nsresult PushParameters() = 0;
|
||||
|
||||
nsCameraControl(uint32_t aCameraId, nsIThread* aCameraThread)
|
||||
: mCameraId(aCameraId)
|
||||
, mCameraThread(aCameraThread)
|
||||
, mCapabilities(nullptr)
|
||||
, mPreview(nullptr)
|
||||
, mFileFormat()
|
||||
, mMaxMeteringAreas(0)
|
||||
, mMaxFocusAreas(0)
|
||||
, mAutoFocusOnSuccessCb(nullptr)
|
||||
, mAutoFocusOnErrorCb(nullptr)
|
||||
, mTakePictureOnSuccessCb(nullptr)
|
||||
, mTakePictureOnErrorCb(nullptr)
|
||||
, mStartRecordingOnSuccessCb(nullptr)
|
||||
, mStartRecordingOnErrorCb(nullptr)
|
||||
, mOnShutterCb(nullptr)
|
||||
{ }
|
||||
|
||||
void TakePictureComplete(uint8_t *aData, uint32_t aLength);
|
||||
void AutoFocusComplete(bool aSuccess);
|
||||
void ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
|
||||
|
||||
protected:
|
||||
virtual ~nsCameraControl() { }
|
||||
|
||||
nsresult SetHelper(uint32_t aKey, const nsAString& aValue);
|
||||
nsresult GetHelper(uint32_t aKey, nsAString& aValue);
|
||||
nsresult SetHelper(uint32_t aKey, double aValue);
|
||||
nsresult GetHelper(uint32_t aKey, double* aValue);
|
||||
nsresult SetHelper(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit);
|
||||
nsresult GetHelper(JSContext* aCx, uint32_t aKey, JS::Value* aValue);
|
||||
virtual ~CameraControlImpl()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual nsresult GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream) = 0;
|
||||
virtual nsresult StartPreviewImpl(StartPreviewTask* aStartPreview) = 0;
|
||||
virtual nsresult StopPreviewImpl(StopPreviewTask* aStopPreview) = 0;
|
||||
virtual nsresult AutoFocusImpl(AutoFocusTask* aAutoFocus) = 0;
|
||||
virtual nsresult TakePictureImpl(TakePictureTask* aTakePicture) = 0;
|
||||
virtual nsresult StartRecordingImpl(StartRecordingTask* aStartRecording) = 0;
|
||||
virtual nsresult StopRecordingImpl(StopRecordingTask* aStopRecording) = 0;
|
||||
virtual nsresult PushParametersImpl(PushParametersTask* aPushParameters) = 0;
|
||||
virtual nsresult PullParametersImpl(PullParametersTask* aPullParameters) = 0;
|
||||
virtual nsresult PushParametersImpl() = 0;
|
||||
virtual nsresult PullParametersImpl() = 0;
|
||||
|
||||
private:
|
||||
nsCameraControl(const nsCameraControl&) MOZ_DELETE;
|
||||
nsCameraControl& operator=(const nsCameraControl&) MOZ_DELETE;
|
||||
uint32_t mCameraId;
|
||||
nsCOMPtr<nsIThread> mCameraThread;
|
||||
nsString mFileFormat;
|
||||
uint32_t mMaxMeteringAreas;
|
||||
uint32_t mMaxFocusAreas;
|
||||
|
||||
protected:
|
||||
/* additional members */
|
||||
uint32_t mCameraId;
|
||||
nsCOMPtr<nsIThread> mCameraThread;
|
||||
nsCOMPtr<nsICameraCapabilities> mCapabilities;
|
||||
uint32_t mPreviewWidth;
|
||||
uint32_t mPreviewHeight;
|
||||
nsCOMPtr<CameraPreview> mPreview;
|
||||
nsString mFileFormat;
|
||||
uint32_t mMaxMeteringAreas;
|
||||
uint32_t mMaxFocusAreas;
|
||||
/**
|
||||
* 'mDOMPreview' is a raw pointer to the object that will receive incoming
|
||||
* preview frames. This is guaranteed to be valid, or null.
|
||||
*
|
||||
* It is set by a call to StartPreview(), and set to null on StopPreview().
|
||||
* It is up to the caller to ensure that the object will not disappear
|
||||
* out from under this pointer--usually by calling NS_ADDREF().
|
||||
*/
|
||||
DOMCameraPreview* mDOMPreview;
|
||||
|
||||
nsCOMPtr<nsICameraAutoFocusCallback> mAutoFocusOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mAutoFocusOnErrorCb;
|
||||
|
@ -150,29 +135,39 @@ protected:
|
|||
nsCOMPtr<nsICameraStartRecordingCallback> mStartRecordingOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mStartRecordingOnErrorCb;
|
||||
nsCOMPtr<nsICameraShutterCallback> mOnShutterCb;
|
||||
|
||||
private:
|
||||
CameraControlImpl(const CameraControlImpl&) MOZ_DELETE;
|
||||
CameraControlImpl& operator=(const CameraControlImpl&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
// Return the resulting preview stream to JS. Runs on the main thread.
|
||||
class GetPreviewStreamResult : public nsRunnable
|
||||
{
|
||||
public:
|
||||
GetPreviewStreamResult(nsIDOMMediaStream* aStream, nsICameraPreviewStreamCallback* onSuccess)
|
||||
: mStream(aStream)
|
||||
GetPreviewStreamResult(CameraControlImpl* aCameraControl, uint32_t aWidth, uint32_t aHeight, uint32_t aFramesPerSecond, nsICameraPreviewStreamCallback* onSuccess)
|
||||
: mCameraControl(aCameraControl)
|
||||
, mWidth(aWidth)
|
||||
, mHeight(aHeight)
|
||||
, mFramesPerSecond(aFramesPerSecond)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mOnSuccessCb) {
|
||||
mOnSuccessCb->HandleEvent(mStream);
|
||||
}
|
||||
return NS_OK;
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~GetPreviewStreamResult()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
// Run() method is implementation specific.
|
||||
NS_IMETHOD Run();
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIDOMMediaStream> mStream;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mFramesPerSecond;
|
||||
nsCOMPtr<nsICameraPreviewStreamCallback> mOnSuccessCb;
|
||||
};
|
||||
|
||||
|
@ -180,12 +175,19 @@ protected:
|
|||
class GetPreviewStreamTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
GetPreviewStreamTask(nsCameraControl* aCameraControl, CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
GetPreviewStreamTask(CameraControlImpl* aCameraControl, CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mSize(aSize)
|
||||
, mCameraControl(aCameraControl)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
, mOnErrorCb(onError)
|
||||
{ }
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~GetPreviewStreamTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
|
@ -199,7 +201,7 @@ public:
|
|||
}
|
||||
|
||||
CameraSize mSize;
|
||||
nsCOMPtr<nsCameraControl> mCameraControl;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
nsCOMPtr<nsICameraPreviewStreamCallback> mOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
|
||||
};
|
||||
|
@ -213,6 +215,8 @@ public:
|
|||
, mOnSuccessCb(onSuccess)
|
||||
{ }
|
||||
|
||||
virtual ~AutoFocusResult() { }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -232,17 +236,24 @@ protected:
|
|||
class AutoFocusTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AutoFocusTask(nsCameraControl* aCameraControl, nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
AutoFocusTask(CameraControlImpl* aCameraControl, nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mCameraControl(aCameraControl)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
, mOnErrorCb(onError)
|
||||
{ }
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~AutoFocusTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->AutoFocusImpl(this);
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
if (NS_FAILED(rv) && mOnErrorCb) {
|
||||
rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE")));
|
||||
|
@ -251,7 +262,7 @@ public:
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsCameraControl> mCameraControl;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
nsCOMPtr<nsICameraAutoFocusCallback> mOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
|
||||
};
|
||||
|
@ -263,15 +274,24 @@ public:
|
|||
TakePictureResult(nsIDOMBlob* aImage, nsICameraTakePictureCallback* onSuccess)
|
||||
: mImage(aImage)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
{ }
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~TakePictureResult()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (mOnSuccessCb) {
|
||||
mOnSuccessCb->HandleEvent(mImage);
|
||||
}
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -284,7 +304,7 @@ protected:
|
|||
class TakePictureTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
TakePictureTask(nsCameraControl* aCameraControl, CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
TakePictureTask(CameraControlImpl* aCameraControl, CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mCameraControl(aCameraControl)
|
||||
, mSize(aSize)
|
||||
, mRotation(aRotation)
|
||||
|
@ -292,13 +312,20 @@ public:
|
|||
, mPosition(aPosition)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
, mOnErrorCb(onError)
|
||||
{ }
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~TakePictureTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->TakePictureImpl(this);
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
if (NS_FAILED(rv) && mOnErrorCb) {
|
||||
rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE")));
|
||||
|
@ -307,7 +334,7 @@ public:
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsCameraControl> mCameraControl;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
CameraSize mSize;
|
||||
int32_t mRotation;
|
||||
nsString mFileFormat;
|
||||
|
@ -325,6 +352,8 @@ public:
|
|||
, mOnSuccessCb(onSuccess)
|
||||
{ }
|
||||
|
||||
virtual ~StartRecordingResult() { }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -344,18 +373,25 @@ protected:
|
|||
class StartRecordingTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
StartRecordingTask(nsCameraControl* aCameraControl, CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
StartRecordingTask(CameraControlImpl* aCameraControl, CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mSize(aSize)
|
||||
, mCameraControl(aCameraControl)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
, mOnErrorCb(onError)
|
||||
{ }
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~StartRecordingTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->StartRecordingImpl(this);
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
if (NS_FAILED(rv) && mOnErrorCb) {
|
||||
rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE")));
|
||||
|
@ -365,7 +401,7 @@ public:
|
|||
}
|
||||
|
||||
CameraSize mSize;
|
||||
nsCOMPtr<nsCameraControl> mCameraControl;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
nsCOMPtr<nsICameraStartRecordingCallback> mOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
|
||||
};
|
||||
|
@ -374,65 +410,87 @@ public:
|
|||
class StopRecordingTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
StopRecordingTask(nsCameraControl* aCameraControl)
|
||||
StopRecordingTask(CameraControlImpl* aCameraControl)
|
||||
: mCameraControl(aCameraControl)
|
||||
{ }
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~StopRecordingTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->StopRecordingImpl(this);
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsCameraControl> mCameraControl;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
};
|
||||
|
||||
// Pushes all camera parameters to the camera.
|
||||
class PushParametersTask : public nsRunnable
|
||||
// Start the preview.
|
||||
class StartPreviewTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
PushParametersTask(nsCameraControl* aCameraControl)
|
||||
StartPreviewTask(CameraControlImpl* aCameraControl, DOMCameraPreview* aDOMPreview)
|
||||
: mCameraControl(aCameraControl)
|
||||
{ }
|
||||
, mDOMPreview(aDOMPreview)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~StartPreviewTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->PushParametersImpl(this);
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->StartPreviewImpl(this);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsCameraControl> mCameraControl;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
DOMCameraPreview* mDOMPreview; // DOMCameraPreview NS_ADDREFs itself for us
|
||||
};
|
||||
|
||||
// Get all camera parameters from the camera.
|
||||
class PullParametersTask : public nsRunnable
|
||||
// Stop the preview.
|
||||
class StopPreviewTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
PullParametersTask(nsCameraControl* aCameraControl)
|
||||
StopPreviewTask(CameraControlImpl* aCameraControl)
|
||||
: mCameraControl(aCameraControl)
|
||||
{ }
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~StopPreviewTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->PullParametersImpl(this);
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
mCameraControl->StopPreviewImpl(this);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsCameraControl> mCameraControl;
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_NSCAMERACONTROL_H
|
||||
#endif // DOM_CAMERA_CAMERACONTROLIMPL_H
|
|
@ -1,114 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CameraPreview.h"
|
||||
#include "Layers.h"
|
||||
#include "ImageContainer.h"
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(CameraPreview, CameraPreview)
|
||||
|
||||
class CameraPreviewListener : public MediaStreamListener
|
||||
{
|
||||
public:
|
||||
CameraPreviewListener(CameraPreview* aPreview) :
|
||||
mPreview(aPreview)
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
~CameraPreviewListener()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
void NotifyConsumptionChanged(MediaStreamGraph* aGraph, Consumption aConsuming)
|
||||
{
|
||||
const char* state;
|
||||
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
switch (aConsuming) {
|
||||
case NOT_CONSUMED:
|
||||
state = "not consuming";
|
||||
break;
|
||||
|
||||
case CONSUMED:
|
||||
state = "consuming";
|
||||
break;
|
||||
|
||||
default:
|
||||
state = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGA("camera viewfinder is %s\n", state);
|
||||
|
||||
switch (aConsuming) {
|
||||
case NOT_CONSUMED:
|
||||
mPreview->Stop();
|
||||
break;
|
||||
|
||||
case CONSUMED:
|
||||
mPreview->Start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<CameraPreview> mPreview;
|
||||
};
|
||||
|
||||
CameraPreview::CameraPreview(nsIThread* aCameraThread, uint32_t aWidth, uint32_t aHeight)
|
||||
: nsDOMMediaStream()
|
||||
, mWidth(aWidth)
|
||||
, mHeight(aHeight)
|
||||
, mFramesPerSecond(0)
|
||||
, mFrameCount(0)
|
||||
, mCameraThread(aCameraThread)
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : mWidth=%d, mHeight=%d : this=%p\n", __func__, __LINE__, mWidth, mHeight, this);
|
||||
|
||||
mImageContainer = LayerManager::CreateImageContainer();
|
||||
MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
|
||||
mStream = gm->CreateInputStream(this);
|
||||
mInput = GetStream()->AsSourceStream();
|
||||
mInput->AddListener(new CameraPreviewListener(this));
|
||||
}
|
||||
|
||||
void
|
||||
CameraPreview::SetFrameRate(uint32_t aFramesPerSecond)
|
||||
{
|
||||
mFramesPerSecond = aFramesPerSecond;
|
||||
mInput->AddTrack(TRACK_VIDEO, mFramesPerSecond, 0, new VideoSegment());
|
||||
mInput->AdvanceKnownTracksTime(MEDIA_TIME_MAX);
|
||||
}
|
||||
|
||||
void
|
||||
CameraPreview::Start()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> cameraPreviewControl = NS_NewRunnableMethod(this, &CameraPreview::StartImpl);
|
||||
nsresult rv = mCameraThread->Dispatch(cameraPreviewControl, NS_DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
DOM_CAMERA_LOGE("failed to start camera preview (%d)\n", rv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CameraPreview::Stop()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> cameraPreviewControl = NS_NewRunnableMethod(this, &CameraPreview::StopImpl);
|
||||
nsresult rv = mCameraThread->Dispatch(cameraPreviewControl, NS_DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
DOM_CAMERA_LOGE("failed to stop camera preview (%d)\n", rv);
|
||||
}
|
||||
}
|
||||
|
||||
CameraPreview::~CameraPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_CAMERA_CAMERAPREVIEW_H
|
||||
#define DOM_CAMERA_CAMERAPREVIEW_H
|
||||
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "StreamBuffer.h"
|
||||
#include "nsDOMMediaStream.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CameraPreview : public nsDOMMediaStream
|
||||
, public MediaStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
CameraPreview(nsIThread* aCameraThread, uint32_t aWidth, uint32_t aHeight);
|
||||
|
||||
void SetFrameRate(uint32_t aFramesPerSecond);
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetCurrentTime(double* aCurrentTime) {
|
||||
return nsDOMMediaStream::GetCurrentTime(aCurrentTime);
|
||||
}
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
virtual nsresult StartImpl() = 0;
|
||||
virtual nsresult StopImpl() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~CameraPreview();
|
||||
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mFramesPerSecond;
|
||||
SourceMediaStream* mInput;
|
||||
nsRefPtr<mozilla::layers::ImageContainer> mImageContainer;
|
||||
VideoSegment mVideoSegment;
|
||||
uint32_t mFrameCount;
|
||||
nsCOMPtr<nsIThread> mCameraThread;
|
||||
|
||||
enum { TRACK_VIDEO = 1 };
|
||||
|
||||
private:
|
||||
CameraPreview(const CameraPreview&) MOZ_DELETE;
|
||||
CameraPreview& operator=(const CameraPreview&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_CAMERAPREVIEW_H
|
|
@ -2,44 +2,29 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include "base/basictypes.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "jsapi.h"
|
||||
#include "camera/CameraParameters.h"
|
||||
#include "CameraControl.h"
|
||||
#include "CameraCapabilities.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "DOMCameraControl.h"
|
||||
#include "DOMCameraCapabilities.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace android;
|
||||
using namespace mozilla;
|
||||
|
||||
DOMCI_DATA(CameraCapabilities, nsICameraCapabilities)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsCameraCapabilities)
|
||||
NS_IMPL_CYCLE_COLLECTION_0(DOMCameraCapabilities)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMCameraCapabilities)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICameraCapabilities)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraCapabilities)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(nsCameraCapabilities)
|
||||
NS_IMPL_RELEASE(nsCameraCapabilities)
|
||||
|
||||
|
||||
nsCameraCapabilities::nsCameraCapabilities(nsCameraControl* aCamera)
|
||||
: mCamera(aCamera)
|
||||
{
|
||||
// member initializers and constructor code
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
nsCameraCapabilities::~nsCameraCapabilities()
|
||||
{
|
||||
// destructor code
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p, mCamera=%p\n", __func__, __LINE__, this, mCamera.get());
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMCameraCapabilities)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMCameraCapabilities)
|
||||
|
||||
static nsresult
|
||||
ParseZoomRatioItemAndAdd(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd)
|
||||
|
@ -49,8 +34,14 @@ ParseZoomRatioItemAndAdd(JSContext* aCx, JSObject* aArray, uint32_t aIndex, cons
|
|||
aEnd = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* The by-100 divisor is Gonk-specific. For now, assume other platforms
|
||||
* return actual fractoinal multipliers.
|
||||
*/
|
||||
double d = strtod(aStart, aEnd);
|
||||
#if MOZ_WIDGET_GONK
|
||||
d /= 100;
|
||||
#endif
|
||||
|
||||
jsval v = JS_NumberValue(d);
|
||||
|
||||
|
@ -117,7 +108,7 @@ ParseDimensionItemAndAdd(JSContext* aCx, JSObject* aArray, uint32_t aIndex, cons
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsCameraCapabilities::ParameterListToNewArray(JSContext* aCx, JSObject** aArray, uint32_t aKey, ParseItemAndAddFunc aParseItemAndAdd)
|
||||
DOMCameraCapabilities::ParameterListToNewArray(JSContext* aCx, JSObject** aArray, uint32_t aKey, ParseItemAndAddFunc aParseItemAndAdd)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
|
@ -139,7 +130,16 @@ nsCameraCapabilities::ParameterListToNewArray(JSContext* aCx, JSObject** aArray,
|
|||
char* q;
|
||||
|
||||
while (p) {
|
||||
q = strchr(p, ',');
|
||||
/**
|
||||
* In C's string.h, strchr() is declared as returning 'char*'; in C++'s
|
||||
* cstring, it is declared as returning 'const char*', _except_ in MSVC,
|
||||
* where the C version is declared to return const like the C++ version.
|
||||
*
|
||||
* Unfortunately, for both cases, strtod() and strtol() take a 'char**' as
|
||||
* the end-of-conversion pointer, so we need to cast away strchr()'s
|
||||
* const-ness here to make the MSVC build everything happy.
|
||||
*/
|
||||
q = const_cast<char*>(strchr(p, ','));
|
||||
if (q != p) { // skip consecutive delimiters, just in case
|
||||
rv = aParseItemAndAdd(aCx, *aArray, index, p, &q);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -155,7 +155,7 @@ nsCameraCapabilities::ParameterListToNewArray(JSContext* aCx, JSObject** aArray,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsCameraCapabilities::StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
|
||||
DOMCameraCapabilities::StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
|
||||
{
|
||||
JSObject* array;
|
||||
|
||||
|
@ -167,7 +167,7 @@ nsCameraCapabilities::StringListToNewObject(JSContext* aCx, JS::Value* aArray, u
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsCameraCapabilities::DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
|
||||
DOMCameraCapabilities::DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
|
||||
{
|
||||
JSObject* array;
|
||||
nsresult rv;
|
||||
|
@ -181,67 +181,67 @@ nsCameraCapabilities::DimensionListToNewObject(JSContext* aCx, JS::Value* aArray
|
|||
|
||||
/* readonly attribute jsval previewSizes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetPreviewSizes(JSContext* cx, JS::Value* aPreviewSizes)
|
||||
DOMCameraCapabilities::GetPreviewSizes(JSContext* cx, JS::Value* aPreviewSizes)
|
||||
{
|
||||
return DimensionListToNewObject(cx, aPreviewSizes, nsCameraControl::CAMERA_PARAM_SUPPORTED_PREVIEWSIZES);
|
||||
return DimensionListToNewObject(cx, aPreviewSizes, CAMERA_PARAM_SUPPORTED_PREVIEWSIZES);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval pictureSizes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
|
||||
DOMCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
|
||||
{
|
||||
return DimensionListToNewObject(cx, aPictureSizes, nsCameraControl::CAMERA_PARAM_SUPPORTED_PICTURESIZES);
|
||||
return DimensionListToNewObject(cx, aPictureSizes, CAMERA_PARAM_SUPPORTED_PICTURESIZES);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval fileFormats; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
|
||||
DOMCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
|
||||
{
|
||||
return StringListToNewObject(cx, aFileFormats, nsCameraControl::CAMERA_PARAM_SUPPORTED_PICTUREFORMATS);
|
||||
return StringListToNewObject(cx, aFileFormats, CAMERA_PARAM_SUPPORTED_PICTUREFORMATS);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval whiteBalanceModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetWhiteBalanceModes(JSContext* cx, JS::Value* aWhiteBalanceModes)
|
||||
DOMCameraCapabilities::GetWhiteBalanceModes(JSContext* cx, JS::Value* aWhiteBalanceModes)
|
||||
{
|
||||
return StringListToNewObject(cx, aWhiteBalanceModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_WHITEBALANCES);
|
||||
return StringListToNewObject(cx, aWhiteBalanceModes, CAMERA_PARAM_SUPPORTED_WHITEBALANCES);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval sceneModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetSceneModes(JSContext* cx, JS::Value* aSceneModes)
|
||||
DOMCameraCapabilities::GetSceneModes(JSContext* cx, JS::Value* aSceneModes)
|
||||
{
|
||||
return StringListToNewObject(cx, aSceneModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_SCENEMODES);
|
||||
return StringListToNewObject(cx, aSceneModes, CAMERA_PARAM_SUPPORTED_SCENEMODES);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval effects; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetEffects(JSContext* cx, JS::Value* aEffects)
|
||||
DOMCameraCapabilities::GetEffects(JSContext* cx, JS::Value* aEffects)
|
||||
{
|
||||
return StringListToNewObject(cx, aEffects, nsCameraControl::CAMERA_PARAM_SUPPORTED_EFFECTS);
|
||||
return StringListToNewObject(cx, aEffects, CAMERA_PARAM_SUPPORTED_EFFECTS);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval flashModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetFlashModes(JSContext* cx, JS::Value* aFlashModes)
|
||||
DOMCameraCapabilities::GetFlashModes(JSContext* cx, JS::Value* aFlashModes)
|
||||
{
|
||||
return StringListToNewObject(cx, aFlashModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_FLASHMODES);
|
||||
return StringListToNewObject(cx, aFlashModes, CAMERA_PARAM_SUPPORTED_FLASHMODES);
|
||||
}
|
||||
|
||||
/* readonly attribute jsval focusModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetFocusModes(JSContext* cx, JS::Value* aFocusModes)
|
||||
DOMCameraCapabilities::GetFocusModes(JSContext* cx, JS::Value* aFocusModes)
|
||||
{
|
||||
return StringListToNewObject(cx, aFocusModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_FOCUSMODES);
|
||||
return StringListToNewObject(cx, aFocusModes, CAMERA_PARAM_SUPPORTED_FOCUSMODES);
|
||||
}
|
||||
|
||||
/* readonly attribute long maxFocusAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
|
||||
DOMCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS);
|
||||
const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS);
|
||||
if (!value) {
|
||||
// in case we get nonsense data back
|
||||
*aMaxFocusAreas = 0;
|
||||
|
@ -254,11 +254,11 @@ nsCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
|
|||
|
||||
/* readonly attribute double minExposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExposureCompensation)
|
||||
DOMCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExposureCompensation)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION);
|
||||
const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION);
|
||||
if (!value) {
|
||||
// in case we get nonsense data back
|
||||
*aMinExposureCompensation = 0;
|
||||
|
@ -271,11 +271,11 @@ nsCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExpo
|
|||
|
||||
/* readonly attribute double maxExposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExposureCompensation)
|
||||
DOMCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExposureCompensation)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION);
|
||||
const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION);
|
||||
if (!value) {
|
||||
// in case we get nonsense data back
|
||||
*aMaxExposureCompensation = 0;
|
||||
|
@ -288,11 +288,11 @@ nsCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExpo
|
|||
|
||||
/* readonly attribute double stepExposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepExposureCompensation)
|
||||
DOMCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepExposureCompensation)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP);
|
||||
const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP);
|
||||
if (!value) {
|
||||
// in case we get nonsense data back
|
||||
*aStepExposureCompensation = 0;
|
||||
|
@ -305,11 +305,11 @@ nsCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepEx
|
|||
|
||||
/* readonly attribute long maxMeteringAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAreas)
|
||||
DOMCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAreas)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS);
|
||||
const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS);
|
||||
if (!value) {
|
||||
// in case we get nonsense data back
|
||||
*aMaxMeteringAreas = 0;
|
||||
|
@ -322,12 +322,12 @@ nsCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAr
|
|||
|
||||
/* readonly attribute jsval zoomRatios; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
|
||||
DOMCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_ZOOM);
|
||||
if (!value || strcmp(value, CameraParameters::TRUE) != 0) {
|
||||
const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_ZOOM);
|
||||
if (!value || strcmp(value, "true") != 0) {
|
||||
// if zoom is not supported, return a null object
|
||||
*aZoomRatios = JSVAL_NULL;
|
||||
return NS_OK;
|
||||
|
@ -335,7 +335,7 @@ nsCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
|
|||
|
||||
JSObject* array;
|
||||
|
||||
nsresult rv = ParameterListToNewArray(cx, &array, nsCameraControl::CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, ParseZoomRatioItemAndAdd);
|
||||
nsresult rv = ParameterListToNewArray(cx, &array, CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, ParseZoomRatioItemAndAdd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aZoomRatios = OBJECT_TO_JSVAL(array);
|
||||
|
@ -344,7 +344,7 @@ nsCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
|
|||
|
||||
/* readonly attribute jsval videoSizes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetVideoSizes(JSContext* cx, JS::Value* aVideoSizes)
|
||||
DOMCameraCapabilities::GetVideoSizes(JSContext* cx, JS::Value* aVideoSizes)
|
||||
{
|
||||
return DimensionListToNewObject(cx, aVideoSizes, nsCameraControl::CAMERA_PARAM_SUPPORTED_VIDEOSIZES);
|
||||
return DimensionListToNewObject(cx, aVideoSizes, CAMERA_PARAM_SUPPORTED_VIDEOSIZES);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_CAMERA_DOMCAMERACAPABILITIES_H
|
||||
#define DOM_CAMERA_DOMCAMERACAPABILITIES_H
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "ICameraControl.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef nsresult (*ParseItemAndAddFunc)(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd);
|
||||
|
||||
class DOMCameraCapabilities MOZ_FINAL : public nsICameraCapabilities
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(DOMCameraCapabilities)
|
||||
NS_DECL_NSICAMERACAPABILITIES
|
||||
|
||||
DOMCameraCapabilities(ICameraControl* aCamera)
|
||||
: mCamera(aCamera)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
nsresult ParameterListToNewArray(
|
||||
JSContext* cx,
|
||||
JSObject** aArray,
|
||||
uint32_t aKey,
|
||||
ParseItemAndAddFunc aParseItemAndAdd
|
||||
);
|
||||
nsresult StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
|
||||
nsresult DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
|
||||
|
||||
private:
|
||||
DOMCameraCapabilities(const DOMCameraCapabilities&) MOZ_DELETE;
|
||||
DOMCameraCapabilities& operator=(const DOMCameraCapabilities&) MOZ_DELETE;
|
||||
|
||||
protected:
|
||||
/* additional members */
|
||||
~DOMCameraCapabilities()
|
||||
{
|
||||
// destructor code
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p, mCamera=%p\n", __func__, __LINE__, this, mCamera.get());
|
||||
}
|
||||
|
||||
nsRefPtr<ICameraControl> mCamera;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_DOMCAMERACAPABILITIES_H
|
|
@ -0,0 +1,370 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsThread.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "DOMCameraManager.h"
|
||||
#include "DOMCameraCapabilities.h"
|
||||
#include "DOMCameraControl.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace dom;
|
||||
|
||||
DOMCI_DATA(CameraControl, nsICameraControl)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMCameraControl)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMCameraControl)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMCapabilities)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMCameraControl)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMCapabilities)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraControl)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICameraControl)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraControl)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCameraControl)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCameraControl)
|
||||
|
||||
nsDOMCameraControl::~nsDOMCameraControl()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
/* readonly attribute nsICameraCapabilities capabilities; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetCapabilities(nsICameraCapabilities** aCapabilities)
|
||||
{
|
||||
if (!mDOMCapabilities) {
|
||||
mDOMCapabilities = new DOMCameraCapabilities(mCameraControl);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICameraCapabilities> capabilities = mDOMCapabilities;
|
||||
capabilities.forget(aCapabilities);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute DOMString effect; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetEffect(nsAString& aEffect)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_EFFECT, aEffect);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetEffect(const nsAString& aEffect)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_EFFECT, aEffect);
|
||||
}
|
||||
|
||||
/* attribute DOMString whiteBalanceMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetWhiteBalanceMode(nsAString& aWhiteBalanceMode)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString sceneMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetSceneMode(nsAString& aSceneMode)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetSceneMode(const nsAString& aSceneMode)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_SCENEMODE, aSceneMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString flashMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFlashMode(nsAString& aFlashMode)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetFlashMode(const nsAString& aFlashMode)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_FLASHMODE, aFlashMode);
|
||||
}
|
||||
|
||||
/* attribute DOMString focusMode; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusMode(nsAString& aFocusMode)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetFocusMode(const nsAString& aFocusMode)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, aFocusMode);
|
||||
}
|
||||
|
||||
/* attribute double zoom; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetZoom(double* aZoom)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_ZOOM, aZoom);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetZoom(double aZoom)
|
||||
{
|
||||
return mCameraControl->Set(CAMERA_PARAM_ZOOM, aZoom);
|
||||
}
|
||||
|
||||
/* attribute jsval meteringAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetMeteringAreas(JSContext* cx, JS::Value* aMeteringAreas)
|
||||
{
|
||||
return mCameraControl->Get(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetMeteringAreas(JSContext* cx, const JS::Value& aMeteringAreas)
|
||||
{
|
||||
return mCameraControl->SetMeteringAreas(cx, aMeteringAreas);
|
||||
}
|
||||
|
||||
/* attribute jsval focusAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusAreas(JSContext* cx, JS::Value* aFocusAreas)
|
||||
{
|
||||
return mCameraControl->Get(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetFocusAreas(JSContext* cx, const JS::Value& aFocusAreas)
|
||||
{
|
||||
return mCameraControl->SetFocusAreas(cx, aFocusAreas);
|
||||
}
|
||||
|
||||
/* readonly attribute double focalLength; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocalLength(double* aFocalLength)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCALLENGTH, aFocalLength);
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceNear; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusDistanceNear(double* aFocusDistanceNear)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCENEAR, aFocusDistanceNear);
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceOptimum; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusDistanceOptimum(double* aFocusDistanceOptimum)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, aFocusDistanceOptimum);
|
||||
}
|
||||
|
||||
/* readonly attribute double focusDistanceFar; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetFocusDistanceFar(double* aFocusDistanceFar)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEFAR, aFocusDistanceFar);
|
||||
}
|
||||
|
||||
/* void setExposureCompensation (const JS::Value& aCompensation, JSContext* cx); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetExposureCompensation(const JS::Value& aCompensation, JSContext* cx)
|
||||
{
|
||||
if (aCompensation.isNullOrUndefined()) {
|
||||
// use NaN to switch the camera back into auto mode
|
||||
return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN);
|
||||
}
|
||||
|
||||
double compensation;
|
||||
if (!JS_ValueToNumber(cx, aCompensation, &compensation)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, compensation);
|
||||
}
|
||||
|
||||
/* readonly attribute double exposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetExposureCompensation(double* aExposureCompensation)
|
||||
{
|
||||
return mCameraControl->Get(CAMERA_PARAM_EXPOSURECOMPENSATION, aExposureCompensation);
|
||||
}
|
||||
|
||||
/* attribute nsICameraShutterCallback onShutter; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetOnShutter(nsICameraShutterCallback** aOnShutter)
|
||||
{
|
||||
// TODO: see bug 779138.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter)
|
||||
{
|
||||
// TODO: see bug 779138.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* void startRecording (in jsval aOptions, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
CameraSize size;
|
||||
nsresult rv = size.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
NS_WARNING("Could not get the Observer service for CameraControl::StartRecording.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
obs->NotifyObservers(nullptr,
|
||||
"recording-device-events",
|
||||
NS_LITERAL_STRING("starting").get());
|
||||
|
||||
return mCameraControl->StartRecording(size, onSuccess, onError);
|
||||
}
|
||||
|
||||
/* void stopRecording (); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::StopRecording()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
NS_WARNING("Could not get the Observer service for CameraControl::StopRecording.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
obs->NotifyObservers(nullptr,
|
||||
"recording-device-events",
|
||||
NS_LITERAL_STRING("shutdown").get());
|
||||
|
||||
return mCameraControl->StopRecording();
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] void getPreviewStream (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::GetPreviewStream(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
CameraSize size;
|
||||
nsresult rv = size.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mCameraControl->GetPreviewStream(size, onSuccess, onError);
|
||||
}
|
||||
|
||||
/* void resumePreview(); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::ResumePreview()
|
||||
{
|
||||
return mCameraControl->StartPreview(nullptr);
|
||||
}
|
||||
|
||||
/* void autoFocus (in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
return mCameraControl->AutoFocus(onSuccess, onError);
|
||||
}
|
||||
|
||||
/* void takePicture (in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
|
||||
|
||||
CameraPictureOptions options;
|
||||
CameraSize size;
|
||||
CameraPosition pos;
|
||||
|
||||
nsresult rv = options.Init(cx, &aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = size.Init(cx, &options.pictureSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
/**
|
||||
* Default values, until the dictionary parser can handle them.
|
||||
* NaN indicates no value provided.
|
||||
*/
|
||||
pos.latitude = NAN;
|
||||
pos.longitude = NAN;
|
||||
pos.altitude = NAN;
|
||||
pos.timestamp = NAN;
|
||||
rv = pos.Init(cx, &options.position);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mCameraControl->TakePicture(size, options.rotation, options.fileFormat, pos, onSuccess, onError);
|
||||
}
|
||||
|
||||
class GetCameraResult : public nsRunnable
|
||||
{
|
||||
public:
|
||||
GetCameraResult(nsDOMCameraControl* aDOMCameraControl, nsresult aResult, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mDOMCameraControl(aDOMCameraControl)
|
||||
, mResult(aResult)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
, mOnErrorCb(onError)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DOM_CAMERA_LOGT("%s : this=%p -- BEFORE CALLBACK\n", __func__, this);
|
||||
if (NS_FAILED(mResult)) {
|
||||
if (mOnErrorCb) {
|
||||
mOnErrorCb->HandleEvent(NS_LITERAL_STRING("FAILURE"));
|
||||
}
|
||||
} else {
|
||||
if (mOnSuccessCb) {
|
||||
mOnSuccessCb->HandleEvent(mDOMCameraControl);
|
||||
}
|
||||
}
|
||||
DOM_CAMERA_LOGT("%s : this=%p -- AFTER CALLBACK\n", __func__, this);
|
||||
|
||||
/**
|
||||
* Finally, release the extra reference to the DOM-facing camera control.
|
||||
* See the nsDOMCameraControl constructor for the corresponding call to
|
||||
* NS_ADDREF_THIS().
|
||||
*/
|
||||
NS_RELEASE(mDOMCameraControl);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* 'mDOMCameraControl' is a raw pointer to a previously ADDREF()ed object,
|
||||
* which is released in Run().
|
||||
*/
|
||||
nsDOMCameraControl* mDOMCameraControl;
|
||||
nsresult mResult;
|
||||
nsCOMPtr<nsICameraGetCameraCallback> mOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsDOMCameraControl::Result(nsresult aResult, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
nsCOMPtr<GetCameraResult> getCameraResult = new GetCameraResult(this, aResult, onSuccess, onError);
|
||||
return NS_DispatchToMainThread(getCameraResult);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_CAMERA_DOMCAMERACONTROL_H
|
||||
#define DOM_CAMERA_DOMCAMERACONTROL_H
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "ICameraControl.h"
|
||||
#include "DOMCameraPreview.h"
|
||||
#include "nsIDOMCameraManager.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace dom;
|
||||
|
||||
// Main camera control.
|
||||
class nsDOMCameraControl : public nsICameraControl
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMCameraControl)
|
||||
NS_DECL_NSICAMERACONTROL
|
||||
|
||||
nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult Result(nsresult aResult, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMCameraControl();
|
||||
|
||||
private:
|
||||
nsDOMCameraControl(const nsDOMCameraControl&) MOZ_DELETE;
|
||||
nsDOMCameraControl& operator=(const nsDOMCameraControl&) MOZ_DELETE;
|
||||
|
||||
protected:
|
||||
/* additional members */
|
||||
nsRefPtr<ICameraControl> mCameraControl; // non-DOM camera control
|
||||
nsCOMPtr<nsICameraCapabilities> mDOMCapabilities;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_DOMCAMERACONTROL_H
|
|
@ -2,13 +2,10 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CameraControl.h"
|
||||
#include "DOMCameraControl.h"
|
||||
#include "DOMCameraManager.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
|
||||
#undef DOM_CAMERA_LOG_LEVEL
|
||||
#define DOM_CAMERA_LOG_LEVEL DOM_CAMERA_LOG_NOTHING
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -24,6 +21,16 @@ NS_INTERFACE_MAP_END
|
|||
NS_IMPL_ADDREF(nsDOMCameraManager)
|
||||
NS_IMPL_RELEASE(nsDOMCameraManager)
|
||||
|
||||
/**
|
||||
* Global camera logging object
|
||||
*
|
||||
* Set the NSPR_LOG_MODULES environment variable to enable logging
|
||||
* in a debug build, e.g. NSPR_LOG_MODULES=Camera:5
|
||||
*/
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* gCameraLog;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* nsDOMCameraManager::GetListOfCameras
|
||||
* is implementation-specific, and can be found in (e.g.)
|
||||
|
@ -34,27 +41,32 @@ nsDOMCameraManager::nsDOMCameraManager(uint64_t aWindowId)
|
|||
: mWindowId(aWindowId)
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p, windowId=%llx\n", __func__, __LINE__, this, mWindowId);
|
||||
}
|
||||
|
||||
nsDOMCameraManager::~nsDOMCameraManager()
|
||||
{
|
||||
/* destructor code */
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMCameraManager::OnNavigation(uint64_t aWindowId)
|
||||
{
|
||||
// TODO: implement -- see getUserMedia() implementation
|
||||
// TODO: see bug 779145.
|
||||
}
|
||||
|
||||
// static creator
|
||||
already_AddRefed<nsDOMCameraManager>
|
||||
nsDOMCameraManager::Create(uint64_t aWindowId)
|
||||
{
|
||||
// TODO: check for permissions here to access cameras
|
||||
// TODO: see bug 776934.
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gCameraLog) {
|
||||
gCameraLog = PR_LOG_DEFINE("Camera");
|
||||
}
|
||||
#endif
|
||||
nsRefPtr<nsDOMCameraManager> cameraManager = new nsDOMCameraManager(aWindowId);
|
||||
return cameraManager.forget();
|
||||
}
|
||||
|
@ -81,10 +93,10 @@ nsDOMCameraManager::GetCamera(const JS::Value& aOptions, nsICameraGetCameraCallb
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
nsCOMPtr<nsIRunnable> getCameraTask = new GetCameraTask(cameraId, onSuccess, onError, mCameraThread);
|
||||
mCameraThread->Dispatch(getCameraTask, NS_DISPATCH_NORMAL);
|
||||
// Creating this object will trigger the onSuccess handler
|
||||
nsCOMPtr<nsICameraControl> cameraControl = new nsDOMCameraControl(cameraId, mCameraThread, onSuccess, onError);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ protected:
|
|||
nsCOMPtr<nsIThread> mCameraThread;
|
||||
};
|
||||
|
||||
|
||||
class GetCameraTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -56,28 +55,4 @@ protected:
|
|||
nsCOMPtr<nsIThread> mCameraThread;
|
||||
};
|
||||
|
||||
class GetCameraResult : public nsRunnable
|
||||
{
|
||||
public:
|
||||
GetCameraResult(nsICameraControl* aCameraControl, nsICameraGetCameraCallback* onSuccess)
|
||||
: mCameraControl(aCameraControl)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// TODO: window management stuff
|
||||
if (mOnSuccessCb) {
|
||||
mOnSuccessCb->HandleEvent(mCameraControl);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsICameraControl> mCameraControl;
|
||||
nsCOMPtr<nsICameraGetCameraCallback> mOnSuccessCb;
|
||||
};
|
||||
|
||||
#endif // DOM_CAMERA_DOMCAMERAMANAGER_H
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "Layers.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "DOMCameraPreview.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/**
|
||||
* 'PreviewControl' is a helper class that dispatches preview control
|
||||
* events from the main thread.
|
||||
*
|
||||
* NS_NewRunnableMethod() can't be used because it AddRef()s the method's
|
||||
* object, which can't be done off the main thread for cycle collection
|
||||
* participants.
|
||||
*
|
||||
* Before using this class, 'aDOMPreview' must be appropriately AddRef()ed.
|
||||
*/
|
||||
class PreviewControl : public nsRunnable
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
START,
|
||||
STOP,
|
||||
STARTED,
|
||||
STOPPED
|
||||
};
|
||||
PreviewControl(DOMCameraPreview* aDOMPreview, uint32_t aControl)
|
||||
: mDOMPreview(aDOMPreview)
|
||||
, mControl(aControl)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "PreviewControl not run on main thread");
|
||||
|
||||
switch (mControl) {
|
||||
case START:
|
||||
mDOMPreview->Start();
|
||||
break;
|
||||
|
||||
case STOP:
|
||||
mDOMPreview->Stop();
|
||||
break;
|
||||
|
||||
case STARTED:
|
||||
mDOMPreview->SetStateStarted();
|
||||
break;
|
||||
|
||||
case STOPPED:
|
||||
mDOMPreview->SetStateStopped();
|
||||
break;
|
||||
|
||||
default:
|
||||
DOM_CAMERA_LOGE("PreviewControl: invalid control %d\n", mControl);
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This must be a raw pointer because this class is not created on the
|
||||
* main thread, and DOMCameraPreview is not threadsafe. Prior to
|
||||
* issuing a preview control event, the caller must ensure that
|
||||
* mDOMPreview will not disappear.
|
||||
*/
|
||||
DOMCameraPreview* mDOMPreview;
|
||||
uint32_t mControl;
|
||||
};
|
||||
|
||||
class DOMCameraPreviewListener : public MediaStreamListener
|
||||
{
|
||||
public:
|
||||
DOMCameraPreviewListener(DOMCameraPreview* aDOMPreview) :
|
||||
mDOMPreview(aDOMPreview)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
~DOMCameraPreviewListener()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
void NotifyConsumptionChanged(MediaStreamGraph* aGraph, Consumption aConsuming)
|
||||
{
|
||||
const char* state;
|
||||
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
switch (aConsuming) {
|
||||
case NOT_CONSUMED:
|
||||
state = "not consuming";
|
||||
break;
|
||||
|
||||
case CONSUMED:
|
||||
state = "consuming";
|
||||
break;
|
||||
|
||||
default:
|
||||
state = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGA("camera viewfinder is %s\n", state);
|
||||
nsCOMPtr<nsIRunnable> previewControl;
|
||||
|
||||
switch (aConsuming) {
|
||||
case NOT_CONSUMED:
|
||||
previewControl = new PreviewControl(mDOMPreview, PreviewControl::STOP);
|
||||
break;
|
||||
|
||||
case CONSUMED:
|
||||
previewControl = new PreviewControl(mDOMPreview, PreviewControl::START);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(previewControl);
|
||||
if (NS_FAILED(rv)) {
|
||||
DOM_CAMERA_LOGE("Failed to dispatch preview control (%d)!\n", rv);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// Raw pointer; if we exist, 'mDOMPreview' exists as well
|
||||
DOMCameraPreview* mDOMPreview;
|
||||
};
|
||||
|
||||
DOMCameraPreview::DOMCameraPreview(ICameraControl* aCameraControl, uint32_t aWidth, uint32_t aHeight, uint32_t aFrameRate)
|
||||
: nsDOMMediaStream()
|
||||
, mState(STOPPED)
|
||||
, mWidth(aWidth)
|
||||
, mHeight(aHeight)
|
||||
, mFramesPerSecond(aFrameRate)
|
||||
, mFrameCount(0)
|
||||
, mCameraControl(aCameraControl)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p : mWidth=%d, mHeight=%d, mFramesPerSecond=%d\n", __func__, __LINE__, this, mWidth, mHeight, mFramesPerSecond);
|
||||
|
||||
mImageContainer = LayerManager::CreateImageContainer();
|
||||
MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
|
||||
mStream = gm->CreateInputStream(this);
|
||||
mInput = GetStream()->AsSourceStream();
|
||||
|
||||
mListener = new DOMCameraPreviewListener(this);
|
||||
mInput->AddListener(mListener);
|
||||
|
||||
mInput->AddTrack(TRACK_VIDEO, mFramesPerSecond, 0, new VideoSegment());
|
||||
mInput->AdvanceKnownTracksTime(MEDIA_TIME_MAX);
|
||||
}
|
||||
|
||||
DOMCameraPreview::~DOMCameraPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p, mListener=%p\n", __func__, __LINE__, this, mListener);
|
||||
mInput->RemoveListener(mListener);
|
||||
}
|
||||
|
||||
bool
|
||||
DOMCameraPreview::HaveEnoughBuffered()
|
||||
{
|
||||
return mInput->HaveEnoughBuffered(TRACK_VIDEO);
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (!aBuffer || !aBuilder) {
|
||||
return;
|
||||
}
|
||||
if (mState != STARTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageFormat format = aFormat;
|
||||
nsRefPtr<Image> image = mImageContainer->CreateImage(&format, 1);
|
||||
aBuilder(image, aBuffer, mWidth, mHeight);
|
||||
|
||||
// AppendFrame() takes over image's reference
|
||||
mVideoSegment.AppendFrame(image.forget(), 1, gfxIntSize(mWidth, mHeight));
|
||||
mInput->AppendToTrack(TRACK_VIDEO, &mVideoSegment);
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::Start()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Start() not called from main thread");
|
||||
if (mState != STOPPED) {
|
||||
return;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("Starting preview stream\n");
|
||||
|
||||
/**
|
||||
* Add a reference to ourselves to make sure we stay alive while
|
||||
* the preview is running, as the CameraControlImpl object holds a
|
||||
* weak reference to us.
|
||||
*
|
||||
* This reference is removed in SetStateStopped().
|
||||
*/
|
||||
NS_ADDREF_THIS();
|
||||
mState = STARTING;
|
||||
mCameraControl->StartPreview(this);
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::SetStateStarted()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "SetStateStarted() not called from main thread");
|
||||
|
||||
mState = STARTED;
|
||||
DOM_CAMERA_LOGI("Preview stream started\n");
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::Started()
|
||||
{
|
||||
if (mState != STARTING) {
|
||||
return;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("Dispatching preview stream started\n");
|
||||
nsCOMPtr<nsIRunnable> started = new PreviewControl(this, PreviewControl::STARTED);
|
||||
nsresult rv = NS_DispatchToMainThread(started);
|
||||
if (NS_FAILED(rv)) {
|
||||
DOM_CAMERA_LOGE("failed to set statrted state (%d), POTENTIAL MEMORY LEAK!\n", rv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::Stop()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Stop() not called from main thread");
|
||||
if (mState != STARTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("Stopping preview stream\n");
|
||||
mState = STOPPING;
|
||||
mCameraControl->StopPreview();
|
||||
mInput->EndTrack(TRACK_VIDEO);
|
||||
mInput->Finish();
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::SetStateStopped()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "SetStateStopped() not called from main thread");
|
||||
|
||||
mState = STOPPED;
|
||||
DOM_CAMERA_LOGI("Preview stream stopped\n");
|
||||
|
||||
/**
|
||||
* Only remove the reference added in Start() once the preview
|
||||
* has stopped completely.
|
||||
*/
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::Stopped(bool aForced)
|
||||
{
|
||||
if (mState != STOPPING && !aForced) {
|
||||
return;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("Dispatching preview stream stopped\n");
|
||||
nsCOMPtr<nsIRunnable> stopped = new PreviewControl(this, PreviewControl::STOPPED);
|
||||
nsresult rv = NS_DispatchToMainThread(stopped);
|
||||
if (NS_FAILED(rv)) {
|
||||
DOM_CAMERA_LOGE("failed to decrement reference count (%d), MEMORY LEAK!\n", rv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DOMCameraPreview::Error()
|
||||
{
|
||||
DOM_CAMERA_LOGE("Error occurred changing preview state!\n");
|
||||
Stopped(true);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_CAMERA_DOMCAMERAPREVIEW_H
|
||||
#define DOM_CAMERA_DOMCAMERAPREVIEW_H
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "StreamBuffer.h"
|
||||
#include "ICameraControl.h"
|
||||
#include "nsDOMMediaStream.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef void (*FrameBuilder)(Image* aImage, void* aBuffer, uint32_t aWidth, uint32_t aHeight);
|
||||
|
||||
/**
|
||||
* DOMCameraPreview is only exposed to the DOM as an nsDOMMediaStream,
|
||||
* which is a cycle-collection participant already.
|
||||
*/
|
||||
class DOMCameraPreview : public nsDOMMediaStream
|
||||
{
|
||||
protected:
|
||||
enum { TRACK_VIDEO = 1 };
|
||||
|
||||
public:
|
||||
DOMCameraPreview(ICameraControl* aCameraControl, uint32_t aWidth, uint32_t aHeight, uint32_t aFramesPerSecond = 30);
|
||||
void ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
|
||||
bool HaveEnoughBuffered();
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetCurrentTime(double* aCurrentTime) {
|
||||
return nsDOMMediaStream::GetCurrentTime(aCurrentTime);
|
||||
}
|
||||
|
||||
void Start(); // called by the MediaStreamListener to start preview
|
||||
void Started(); // called by the CameraControl when preview is started
|
||||
void Stop(); // called by the MediaStreamListener to stop preview
|
||||
void Stopped(bool aForced = false);
|
||||
// called by the CameraControl when preview is stopped
|
||||
void Error(); // something went wrong, NS_RELEASE needed
|
||||
|
||||
void SetStateStarted();
|
||||
void SetStateStopped();
|
||||
|
||||
protected:
|
||||
virtual ~DOMCameraPreview();
|
||||
|
||||
enum {
|
||||
STOPPED,
|
||||
STARTING,
|
||||
STARTED,
|
||||
STOPPING
|
||||
};
|
||||
uint32_t mState;
|
||||
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mFramesPerSecond;
|
||||
SourceMediaStream* mInput;
|
||||
nsRefPtr<ImageContainer> mImageContainer;
|
||||
VideoSegment mVideoSegment;
|
||||
uint32_t mFrameCount;
|
||||
nsRefPtr<ICameraControl> mCameraControl;
|
||||
|
||||
// Raw pointer; AddListener() keeps the reference for us
|
||||
MediaStreamListener* mListener;
|
||||
|
||||
private:
|
||||
DOMCameraPreview(const DOMCameraPreview&) MOZ_DELETE;
|
||||
DOMCameraPreview& operator=(const DOMCameraPreview&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_DOMCAMERAPREVIEW_H
|
|
@ -3,138 +3,126 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "CameraControl.h"
|
||||
#include "CameraCapabilities.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "DOMCameraControl.h"
|
||||
#include "DOMCameraCapabilities.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
DOMCI_DATA(CameraCapabilities, nsICameraCapabilities)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsCameraCapabilities)
|
||||
NS_IMPL_CYCLE_COLLECTION_0(DOMCameraCapabilities)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMCameraCapabilities)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICameraCapabilities)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraCapabilities)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(nsCameraCapabilities)
|
||||
NS_IMPL_RELEASE(nsCameraCapabilities)
|
||||
|
||||
nsCameraCapabilities::nsCameraCapabilities(nsCameraControl* aCamera)
|
||||
: mCamera(aCamera)
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
DOM_CAMERA_LOGI("%s:%d : FALLBACK CAMERA CAPABILITIES\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
nsCameraCapabilities::~nsCameraCapabilities()
|
||||
{
|
||||
/* destructor code */
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMCameraCapabilities)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMCameraCapabilities)
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval previewSizes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetPreviewSizes(JSContext* cx, JS::Value* aPreviewSizes)
|
||||
DOMCameraCapabilities::GetPreviewSizes(JSContext* cx, JS::Value* aPreviewSizes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval pictureSizes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
|
||||
DOMCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval fileFormats; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
|
||||
DOMCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval whiteBalanceModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetWhiteBalanceModes(JSContext* cx, JS::Value* aWhiteBalanceModes)
|
||||
DOMCameraCapabilities::GetWhiteBalanceModes(JSContext* cx, JS::Value* aWhiteBalanceModes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval sceneModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetSceneModes(JSContext* cx, JS::Value* aSceneModes)
|
||||
DOMCameraCapabilities::GetSceneModes(JSContext* cx, JS::Value* aSceneModes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval effects; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetEffects(JSContext* cx, JS::Value* aEffects)
|
||||
DOMCameraCapabilities::GetEffects(JSContext* cx, JS::Value* aEffects)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval flashModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetFlashModes(JSContext* cx, JS::Value* aFlashModes)
|
||||
DOMCameraCapabilities::GetFlashModes(JSContext* cx, JS::Value* aFlashModes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval focusModes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetFocusModes(JSContext* cx, JS::Value* aFocusModes)
|
||||
DOMCameraCapabilities::GetFocusModes(JSContext* cx, JS::Value* aFocusModes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute long maxFocusAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
|
||||
DOMCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute double minExposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExposureCompensation)
|
||||
DOMCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExposureCompensation)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute double maxExposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExposureCompensation)
|
||||
DOMCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExposureCompensation)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute double stepExposureCompensation; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepExposureCompensation)
|
||||
DOMCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepExposureCompensation)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute long maxMeteringAreas; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAreas)
|
||||
DOMCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAreas)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval zoomRatios; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
|
||||
DOMCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [implicit_jscontext] readonly attribute jsval videoSizes; */
|
||||
NS_IMETHODIMP
|
||||
nsCameraCapabilities::GetVideoSizes(JSContext* cx, JS::Value* aVideoSizes)
|
||||
DOMCameraCapabilities::GetVideoSizes(JSContext* cx, JS::Value* aVideoSizes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "DOMCameraManager.h"
|
||||
#include "CameraControl.h"
|
||||
#include "DOMCameraControl.h"
|
||||
#include "CameraControlImpl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -12,10 +11,10 @@ using namespace mozilla;
|
|||
* Fallback camera control subclass. Can be used as a template for the
|
||||
* definition of new camera support classes.
|
||||
*/
|
||||
class nsFallbackCameraControl : public nsCameraControl
|
||||
class nsFallbackCameraControl : public CameraControlImpl
|
||||
{
|
||||
public:
|
||||
nsFallbackCameraControl(uint32_t aCameraId, nsIThread* aCameraThread);
|
||||
nsFallbackCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
|
||||
const char* GetParameter(const char* aKey);
|
||||
const char* GetParameterConstChar(uint32_t aKey);
|
||||
|
@ -25,36 +24,52 @@ public:
|
|||
void SetParameter(uint32_t aKey, const char* aValue);
|
||||
void SetParameter(uint32_t aKey, double aValue);
|
||||
void SetParameter(uint32_t aKey, const nsTArray<dom::CameraRegion>& aRegions);
|
||||
void PushParameters();
|
||||
nsresult PushParameters();
|
||||
|
||||
protected:
|
||||
~nsFallbackCameraControl();
|
||||
|
||||
nsresult GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream);
|
||||
nsresult StartPreviewImpl(StartPreviewTask* aStartPreview);
|
||||
nsresult StopPreviewImpl(StopPreviewTask* aStopPreview);
|
||||
nsresult AutoFocusImpl(AutoFocusTask* aAutoFocus);
|
||||
nsresult TakePictureImpl(TakePictureTask* aTakePicture);
|
||||
nsresult StartRecordingImpl(StartRecordingTask* aStartRecording);
|
||||
nsresult StopRecordingImpl(StopRecordingTask* aStopRecording);
|
||||
nsresult PushParametersImpl(PushParametersTask* aPushParameters);
|
||||
nsresult PullParametersImpl(PullParametersTask* aPullParameters);
|
||||
nsresult PushParametersImpl();
|
||||
nsresult PullParametersImpl();
|
||||
|
||||
private:
|
||||
nsFallbackCameraControl(const nsFallbackCameraControl&) MOZ_DELETE;
|
||||
nsFallbackCameraControl& operator=(const nsFallbackCameraControl&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stub implementation of the DOM-facing camera control constructor.
|
||||
*
|
||||
* This should never get called--it exists to keep the linker happy; if
|
||||
* implemented, it should construct (e.g.) nsFallbackCameraControl and
|
||||
* store a reference in the 'mCameraControl' member (which is why it is
|
||||
* defined here).
|
||||
*/
|
||||
nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub implemetations of the fallback camera control.
|
||||
*
|
||||
* None of these should ever get called--they exist to keep the linker happy,
|
||||
* and may be used as templates for new camera support classes.
|
||||
*/
|
||||
nsFallbackCameraControl::nsFallbackCameraControl(uint32_t aCameraId, nsIThread* aCameraThread)
|
||||
: nsCameraControl(aCameraId, aCameraThread)
|
||||
{ }
|
||||
nsFallbackCameraControl::nsFallbackCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: CameraControlImpl(aCameraId, aCameraThread)
|
||||
{
|
||||
}
|
||||
|
||||
nsFallbackCameraControl::~nsFallbackCameraControl()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
nsFallbackCameraControl::GetParameter(const char* aKey)
|
||||
|
@ -99,9 +114,10 @@ nsFallbackCameraControl::SetParameter(uint32_t aKey, const nsTArray<dom::CameraR
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
nsFallbackCameraControl::PushParameters()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -110,6 +126,18 @@ nsFallbackCameraControl::GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewS
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFallbackCameraControl::StartPreviewImpl(StartPreviewTask* aGetPreviewStream)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFallbackCameraControl::StopPreviewImpl(StopPreviewTask* aGetPreviewStream)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFallbackCameraControl::AutoFocusImpl(AutoFocusTask* aAutoFocus)
|
||||
{
|
||||
|
@ -135,13 +163,13 @@ nsFallbackCameraControl::StopRecordingImpl(StopRecordingTask* aStopRecording)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsFallbackCameraControl::PushParametersImpl(PushParametersTask* aPushParameters)
|
||||
nsFallbackCameraControl::PushParametersImpl()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFallbackCameraControl::PullParametersImpl(PullParametersTask* aPullParameters)
|
||||
nsFallbackCameraControl::PullParametersImpl()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -12,11 +12,3 @@ nsDOMCameraManager::GetListOfCameras(JSContext* cx, JS::Value* _retval)
|
|||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetCameraTask::Run()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -26,114 +26,208 @@
|
|||
#include "nsPrintfCString.h"
|
||||
#include "DOMCameraManager.h"
|
||||
#include "GonkCameraHwMgr.h"
|
||||
#include "CameraCapabilities.h"
|
||||
#include "DOMCameraCapabilities.h"
|
||||
#include "DOMCameraControl.h"
|
||||
#include "GonkCameraControl.h"
|
||||
#include "GonkCameraPreview.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace android;
|
||||
|
||||
static const char* getKeyText(uint32_t aKey)
|
||||
{
|
||||
switch (aKey) {
|
||||
case nsCameraControl::CAMERA_PARAM_EFFECT:
|
||||
case CAMERA_PARAM_EFFECT:
|
||||
return CameraParameters::KEY_EFFECT;
|
||||
case nsCameraControl::CAMERA_PARAM_WHITEBALANCE:
|
||||
case CAMERA_PARAM_WHITEBALANCE:
|
||||
return CameraParameters::KEY_WHITE_BALANCE;
|
||||
case nsCameraControl::CAMERA_PARAM_SCENEMODE:
|
||||
case CAMERA_PARAM_SCENEMODE:
|
||||
return CameraParameters::KEY_SCENE_MODE;
|
||||
case nsCameraControl::CAMERA_PARAM_FLASHMODE:
|
||||
case CAMERA_PARAM_FLASHMODE:
|
||||
return CameraParameters::KEY_FLASH_MODE;
|
||||
case nsCameraControl::CAMERA_PARAM_FOCUSMODE:
|
||||
case CAMERA_PARAM_FOCUSMODE:
|
||||
return CameraParameters::KEY_FOCUS_MODE;
|
||||
case nsCameraControl::CAMERA_PARAM_ZOOM:
|
||||
case CAMERA_PARAM_ZOOM:
|
||||
return CameraParameters::KEY_ZOOM;
|
||||
case nsCameraControl::CAMERA_PARAM_METERINGAREAS:
|
||||
case CAMERA_PARAM_METERINGAREAS:
|
||||
return CameraParameters::KEY_METERING_AREAS;
|
||||
case nsCameraControl::CAMERA_PARAM_FOCUSAREAS:
|
||||
case CAMERA_PARAM_FOCUSAREAS:
|
||||
return CameraParameters::KEY_FOCUS_AREAS;
|
||||
case nsCameraControl::CAMERA_PARAM_FOCALLENGTH:
|
||||
case CAMERA_PARAM_FOCALLENGTH:
|
||||
return CameraParameters::KEY_FOCAL_LENGTH;
|
||||
case nsCameraControl::CAMERA_PARAM_FOCUSDISTANCENEAR:
|
||||
case CAMERA_PARAM_FOCUSDISTANCENEAR:
|
||||
return CameraParameters::KEY_FOCUS_DISTANCES;
|
||||
case nsCameraControl::CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
|
||||
case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
|
||||
return CameraParameters::KEY_FOCUS_DISTANCES;
|
||||
case nsCameraControl::CAMERA_PARAM_FOCUSDISTANCEFAR:
|
||||
case CAMERA_PARAM_FOCUSDISTANCEFAR:
|
||||
return CameraParameters::KEY_FOCUS_DISTANCES;
|
||||
case nsCameraControl::CAMERA_PARAM_EXPOSURECOMPENSATION:
|
||||
case CAMERA_PARAM_EXPOSURECOMPENSATION:
|
||||
return CameraParameters::KEY_EXPOSURE_COMPENSATION;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
|
||||
case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
|
||||
return CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
|
||||
case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
|
||||
return CameraParameters::KEY_SUPPORTED_VIDEO_SIZES;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_PICTURESIZES:
|
||||
case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
|
||||
return CameraParameters::KEY_SUPPORTED_PICTURE_SIZES;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
|
||||
case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
|
||||
return CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_WHITEBALANCES:
|
||||
case CAMERA_PARAM_SUPPORTED_WHITEBALANCES:
|
||||
return CameraParameters::KEY_SUPPORTED_WHITE_BALANCE;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_SCENEMODES:
|
||||
case CAMERA_PARAM_SUPPORTED_SCENEMODES:
|
||||
return CameraParameters::KEY_SUPPORTED_SCENE_MODES;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_EFFECTS:
|
||||
case CAMERA_PARAM_SUPPORTED_EFFECTS:
|
||||
return CameraParameters::KEY_SUPPORTED_EFFECTS;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_FLASHMODES:
|
||||
case CAMERA_PARAM_SUPPORTED_FLASHMODES:
|
||||
return CameraParameters::KEY_SUPPORTED_FLASH_MODES;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_FOCUSMODES:
|
||||
case CAMERA_PARAM_SUPPORTED_FOCUSMODES:
|
||||
return CameraParameters::KEY_SUPPORTED_FOCUS_MODES;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS:
|
||||
case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS:
|
||||
return CameraParameters::KEY_MAX_NUM_FOCUS_AREAS;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS:
|
||||
case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS:
|
||||
return CameraParameters::KEY_MAX_NUM_METERING_AREAS;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
|
||||
case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
|
||||
return CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
|
||||
case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
|
||||
return CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP:
|
||||
case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP:
|
||||
return CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_ZOOM:
|
||||
case CAMERA_PARAM_SUPPORTED_ZOOM:
|
||||
return CameraParameters::KEY_ZOOM_SUPPORTED;
|
||||
case nsCameraControl::CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
|
||||
case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
|
||||
return CameraParameters::KEY_ZOOM_RATIOS;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// nsDOMCameraControl implementation-specific constructor
|
||||
nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mDOMCapabilities(nullptr)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
/**
|
||||
* nsDOMCameraControl is a cycle-collection participant, which means it is
|
||||
* not threadsafe--so we need to bump up its reference count here to make
|
||||
* sure that it exists long enough to be initialized.
|
||||
*
|
||||
* Once it is initialized, the GetCameraResult main-thread runnable will
|
||||
* decrement it again to make sure it can be cleaned up.
|
||||
*
|
||||
* nsGonkCameraControl MUST NOT hold a strong reference to this
|
||||
* nsDOMCameraControl or memory will leak!
|
||||
*/
|
||||
NS_ADDREF_THIS();
|
||||
mCameraControl = new nsGonkCameraControl(aCameraId, aCameraThread, this, onSuccess, onError);
|
||||
}
|
||||
|
||||
// Gonk-specific CameraControl implementation.
|
||||
|
||||
nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraThread)
|
||||
: nsCameraControl(aCameraId, aCameraThread)
|
||||
// Initialize nsGonkCameraControl instance--runs on camera thread.
|
||||
class InitGonkCameraControl : public nsRunnable
|
||||
{
|
||||
public:
|
||||
InitGonkCameraControl(nsGonkCameraControl* aCameraControl, nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mCameraControl(aCameraControl)
|
||||
, mDOMCameraControl(aDOMCameraControl)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
, mOnErrorCb(onError)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
~InitGonkCameraControl()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsresult rv = mCameraControl->Init();
|
||||
return mDOMCameraControl->Result(rv, mOnSuccessCb, mOnErrorCb);
|
||||
}
|
||||
|
||||
nsRefPtr<nsGonkCameraControl> mCameraControl;
|
||||
// Raw pointer to DOM-facing camera control--it must NS_ADDREF itself for us
|
||||
nsDOMCameraControl* mDOMCameraControl;
|
||||
nsCOMPtr<nsICameraGetCameraCallback> mOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
|
||||
};
|
||||
|
||||
// Construct nsGonkCameraControl on the main thread.
|
||||
nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: CameraControlImpl(aCameraId, aCameraThread)
|
||||
, mHwHandle(0)
|
||||
, mExposureCompensationMin(0.0)
|
||||
, mExposureCompensationStep(0.0)
|
||||
, mDeferConfigUpdate(false)
|
||||
, mWidth(0)
|
||||
, mHeight(0)
|
||||
, mFormat(PREVIEW_FORMAT_UNKNOWN)
|
||||
, mDiscardedFrameCount(0)
|
||||
{
|
||||
// Constructor runs on the main thread...
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
mRwLock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraControl.Parameters.Lock");
|
||||
|
||||
// ...but initialization is carried out on the camera thread.
|
||||
nsCOMPtr<nsIRunnable> init = new InitGonkCameraControl(this, aDOMCameraControl, onSuccess, onError);
|
||||
mCameraThread->Dispatch(init, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::Init()
|
||||
{
|
||||
// Constructor runs on the camera thread--see DOMCameraManager.cpp::GetCameraImpl().
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
mHwHandle = GonkCameraHardware::GetHandle(this, mCameraId);
|
||||
DOM_CAMERA_LOGI("%s:%d : this = %p, mHwHandle = %d\n", __func__, __LINE__, this, mHwHandle);
|
||||
DOM_CAMERA_LOGI("Initializing camera %d (this=%p, mHwHandle=%d)\n", mCameraId, this, mHwHandle);
|
||||
|
||||
// Initialize our camera configuration database.
|
||||
mRwLock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraControl.Parameters.Lock");
|
||||
PullParametersImpl(nullptr);
|
||||
PullParametersImpl();
|
||||
|
||||
// Grab any settings we'll need later.
|
||||
mExposureCompensationMin = mParams.getFloat(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION);
|
||||
mExposureCompensationStep = mParams.getFloat(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP);
|
||||
mMaxMeteringAreas = mParams.getInt(CameraParameters::KEY_MAX_NUM_METERING_AREAS);
|
||||
mMaxFocusAreas = mParams.getInt(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS);
|
||||
// Try to set preferred image format and frame rate
|
||||
DOM_CAMERA_LOGI("Camera preview formats: %s\n", mParams.get(mParams.KEY_SUPPORTED_PREVIEW_FORMATS));
|
||||
const char* const PREVIEW_FORMAT = "yuv420p";
|
||||
const char* const BAD_PREVIEW_FORMAT = "yuv420sp";
|
||||
mParams.setPreviewFormat(PREVIEW_FORMAT);
|
||||
mParams.setPreviewFrameRate(mFps);
|
||||
|
||||
DOM_CAMERA_LOGI("minimum exposure compensation = %f\n", mExposureCompensationMin);
|
||||
DOM_CAMERA_LOGI("exposure compensation step = %f\n", mExposureCompensationStep);
|
||||
DOM_CAMERA_LOGI("maximum metering areas = %d\n", mMaxMeteringAreas);
|
||||
DOM_CAMERA_LOGI("maximum focus areas = %d\n", mMaxFocusAreas);
|
||||
// Check that our settings stuck
|
||||
PullParametersImpl();
|
||||
const char* format = mParams.getPreviewFormat();
|
||||
if (strcmp(format, PREVIEW_FORMAT) == 0) {
|
||||
mFormat = PREVIEW_FORMAT_YUV420P; /* \o/ */
|
||||
} else if (strcmp(format, BAD_PREVIEW_FORMAT) == 0) {
|
||||
mFormat = PREVIEW_FORMAT_YUV420SP;
|
||||
DOM_CAMERA_LOGA("Camera ignored our request for '%s' preview, will have to convert (from %d)\n", PREVIEW_FORMAT, mFormat);
|
||||
} else {
|
||||
mFormat = PREVIEW_FORMAT_UNKNOWN;
|
||||
DOM_CAMERA_LOGE("Camera ignored our request for '%s' preview, returned UNSUPPORTED format '%s'\n", PREVIEW_FORMAT, format);
|
||||
}
|
||||
|
||||
// Check the frame rate and log if the camera ignored our setting
|
||||
uint32_t fps = mParams.getPreviewFrameRate();
|
||||
if (fps != mFps) {
|
||||
DOM_CAMERA_LOGA("We asked for %d fps but camera returned %d fps, using that", mFps, fps);
|
||||
mFps = fps;
|
||||
}
|
||||
|
||||
// Grab any other settings we'll need later.
|
||||
mExposureCompensationMin = mParams.getFloat(mParams.KEY_MIN_EXPOSURE_COMPENSATION);
|
||||
mExposureCompensationStep = mParams.getFloat(mParams.KEY_EXPOSURE_COMPENSATION_STEP);
|
||||
mMaxMeteringAreas = mParams.getInt(mParams.KEY_MAX_NUM_METERING_AREAS);
|
||||
mMaxFocusAreas = mParams.getInt(mParams.KEY_MAX_NUM_FOCUS_AREAS);
|
||||
|
||||
DOM_CAMERA_LOGI(" - minimum exposure compensation: %f\n", mExposureCompensationMin);
|
||||
DOM_CAMERA_LOGI(" - exposure compensation step: %f\n", mExposureCompensationStep);
|
||||
DOM_CAMERA_LOGI(" - maximum metering areas: %d\n", mMaxMeteringAreas);
|
||||
DOM_CAMERA_LOGI(" - maximum focus areas: %d\n", mMaxFocusAreas);
|
||||
|
||||
return mHwHandle != 0 ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsGonkCameraControl::~nsGonkCameraControl()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : this = %p, mHwHandle = %d\n", __func__, __LINE__, this, mHwHandle);
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p, mHwHandle = %d\n", __func__, __LINE__, this, mHwHandle);
|
||||
GonkCameraHardware::ReleaseHandle(mHwHandle);
|
||||
if (mRwLock) {
|
||||
PRRWLock* lock = mRwLock;
|
||||
|
@ -141,7 +235,7 @@ nsGonkCameraControl::~nsGonkCameraControl()
|
|||
PR_DestroyRWLock(lock);
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
class RwAutoLockRead
|
||||
|
@ -300,24 +394,28 @@ GetParameter_error:
|
|||
aRegions.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
nsGonkCameraControl::PushParameters()
|
||||
{
|
||||
if (!mDeferConfigUpdate) {
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
/**
|
||||
* If we're already on the camera thread, call PushParametersImpl()
|
||||
* directly, so that it executes synchronously. Some callers
|
||||
* require this so that changes take effect immediately before
|
||||
* we can proceed.
|
||||
*/
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIRunnable> pushParametersTask = new PushParametersTask(this);
|
||||
mCameraThread->Dispatch(pushParametersTask, NS_DISPATCH_NORMAL);
|
||||
} else {
|
||||
PushParametersImpl(nullptr);
|
||||
}
|
||||
if (mDeferConfigUpdate) {
|
||||
DOM_CAMERA_LOGT("%s:%d - defering config update\n", __func__, __LINE__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're already on the camera thread, call PushParametersImpl()
|
||||
* directly, so that it executes synchronously. Some callers
|
||||
* require this so that changes take effect immediately before
|
||||
* we can proceed.
|
||||
*/
|
||||
if (NS_IsMainThread()) {
|
||||
DOM_CAMERA_LOGT("%s:%d - dispatching to main thread\n", __func__, __LINE__);
|
||||
nsCOMPtr<nsIRunnable> pushParametersTask = NS_NewRunnableMethod(this, &nsGonkCameraControl::PushParametersImpl);
|
||||
return mCameraThread->Dispatch(pushParametersTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
return PushParametersImpl();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -411,22 +509,55 @@ nsGonkCameraControl::SetParameter(uint32_t aKey, const nsTArray<CameraRegion>& a
|
|||
nsresult
|
||||
nsGonkCameraControl::GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream)
|
||||
{
|
||||
nsCOMPtr<CameraPreview> preview = mPreview;
|
||||
nsresult rv;
|
||||
SetPreviewSize(aGetPreviewStream->mSize.width, aGetPreviewStream->mSize.height);
|
||||
|
||||
if (!preview) {
|
||||
preview = new GonkCameraPreview(mCameraThread, mHwHandle, aGetPreviewStream->mSize.width, aGetPreviewStream->mSize.height);
|
||||
if (!preview) {
|
||||
if (aGetPreviewStream->mOnErrorCb) {
|
||||
rv = NS_DispatchToMainThread(new CameraErrorResult(aGetPreviewStream->mOnErrorCb, NS_LITERAL_STRING("OUT_OF_MEMORY")));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
DOM_CAMERA_LOGI("config preview: wated %d x %d, got %d x %d (%d fps, format %d)\n", aGetPreviewStream->mSize.width, aGetPreviewStream->mSize.height, mWidth, mHeight, mFps, mFormat);
|
||||
|
||||
nsCOMPtr<GetPreviewStreamResult> getPreviewStreamResult = new GetPreviewStreamResult(this, mWidth, mHeight, mFps, aGetPreviewStream->mOnSuccessCb);
|
||||
return NS_DispatchToMainThread(getPreviewStreamResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::StartPreviewImpl(StartPreviewTask* aStartPreview)
|
||||
{
|
||||
/**
|
||||
* If 'aStartPreview->mDOMPreview' is null, we are just restarting
|
||||
* the preview after taking a picture. No need to monkey with the
|
||||
* currently set DOM-facing preview object.
|
||||
*/
|
||||
if (aStartPreview->mDOMPreview) {
|
||||
if (mDOMPreview) {
|
||||
mDOMPreview->Stopped(true);
|
||||
}
|
||||
mDOMPreview = aStartPreview->mDOMPreview;
|
||||
} else if (!mDOMPreview) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
mPreview = preview;
|
||||
return NS_DispatchToMainThread(new GetPreviewStreamResult(preview.get(), aGetPreviewStream->mOnSuccessCb));
|
||||
DOM_CAMERA_LOGI("%s: starting preview (mDOMPreview=%p)\n", __func__, mDOMPreview);
|
||||
if (GonkCameraHardware::StartPreview(mHwHandle) != OK) {
|
||||
DOM_CAMERA_LOGE("%s: failed to start preview\n", __func__);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aStartPreview->mDOMPreview) {
|
||||
mDOMPreview->Started();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::StopPreviewImpl(StopPreviewTask* aStopPreview)
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s: stopping preview\n", __func__);
|
||||
|
||||
// StopPreview() is a synchronous call--it doesn't return
|
||||
// until the camera preview thread exits.
|
||||
GonkCameraHardware::StopPreview(mHwHandle);
|
||||
mDOMPreview->Stopped();
|
||||
mDOMPreview = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -461,7 +592,7 @@ nsGonkCameraControl::AutoFocusImpl(AutoFocusTask* aAutoFocus)
|
|||
nsresult
|
||||
nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
|
||||
{
|
||||
nsCOMPtr<nsICameraTakePictureCallback> cb = mTakePictureOnSuccessCb;
|
||||
nsCOMPtr<nsICameraTakePictureCallback> cb = mTakePictureOnSuccessCb;
|
||||
if (cb) {
|
||||
/**
|
||||
* We already have a callback, so someone has already
|
||||
|
@ -537,8 +668,9 @@ nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::PushParametersImpl(PushParametersTask* aPushParameters)
|
||||
nsGonkCameraControl::PushParametersImpl()
|
||||
{
|
||||
DOM_CAMERA_LOGI("Pushing camera parameters\n");
|
||||
RwAutoLockRead lock(mRwLock);
|
||||
if (GonkCameraHardware::PushParameters(mHwHandle, mParams) != OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -548,8 +680,9 @@ nsGonkCameraControl::PushParametersImpl(PushParametersTask* aPushParameters)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::PullParametersImpl(PullParametersTask* aPullParameters)
|
||||
nsGonkCameraControl::PullParametersImpl()
|
||||
{
|
||||
DOM_CAMERA_LOGI("Pulling camera parameters\n");
|
||||
RwAutoLockWrite lock(mRwLock);
|
||||
GonkCameraHardware::PullParameters(mHwHandle, mParams);
|
||||
return NS_OK;
|
||||
|
@ -568,17 +701,114 @@ nsGonkCameraControl::StopRecordingImpl(StopRecordingTask* aStopRecording)
|
|||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::ReceiveFrame(layers::GraphicBufferLocked *aBuffer)
|
||||
nsGonkCameraControl::AutoFocusComplete(bool aSuccess)
|
||||
{
|
||||
nsCOMPtr<CameraPreview> preview = mPreview;
|
||||
/**
|
||||
* Auto focusing can change some of the camera's parameters, so
|
||||
* we need to pull a new set before sending the result to the
|
||||
* main thread.
|
||||
*/
|
||||
PullParametersImpl();
|
||||
|
||||
if (preview) {
|
||||
GonkCameraPreview* p = static_cast<GonkCameraPreview* >(preview.get());
|
||||
MOZ_ASSERT(p);
|
||||
p->ReceiveFrame(aBuffer);
|
||||
/**
|
||||
* If we make it here, regardless of the value of 'aSuccess', we
|
||||
* consider the autofocus _process_ to have succeeded. It is up
|
||||
* to the onSuccess callback to determine how to handle the case
|
||||
* where the camera wasn't actually able to acquire focus.
|
||||
*/
|
||||
nsCOMPtr<nsIRunnable> autoFocusResult = new AutoFocusResult(aSuccess, mAutoFocusOnSuccessCb);
|
||||
/**
|
||||
* Remember to set these to null so that we don't hold any extra
|
||||
* references to our document's window.
|
||||
*/
|
||||
mAutoFocusOnSuccessCb = nullptr;
|
||||
mAutoFocusOnErrorCb = nullptr;
|
||||
nsresult rv = NS_DispatchToMainThread(autoFocusResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to dispatch autoFocus() onSuccess callback to main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::TakePictureComplete(uint8_t* aData, uint32_t aLength)
|
||||
{
|
||||
uint8_t* data = new uint8_t[aLength];
|
||||
|
||||
memcpy(data, aData, aLength);
|
||||
|
||||
// TODO: see bug 779144.
|
||||
nsIDOMBlob* blob = new nsDOMMemoryFile(static_cast<void*>(data), static_cast<uint64_t>(aLength), NS_LITERAL_STRING("image/jpeg"));
|
||||
nsCOMPtr<nsIRunnable> takePictureResult = new TakePictureResult(blob, mTakePictureOnSuccessCb);
|
||||
/**
|
||||
* Remember to set these to null so that we don't hold any extra
|
||||
* references to our document's window.
|
||||
*/
|
||||
mTakePictureOnSuccessCb = nullptr;
|
||||
mTakePictureOnErrorCb = nullptr;
|
||||
nsresult rv = NS_DispatchToMainThread(takePictureResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to dispatch takePicture() onSuccess callback to main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGonkCameraControl::SetPreviewSize(uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
Vector<Size> previewSizes;
|
||||
uint32_t bestWidth = aWidth;
|
||||
uint32_t bestHeight = aHeight;
|
||||
uint32_t minSizeDelta = PR_UINT32_MAX;
|
||||
uint32_t delta;
|
||||
Size size;
|
||||
|
||||
mParams.getSupportedPreviewSizes(previewSizes);
|
||||
|
||||
if (!aWidth && !aHeight) {
|
||||
// no size specified, take the first supported size
|
||||
size = previewSizes[0];
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
} else if (aWidth && aHeight) {
|
||||
// both height and width specified, find the supported size closest to requested size
|
||||
for (uint32_t i = 0; i < previewSizes.size(); i++) {
|
||||
Size size = previewSizes[i];
|
||||
uint32_t delta = abs((long int)(size.width * size.height - aWidth * aHeight));
|
||||
if (delta < minSizeDelta) {
|
||||
minSizeDelta = delta;
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
}
|
||||
}
|
||||
} else if (!aWidth) {
|
||||
// width not specified, find closest height match
|
||||
for (uint32_t i = 0; i < previewSizes.size(); i++) {
|
||||
size = previewSizes[i];
|
||||
delta = abs((long int)(size.height - aHeight));
|
||||
if (delta < minSizeDelta) {
|
||||
minSizeDelta = delta;
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
}
|
||||
}
|
||||
} else if (!aHeight) {
|
||||
// height not specified, find closest width match
|
||||
for (uint32_t i = 0; i < previewSizes.size(); i++) {
|
||||
size = previewSizes[i];
|
||||
delta = abs((long int)(size.width - aWidth));
|
||||
if (delta < minSizeDelta) {
|
||||
minSizeDelta = delta;
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWidth = bestWidth;
|
||||
mHeight = bestHeight;
|
||||
mParams.setPreviewSize(mWidth, mHeight);
|
||||
PushParameters();
|
||||
}
|
||||
|
||||
// Gonk callback handlers.
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -589,15 +819,29 @@ ReceiveImage(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength)
|
|||
}
|
||||
|
||||
void
|
||||
AutoFocusComplete(nsGonkCameraControl* gc, bool success)
|
||||
AutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess)
|
||||
{
|
||||
gc->AutoFocusComplete(success);
|
||||
gc->AutoFocusComplete(aSuccess);
|
||||
}
|
||||
|
||||
static void
|
||||
GonkFrameBuilder(Image* aImage, void* aBuffer, uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
/**
|
||||
* Cast the generic Image back to our platform-specific type and
|
||||
* populate it.
|
||||
*/
|
||||
GonkIOSurfaceImage* videoImage = static_cast<GonkIOSurfaceImage*>(aImage);
|
||||
GonkIOSurfaceImage::Data data;
|
||||
data.mGraphicBuffer = static_cast<layers::GraphicBufferLocked*>(aBuffer);
|
||||
data.mPicSize = gfxIntSize(aWidth, aHeight);
|
||||
videoImage->SetData(data);
|
||||
}
|
||||
|
||||
void
|
||||
ReceiveFrame(nsGonkCameraControl* gc, layers::GraphicBufferLocked *aBuffer)
|
||||
ReceiveFrame(nsGonkCameraControl* gc, layers::GraphicBufferLocked* aBuffer)
|
||||
{
|
||||
gc->ReceiveFrame(aBuffer);
|
||||
gc->ReceiveFrame(aBuffer, ImageFormat::GONK_IO_SURFACE, GonkFrameBuilder);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
#ifndef DOM_CAMERA_GONKCAMERACONTROL_H
|
||||
#define DOM_CAMERA_GONKCAMERACONTROL_H
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "prtypes.h"
|
||||
#include "prrwlock.h"
|
||||
#include "CameraControl.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "nsIDOMCameraManager.h"
|
||||
#include "DOMCameraControl.h"
|
||||
#include "CameraControlImpl.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -30,10 +31,11 @@ namespace layers {
|
|||
class GraphicBufferLocked;
|
||||
}
|
||||
|
||||
class nsGonkCameraControl : public nsCameraControl
|
||||
class nsGonkCameraControl : public CameraControlImpl
|
||||
{
|
||||
public:
|
||||
nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraThread);
|
||||
nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsDOMCameraControl* aDOMCameraControl, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult Init();
|
||||
|
||||
const char* GetParameter(const char* aKey);
|
||||
const char* GetParameterConstChar(uint32_t aKey);
|
||||
|
@ -43,20 +45,25 @@ public:
|
|||
void SetParameter(uint32_t aKey, const char* aValue);
|
||||
void SetParameter(uint32_t aKey, double aValue);
|
||||
void SetParameter(uint32_t aKey, const nsTArray<dom::CameraRegion>& aRegions);
|
||||
void PushParameters();
|
||||
nsresult PushParameters();
|
||||
|
||||
void ReceiveFrame(layers::GraphicBufferLocked* aBuffer);
|
||||
void AutoFocusComplete(bool aSuccess);
|
||||
void TakePictureComplete(uint8_t* aData, uint32_t aLength);
|
||||
|
||||
protected:
|
||||
~nsGonkCameraControl();
|
||||
|
||||
nsresult GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream);
|
||||
nsresult StartPreviewImpl(StartPreviewTask* aStartPreview);
|
||||
nsresult StopPreviewImpl(StopPreviewTask* aStopPreview);
|
||||
nsresult AutoFocusImpl(AutoFocusTask* aAutoFocus);
|
||||
nsresult TakePictureImpl(TakePictureTask* aTakePicture);
|
||||
nsresult StartRecordingImpl(StartRecordingTask* aStartRecording);
|
||||
nsresult StopRecordingImpl(StopRecordingTask* aStopRecording);
|
||||
nsresult PushParametersImpl(PushParametersTask* aPushParameters);
|
||||
nsresult PullParametersImpl(PullParametersTask* aPullParameters);
|
||||
nsresult PushParametersImpl();
|
||||
nsresult PullParametersImpl();
|
||||
|
||||
void SetPreviewSize(uint32_t aWidth, uint32_t aHeight);
|
||||
|
||||
uint32_t mHwHandle;
|
||||
double mExposureCompensationMin;
|
||||
|
@ -64,6 +71,18 @@ protected:
|
|||
bool mDeferConfigUpdate;
|
||||
PRRWLock* mRwLock;
|
||||
android::CameraParameters mParams;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
|
||||
enum {
|
||||
PREVIEW_FORMAT_UNKNOWN,
|
||||
PREVIEW_FORMAT_YUV420P,
|
||||
PREVIEW_FORMAT_YUV420SP
|
||||
};
|
||||
uint32_t mFormat;
|
||||
|
||||
uint32_t mFps;
|
||||
uint32_t mDiscardedFrameCount;
|
||||
|
||||
private:
|
||||
nsGonkCameraControl(const nsGonkCameraControl&) MOZ_DELETE;
|
||||
|
@ -72,7 +91,7 @@ private:
|
|||
|
||||
// camera driver callbacks
|
||||
void ReceiveImage(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength);
|
||||
void AutoFocusComplete(nsGonkCameraControl* gc, bool success);
|
||||
void AutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess);
|
||||
void ReceiveFrame(nsGonkCameraControl* gc, layers::GraphicBufferLocked* aBuffer);
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -18,24 +18,12 @@
|
|||
#include "nsDebug.h"
|
||||
#include "GonkCameraHwMgr.h"
|
||||
#include "GonkNativeWindow.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
using namespace android;
|
||||
|
||||
/**
|
||||
* See bug 783682. Most camera implementations, despite claiming they
|
||||
* support 'yuv420p' as a preview format, actually ignore this setting
|
||||
* and return 'yuv420sp' data anyway. We have come across a new implementation
|
||||
* that, while reporting that 'yuv420p' is supported *and* has been accepted,
|
||||
* still returns the frame data in 'yuv420sp' anyway. So for now, since
|
||||
* everyone seems to return this format, we just force it.
|
||||
*/
|
||||
#define FORCE_PREVIEW_FORMAT_YUV420SP 1
|
||||
|
||||
#if GIHM_TIMING_RECEIVEFRAME
|
||||
#define INCLUDE_TIME_H 1
|
||||
#endif
|
||||
|
@ -60,20 +48,14 @@ static __inline void timespecSubtract(struct timespec* a, struct timespec* b)
|
|||
|
||||
GonkCameraHardware::GonkCameraHardware(GonkCamera* aTarget, uint32_t aCamera)
|
||||
: mCamera(aCamera)
|
||||
, mFps(30)
|
||||
#if !FORCE_PREVIEW_FORMAT_YUV420SP
|
||||
, mPreviewFormat(PREVIEW_FORMAT_UNKNOWN)
|
||||
#else
|
||||
, mPreviewFormat(PREVIEW_FORMAT_YUV420SP)
|
||||
#endif
|
||||
, mClosing(false)
|
||||
, mMonitor("GonkCameraHardware.Monitor")
|
||||
, mNumFrames(0)
|
||||
, mTarget(aTarget)
|
||||
, mInitialized(false)
|
||||
{
|
||||
DOM_CAMERA_LOGI( "%s: this = %p (aTarget = %p)\n", __func__, (void*)this, (void*)aTarget );
|
||||
init();
|
||||
DOM_CAMERA_LOGT( "%s:%d : this=%p (aTarget=%p)\n", __func__, __LINE__, (void*)this, (void*)aTarget );
|
||||
Init();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -162,9 +144,9 @@ GonkCameraHardware::NotifyCallback(int32_t aMsgType, int32_t ext1, int32_t ext2,
|
|||
}
|
||||
|
||||
void
|
||||
GonkCameraHardware::init()
|
||||
GonkCameraHardware::Init()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s: this = %p\n", __func__, (void* )this);
|
||||
DOM_CAMERA_LOGT("%s: this=%p\n", __func__, (void* )this);
|
||||
|
||||
if (hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t**)&mModule) < 0) {
|
||||
return;
|
||||
|
@ -177,24 +159,16 @@ GonkCameraHardware::init()
|
|||
return;
|
||||
}
|
||||
|
||||
mWindow = new GonkNativeWindow(this);
|
||||
|
||||
if (sHwHandle == 0) {
|
||||
sHwHandle = 1; // don't use 0
|
||||
}
|
||||
mHardware->setCallbacks(GonkCameraHardware::NotifyCallback, GonkCameraHardware::DataCallback, NULL, (void*)sHwHandle);
|
||||
|
||||
// initialize the local camera parameter database
|
||||
mParams = mHardware->getParameters();
|
||||
|
||||
mHardware->setPreviewWindow(mWindow);
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
GonkCameraHardware::~GonkCameraHardware()
|
||||
{
|
||||
DOM_CAMERA_LOGI( "%s:%d : this = %p\n", __func__, __LINE__, (void*)this );
|
||||
DOM_CAMERA_LOGT( "%s:%d : this=%p\n", __func__, __LINE__, (void*)this );
|
||||
sHw = nullptr;
|
||||
}
|
||||
|
||||
|
@ -210,15 +184,17 @@ GonkCameraHardware::ReleaseHandle(uint32_t aHwHandle)
|
|||
return;
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("%s: before: sHwHandle = %d\n", __func__, sHwHandle);
|
||||
DOM_CAMERA_LOGT("%s: before: sHwHandle = %d\n", __func__, sHwHandle);
|
||||
sHwHandle += 1; // invalidate old handles before deleting
|
||||
hw->mClosing = true;
|
||||
hw->mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS);
|
||||
hw->mHardware->stopPreview();
|
||||
hw->mHardware->release();
|
||||
GonkNativeWindow* window = static_cast<GonkNativeWindow*>(hw->mWindow.get());
|
||||
window->abandon();
|
||||
DOM_CAMERA_LOGI("%s: after: sHwHandle = %d\n", __func__, sHwHandle);
|
||||
if (window) {
|
||||
window->abandon();
|
||||
}
|
||||
DOM_CAMERA_LOGT("%s: after: sHwHandle = %d\n", __func__, sHwHandle);
|
||||
delete hw; // destroy the camera hardware instance
|
||||
}
|
||||
|
||||
|
@ -239,96 +215,6 @@ GonkCameraHardware::GetHandle(GonkCamera* aTarget, uint32_t aCamera)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GonkCameraHardware::GetFps(uint32_t aHwHandle)
|
||||
{
|
||||
GonkCameraHardware* hw = GetHardware(aHwHandle);
|
||||
if (!hw) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hw->mFps;
|
||||
}
|
||||
|
||||
void
|
||||
GonkCameraHardware::GetPreviewSize(uint32_t aHwHandle, uint32_t* aWidth, uint32_t* aHeight)
|
||||
{
|
||||
GonkCameraHardware* hw = GetHardware(aHwHandle);
|
||||
if (hw) {
|
||||
*aWidth = hw->mWidth;
|
||||
*aHeight = hw->mHeight;
|
||||
} else {
|
||||
*aWidth = 0;
|
||||
*aHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GonkCameraHardware::SetPreviewSize(uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
Vector<Size> previewSizes;
|
||||
uint32_t bestWidth = aWidth;
|
||||
uint32_t bestHeight = aHeight;
|
||||
uint32_t minSizeDelta = PR_UINT32_MAX;
|
||||
uint32_t delta;
|
||||
Size size;
|
||||
|
||||
mParams.getSupportedPreviewSizes(previewSizes);
|
||||
|
||||
if (!aWidth && !aHeight) {
|
||||
// no size specified, take the first supported size
|
||||
size = previewSizes[0];
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
} else if (aWidth && aHeight) {
|
||||
// both height and width specified, find the supported size closest to requested size
|
||||
for (uint32_t i = 0; i < previewSizes.size(); i++) {
|
||||
Size size = previewSizes[i];
|
||||
uint32_t delta = abs((long int)(size.width * size.height - aWidth * aHeight));
|
||||
if (delta < minSizeDelta) {
|
||||
minSizeDelta = delta;
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
}
|
||||
}
|
||||
} else if (!aWidth) {
|
||||
// width not specified, find closest height match
|
||||
for (uint32_t i = 0; i < previewSizes.size(); i++) {
|
||||
size = previewSizes[i];
|
||||
delta = abs((long int)(size.height - aHeight));
|
||||
if (delta < minSizeDelta) {
|
||||
minSizeDelta = delta;
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
}
|
||||
}
|
||||
} else if (!aHeight) {
|
||||
// height not specified, find closest width match
|
||||
for (uint32_t i = 0; i < previewSizes.size(); i++) {
|
||||
size = previewSizes[i];
|
||||
delta = abs((long int)(size.width - aWidth));
|
||||
if (delta < minSizeDelta) {
|
||||
minSizeDelta = delta;
|
||||
bestWidth = size.width;
|
||||
bestHeight = size.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWidth = bestWidth;
|
||||
mHeight = bestHeight;
|
||||
mParams.setPreviewSize(mWidth, mHeight);
|
||||
}
|
||||
|
||||
void
|
||||
GonkCameraHardware::SetPreviewSize(uint32_t aHwHandle, uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
GonkCameraHardware* hw = GetHardware(aHwHandle);
|
||||
if (hw) {
|
||||
hw->SetPreviewSize(aWidth, aHeight);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
GonkCameraHardware::AutoFocus(uint32_t aHwHandle)
|
||||
{
|
||||
|
@ -396,43 +282,15 @@ GonkCameraHardware::PullParameters(uint32_t aHwHandle, CameraParameters& aParams
|
|||
int
|
||||
GonkCameraHardware::StartPreview()
|
||||
{
|
||||
const char* format;
|
||||
|
||||
#if !FORCE_PREVIEW_FORMAT_YUV420SP
|
||||
DOM_CAMERA_LOGI("Preview formats: %s\n", mParams.get(mParams.KEY_SUPPORTED_PREVIEW_FORMATS));
|
||||
|
||||
// try to set preferred image format and frame rate
|
||||
const char* const PREVIEW_FORMAT = "yuv420p";
|
||||
const char* const BAD_PREVIEW_FORMAT = "yuv420sp";
|
||||
mParams.setPreviewFormat(PREVIEW_FORMAT);
|
||||
mParams.setPreviewFrameRate(mFps);
|
||||
mHardware->setParameters(mParams);
|
||||
|
||||
// check that our settings stuck
|
||||
mParams = mHardware->getParameters();
|
||||
format = mParams.getPreviewFormat();
|
||||
if (strcmp(format, PREVIEW_FORMAT) == 0) {
|
||||
mPreviewFormat = PREVIEW_FORMAT_YUV420P; /* \o/ */
|
||||
} else if (strcmp(format, BAD_PREVIEW_FORMAT) == 0) {
|
||||
mPreviewFormat = PREVIEW_FORMAT_YUV420SP;
|
||||
DOM_CAMERA_LOGA("Camera ignored our request for '%s' preview, will have to convert (from %d)\n", PREVIEW_FORMAT, mPreviewFormat);
|
||||
if (mWindow.get()) {
|
||||
GonkNativeWindow* window = static_cast<GonkNativeWindow*>(mWindow.get());
|
||||
window->abandon();
|
||||
} else {
|
||||
mPreviewFormat = PREVIEW_FORMAT_UNKNOWN;
|
||||
DOM_CAMERA_LOGE("Camera ignored our request for '%s' preview, returned UNSUPPORTED format '%s'\n", PREVIEW_FORMAT, format);
|
||||
}
|
||||
#else
|
||||
mParams.setPreviewFormat("yuv420sp");
|
||||
mParams.setPreviewFrameRate(mFps);
|
||||
mHardware->setParameters(mParams);
|
||||
#endif
|
||||
|
||||
// Check the frame rate and log if the camera ignored our setting
|
||||
uint32_t fps = mParams.getPreviewFrameRate();
|
||||
if (fps != mFps) {
|
||||
DOM_CAMERA_LOGA("We asked for %d fps but camera returned %d fps, using it", mFps, fps);
|
||||
mFps = fps;
|
||||
mWindow = new GonkNativeWindow(this);
|
||||
mHardware->setPreviewWindow(mWindow);
|
||||
}
|
||||
|
||||
mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
|
||||
return mHardware->startPreview();
|
||||
}
|
||||
|
||||
|
@ -456,14 +314,3 @@ GonkCameraHardware::StopPreview(uint32_t aHwHandle)
|
|||
hw->mHardware->stopPreview();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GonkCameraHardware::GetPreviewFormat(uint32_t aHwHandle)
|
||||
{
|
||||
GonkCameraHardware* hw = GetHardware(aHwHandle);
|
||||
if (!hw) {
|
||||
return PREVIEW_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
return hw->mPreviewFormat;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
#include "mozilla/ReentrantMonitor.h"
|
||||
|
||||
#include "GonkCameraControl.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
#include "GonkNativeWindow.h"
|
||||
|
@ -44,35 +42,24 @@ class GonkCameraHardware : GonkNativeWindowNewFrameCallback
|
|||
protected:
|
||||
GonkCameraHardware(GonkCamera* aTarget, uint32_t aCamera);
|
||||
~GonkCameraHardware();
|
||||
void init();
|
||||
void Init();
|
||||
|
||||
static void DataCallback(int32_t aMsgType, const sp<IMemory> &aDataPtr, camera_frame_metadata_t* aMetadata, void* aUser);
|
||||
static void NotifyCallback(int32_t aMsgType, int32_t ext1, int32_t ext2, void* aUser);
|
||||
static void DataCallback(int32_t aMsgType, const sp<IMemory> &aDataPtr, camera_frame_metadata_t* aMetadata, void* aUser);
|
||||
static void NotifyCallback(int32_t aMsgType, int32_t ext1, int32_t ext2, void* aUser);
|
||||
|
||||
public:
|
||||
virtual void OnNewFrame() MOZ_OVERRIDE;
|
||||
virtual void OnNewFrame() MOZ_OVERRIDE;
|
||||
|
||||
static void ReleaseHandle(uint32_t aHwHandle);
|
||||
static uint32_t GetHandle(GonkCamera* aTarget, uint32_t aCamera);
|
||||
static uint32_t GetFps(uint32_t aHwHandle);
|
||||
static void GetPreviewSize(uint32_t aHwHandle, uint32_t* aWidth, uint32_t* aHeight);
|
||||
static void SetPreviewSize(uint32_t aHwHandle, uint32_t aWidth, uint32_t aHeight);
|
||||
static int AutoFocus(uint32_t aHwHandle);
|
||||
static void CancelAutoFocus(uint32_t aHwHandle);
|
||||
static int TakePicture(uint32_t aHwHandle);
|
||||
static void CancelTakePicture(uint32_t aHwHandle);
|
||||
static int StartPreview(uint32_t aHwHandle);
|
||||
static void StopPreview(uint32_t aHwHandle);
|
||||
static int PushParameters(uint32_t aHwHandle, const CameraParameters& aParams);
|
||||
static void PullParameters(uint32_t aHwHandle, CameraParameters& aParams);
|
||||
|
||||
enum {
|
||||
PREVIEW_FORMAT_UNKNOWN,
|
||||
PREVIEW_FORMAT_YUV420P,
|
||||
PREVIEW_FORMAT_YUV420SP
|
||||
};
|
||||
// GetPreviewFormat() MUST be called only after StartPreview().
|
||||
static uint32_t GetPreviewFormat(uint32_t aHwHandle);
|
||||
static void ReleaseHandle(uint32_t aHwHandle);
|
||||
static uint32_t GetHandle(GonkCamera* aTarget, uint32_t aCamera);
|
||||
static int AutoFocus(uint32_t aHwHandle);
|
||||
static void CancelAutoFocus(uint32_t aHwHandle);
|
||||
static int TakePicture(uint32_t aHwHandle);
|
||||
static void CancelTakePicture(uint32_t aHwHandle);
|
||||
static int StartPreview(uint32_t aHwHandle);
|
||||
static void StopPreview(uint32_t aHwHandle);
|
||||
static int PushParameters(uint32_t aHwHandle, const CameraParameters& aParams);
|
||||
static void PullParameters(uint32_t aHwHandle, CameraParameters& aParams);
|
||||
|
||||
protected:
|
||||
static GonkCameraHardware* sHw;
|
||||
|
@ -91,15 +78,10 @@ protected:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Instance wrappers to make member function access easier.
|
||||
void SetPreviewSize(uint32_t aWidth, uint32_t aHeight);
|
||||
// Instance wrapper to make member function access easier.
|
||||
int StartPreview();
|
||||
|
||||
uint32_t mCamera;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mFps;
|
||||
uint32_t mPreviewFormat;
|
||||
bool mClosing;
|
||||
mozilla::ReentrantMonitor mMonitor;
|
||||
uint32_t mNumFrames;
|
||||
|
@ -107,7 +89,6 @@ protected:
|
|||
GonkCamera* mTarget;
|
||||
camera_module_t* mModule;
|
||||
sp<ANativeWindow> mWindow;
|
||||
CameraParameters mParams;
|
||||
#if GIHM_TIMING_OVERALL
|
||||
struct timespec mStart;
|
||||
struct timespec mAutoFocusStart;
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#include "libcameraservice/CameraHardwareInterface.h"
|
||||
#include "GonkCameraControl.h"
|
||||
#include "DOMCameraManager.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
// From nsDOMCameraManager, but gonk-specific!
|
||||
|
@ -67,7 +65,7 @@ nsDOMCameraManager::GetListOfCameras(JSContext* cx, JS::Value* _retval)
|
|||
break;
|
||||
|
||||
default:
|
||||
// TODO: handle extra cameras in getCamera().
|
||||
// TODO: see bug 779143.
|
||||
{
|
||||
static uint32_t extraIndex = 2;
|
||||
nsCString s;
|
||||
|
@ -93,15 +91,3 @@ nsDOMCameraManager::GetListOfCameras(JSContext* cx, JS::Value* _retval)
|
|||
*_retval = OBJECT_TO_JSVAL(a);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetCameraTask::Run()
|
||||
{
|
||||
nsCOMPtr<nsICameraControl> cameraControl = new nsGonkCameraControl(mCameraId, mCameraThread);
|
||||
|
||||
DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
return NS_DispatchToMainThread(new GetCameraResult(cameraControl, mOnSuccessCb));
|
||||
}
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "GonkCameraHwMgr.h"
|
||||
#include "GonkCameraPreview.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 2
|
||||
#include "CameraCommon.h"
|
||||
|
||||
#include "GonkIOSurfaceImage.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
void
|
||||
GonkCameraPreview::ReceiveFrame(mozilla::layers::GraphicBufferLocked* aBuffer)
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (!aBuffer)
|
||||
return;
|
||||
|
||||
ImageFormat format = ImageFormat::GONK_IO_SURFACE;
|
||||
nsRefPtr<Image> image = mImageContainer->CreateImage(&format, 1);
|
||||
GonkIOSurfaceImage* videoImage = static_cast<GonkIOSurfaceImage*>(image.get());
|
||||
GonkIOSurfaceImage::Data data;
|
||||
data.mGraphicBuffer = aBuffer;
|
||||
data.mPicSize = gfxIntSize(mWidth, mHeight);
|
||||
videoImage->SetData(data);
|
||||
|
||||
// AppendFrame() takes over image's reference
|
||||
mVideoSegment.AppendFrame(image.forget(), 1, gfxIntSize(mWidth, mHeight));
|
||||
mInput->AppendToTrack(TRACK_VIDEO, &mVideoSegment);
|
||||
|
||||
mFrameCount += 1;
|
||||
|
||||
if ((mFrameCount % 10) == 0) {
|
||||
DOM_CAMERA_LOGI("%s:%d : mFrameCount = %d\n", __func__, __LINE__, mFrameCount);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
GonkCameraPreview::StartImpl()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
/**
|
||||
* We set and then immediately get the preview size, in case the camera
|
||||
* driver has decided to ignore our given dimensions.
|
||||
*/
|
||||
GonkCameraHardware::SetPreviewSize(mHwHandle, mWidth, mHeight);
|
||||
GonkCameraHardware::GetPreviewSize(mHwHandle, &mWidth, &mHeight);
|
||||
SetFrameRate(GonkCameraHardware::GetFps(mHwHandle));
|
||||
|
||||
if (GonkCameraHardware::StartPreview(mHwHandle) != OK) {
|
||||
DOM_CAMERA_LOGE("%s: failed to start preview\n", __func__);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// GetPreviewFormat() must be called after StartPreview().
|
||||
mFormat = GonkCameraHardware::GetPreviewFormat(mHwHandle);
|
||||
DOM_CAMERA_LOGI("preview stream is (actually!) %d x %d (w x h), %d frames per second, format %d\n", mWidth, mHeight, mFramesPerSecond, mFormat);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GonkCameraPreview::StopImpl()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
GonkCameraHardware::StopPreview(mHwHandle);
|
||||
mInput->EndTrack(TRACK_VIDEO);
|
||||
mInput->Finish();
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2012 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_GONKCAMERAPREVIEW_H
|
||||
#define DOM_CAMERA_GONKCAMERAPREVIEW_H
|
||||
|
||||
#include "CameraPreview.h"
|
||||
|
||||
#define DOM_CAMERA_LOG_LEVEL 3
|
||||
#include "CameraCommon.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class GraphicBufferLocked;
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GonkCameraPreview : public CameraPreview
|
||||
{
|
||||
public:
|
||||
GonkCameraPreview(nsIThread* aCameraThread, uint32_t aHwHandle, uint32_t aWidth, uint32_t aHeight)
|
||||
: CameraPreview(aCameraThread, aWidth, aHeight)
|
||||
, mHwHandle(aHwHandle)
|
||||
, mDiscardedFrameCount(0)
|
||||
, mFormat(GonkCameraHardware::PREVIEW_FORMAT_UNKNOWN)
|
||||
{ }
|
||||
|
||||
void ReceiveFrame(layers::GraphicBufferLocked* aBuffer);
|
||||
|
||||
nsresult StartImpl();
|
||||
nsresult StopImpl();
|
||||
|
||||
protected:
|
||||
~GonkCameraPreview()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
uint32_t mHwHandle;
|
||||
uint32_t mDiscardedFrameCount;
|
||||
uint32_t mFormat;
|
||||
|
||||
private:
|
||||
GonkCameraPreview(const GonkCameraPreview&) MOZ_DELETE;
|
||||
GonkCameraPreview& operator=(const GonkCameraPreview&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_GONKCAMERAPREVIEW_H
|
|
@ -57,6 +57,8 @@ GonkNativeWindow::~GonkNativeWindow()
|
|||
void GonkNativeWindow::abandon()
|
||||
{
|
||||
Mutex::Autolock lock(mMutex);
|
||||
++mGeneration;
|
||||
CNW_LOGD("abandon: new generation %d", mGeneration);
|
||||
freeAllBuffersLocked();
|
||||
mDequeueCondition.signal();
|
||||
}
|
||||
|
@ -79,6 +81,7 @@ void GonkNativeWindow::init()
|
|||
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
|
||||
mBufferCount = MIN_BUFFER_SLOTS;
|
||||
mFrameCounter = 0;
|
||||
mGeneration = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -346,7 +349,7 @@ int GonkNativeWindow::queueBuffer(ANativeWindowBuffer* buffer)
|
|||
already_AddRefed<GraphicBufferLocked>
|
||||
GonkNativeWindow::getCurrentBuffer()
|
||||
{
|
||||
CNW_LOGD("GonkNativeWindow::lockCurrentBuffer");
|
||||
CNW_LOGD("GonkNativeWindow::getCurrentBuffer");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
int found = -1;
|
||||
|
@ -368,30 +371,36 @@ GonkNativeWindow::getCurrentBuffer()
|
|||
mSlots[found].mBufferState = BufferSlot::RENDERING;
|
||||
|
||||
nsRefPtr<GraphicBufferLocked> ret =
|
||||
new CameraGraphicBuffer(this, found, mSlots[found].mSurfaceDescriptor);
|
||||
new CameraGraphicBuffer(this, found, mGeneration, mSlots[found].mSurfaceDescriptor);
|
||||
mDequeueCondition.signal();
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
void
|
||||
GonkNativeWindow::returnBuffer(uint32_t aIndex)
|
||||
bool
|
||||
GonkNativeWindow::returnBuffer(uint32_t aIndex, uint32_t aGeneration)
|
||||
{
|
||||
CNW_LOGD("GonkNativeWindow::freeBuffer");
|
||||
CNW_LOGD("GonkNativeWindow::returnBuffer: slot=%d (generation=%d)", aIndex, aGeneration);
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
if (aGeneration != mGeneration) {
|
||||
CNW_LOGD("returnBuffer: buffer is from generation %d (current is %d)",
|
||||
aGeneration, mGeneration);
|
||||
return false;
|
||||
}
|
||||
if (aIndex < 0 || aIndex >= mBufferCount) {
|
||||
CNW_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
|
||||
CNW_LOGE("returnBuffer: slot index out of range [0, %d]: %d",
|
||||
mBufferCount, aIndex);
|
||||
return;
|
||||
} else if (mSlots[aIndex].mBufferState != BufferSlot::RENDERING) {
|
||||
printf_stderr("cancelBuffer: slot %d is not owned by the compositor (state=%d)",
|
||||
return false;
|
||||
}
|
||||
if (mSlots[aIndex].mBufferState != BufferSlot::RENDERING) {
|
||||
CNW_LOGE("returnBuffer: slot %d is not owned by the compositor (state=%d)",
|
||||
aIndex, mSlots[aIndex].mBufferState);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
mSlots[aIndex].mBufferState = BufferSlot::FREE;
|
||||
mDequeueCondition.signal();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
int GonkNativeWindow::lockBuffer(ANativeWindowBuffer* buffer)
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
|
||||
// Return the buffer to the queue and mark it as FREE. After that
|
||||
// the buffer is useable again for the decoder.
|
||||
void returnBuffer(uint32_t index);
|
||||
bool returnBuffer(uint32_t index, uint32_t generation);
|
||||
|
||||
// Release all internal buffers
|
||||
void abandon();
|
||||
|
@ -221,6 +221,9 @@ private:
|
|||
// mFrameCounter is the free running counter, incremented for every buffer queued
|
||||
uint64_t mFrameCounter;
|
||||
|
||||
// mGeneration is the current generation of buffer slots
|
||||
uint32_t mGeneration;
|
||||
|
||||
GonkNativeWindowNewFrameCallback* mNewFrameCallback;
|
||||
};
|
||||
|
||||
|
@ -231,10 +234,12 @@ class CameraGraphicBuffer : public mozilla::layers::GraphicBufferLocked {
|
|||
public:
|
||||
CameraGraphicBuffer(GonkNativeWindow* aNativeWindow,
|
||||
uint32_t aIndex,
|
||||
uint32_t aGeneration,
|
||||
SurfaceDescriptor aBuffer)
|
||||
: GraphicBufferLocked(aBuffer)
|
||||
, mNativeWindow(aNativeWindow)
|
||||
, mIndex(aIndex)
|
||||
, mGeneration(aGeneration)
|
||||
, mLocked(true)
|
||||
{}
|
||||
|
||||
|
@ -248,12 +253,11 @@ public:
|
|||
// The window might has been destroyed. The buffer is no longer
|
||||
// valid at that point.
|
||||
sp<GonkNativeWindow> window = mNativeWindow.promote();
|
||||
if (window.get()) {
|
||||
window->returnBuffer(mIndex);
|
||||
if (window.get() && window->returnBuffer(mIndex, mGeneration)) {
|
||||
mLocked = false;
|
||||
} else {
|
||||
// If the window doesn't exist any more, release the buffer by
|
||||
// ourself.
|
||||
// If the window doesn't exist any more, release the buffer
|
||||
// by ourself.
|
||||
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
|
||||
ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
|
||||
}
|
||||
|
@ -263,6 +267,7 @@ public:
|
|||
protected:
|
||||
wp<GonkNativeWindow> mNativeWindow;
|
||||
uint32_t mIndex;
|
||||
uint32_t mGeneration;
|
||||
bool mLocked;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_CAMERA_ICAMERACONTROL_H
|
||||
#define DOM_CAMERA_ICAMERACONTROL_H
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "prtypes.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIDOMCameraManager.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
class DOMCameraPreview;
|
||||
|
||||
class ICameraControl
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ICameraControl)
|
||||
|
||||
virtual nsresult GetPreviewStream(CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult StartPreview(DOMCameraPreview* aDOMPreview) = 0;
|
||||
virtual void StopPreview() = 0;
|
||||
virtual nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult StartRecording(CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult StopRecording() = 0;
|
||||
|
||||
virtual nsresult Set(uint32_t aKey, const nsAString& aValue) = 0;
|
||||
virtual nsresult Get(uint32_t aKey, nsAString& aValue) = 0;
|
||||
virtual nsresult Set(uint32_t aKey, double aValue) = 0;
|
||||
virtual nsresult Get(uint32_t aKey, double* aValue) = 0;
|
||||
virtual nsresult Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit) = 0;
|
||||
virtual nsresult Get(JSContext* aCx, uint32_t aKey, JS::Value* aValue) = 0;
|
||||
virtual nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue) = 0;
|
||||
virtual nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue) = 0;
|
||||
|
||||
virtual const char* GetParameter(const char* aKey) = 0;
|
||||
virtual const char* GetParameterConstChar(uint32_t aKey) = 0;
|
||||
virtual double GetParameterDouble(uint32_t aKey) = 0;
|
||||
virtual void GetParameter(uint32_t aKey, nsTArray<CameraRegion>& aRegions) = 0;
|
||||
virtual void SetParameter(const char* aKey, const char* aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, const char* aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, double aValue) = 0;
|
||||
virtual void SetParameter(uint32_t aKey, const nsTArray<CameraRegion>& aRegions) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~ICameraControl() { }
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_CAMERA_ICAMERACONTROL_H
|
|
@ -19,8 +19,10 @@ include $(topsrcdir)/dom/dom-config.mk
|
|||
|
||||
CPPSRCS = \
|
||||
DOMCameraManager.cpp \
|
||||
CameraControl.cpp \
|
||||
CameraPreview.cpp \
|
||||
DOMCameraControl.cpp \
|
||||
DOMCameraPreview.cpp \
|
||||
DOMCameraCapabilities.cpp \
|
||||
CameraControlImpl.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_B2G_CAMERA),1)
|
||||
|
@ -28,15 +30,12 @@ CPPSRCS += \
|
|||
GonkCameraManager.cpp \
|
||||
GonkCameraControl.cpp \
|
||||
GonkCameraHwMgr.cpp \
|
||||
GonkCameraPreview.cpp \
|
||||
GonkNativeWindow.cpp \
|
||||
GonkCameraCapabilities.cpp \
|
||||
$(NULL)
|
||||
else
|
||||
CPPSRCS += \
|
||||
FallbackCameraManager.cpp \
|
||||
FallbackCameraControl.cpp \
|
||||
FallbackCameraCapabilities.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ interface nsICameraErrorCallback : nsISupports
|
|||
attributes here affect the preview, any pictures taken, and/or
|
||||
any video recorded by the camera.
|
||||
*/
|
||||
[scriptable, uuid(3066c884-d2c3-4477-847d-08ea1c2d188a)]
|
||||
[scriptable, uuid(b8949e5c-55b0-49dd-99a9-68d11342915a)]
|
||||
interface nsICameraControl : nsISupports
|
||||
{
|
||||
readonly attribute nsICameraCapabilities capabilities;
|
||||
|
@ -313,6 +313,10 @@ interface nsICameraControl : nsISupports
|
|||
*/
|
||||
[implicit_jscontext]
|
||||
void getPreviewStream(in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
|
||||
/* call in or after the takePicture() onSuccess callback to
|
||||
resume the camera preview stream. */
|
||||
void resumePreview();
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(a267afbc-d91c-413a-8de5-0b94aecffa3e)]
|
||||
|
|
Загрузка…
Ссылка в новой задаче