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:
Mike Habicher 2012-09-04 21:01:56 -04:00
Родитель 9d666dfae5
Коммит 6ae700c29b
31 изменённых файлов: 2040 добавлений и 1533 удалений

Просмотреть файл

@ -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 = &regionArray[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 = &regionArray[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)]