gecko/dom/camera/CameraControlImpl.cpp

247 lines
6.5 KiB
C++

/* 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);
}
bool
CameraControlImpl::ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder)
{
if (!mDOMPreview) {
return false;
}
return 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;
}