Bug 1139027 - Permit running of camera mochitests on B2G desktop. r=mikeh

This commit is contained in:
Andrew Osmond 2015-03-10 19:39:49 -04:00
parent f4face05d6
commit a0bbbdd643
29 changed files with 1110 additions and 611 deletions

View File

@ -31,6 +31,8 @@ uint32_t CameraPreferences::sPrefCameraControlLowMemoryThresholdMB = 0;
bool CameraPreferences::sPrefCameraParametersIsLowMemory = false;
bool CameraPreferences::sPrefCameraParametersPermission = false;
#ifdef MOZ_WIDGET_GONK
StaticRefPtr<CameraPreferences> CameraPreferences::sObserver;
@ -113,6 +115,11 @@ CameraPreferences::Pref CameraPreferences::sPrefs[] = {
kPrefValueIsCString,
{ &sPrefHardwareTest }
},
{
"camera.control.test.permission",
kPrefValueIsBoolean,
{ &sPrefCameraParametersPermission }
},
#ifdef MOZ_B2G
{
"camera.control.test.hardware.gonk.parameters",

View File

@ -80,6 +80,8 @@ protected:
static bool sPrefCameraParametersIsLowMemory;
static bool sPrefCameraParametersPermission;
#ifdef MOZ_WIDGET_GONK
static StaticRefPtr<CameraPreferences> sObserver;

View File

@ -16,6 +16,7 @@
#include "DOMCameraControl.h"
#include "nsDOMClassInfo.h"
#include "CameraCommon.h"
#include "CameraPreferences.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/PermissionMessageUtils.h"
@ -298,7 +299,11 @@ nsDOMCameraManager::GetCamera(const nsAString& aCamera,
// which gets us a performance win.
uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
principal->GetAppStatus(&status);
if (status == nsIPrincipal::APP_STATUS_CERTIFIED && CheckPermission(mWindow)) {
// Unprivileged mochitests always fail the dispatched permission check,
// even if permission to the camera has been granted.
bool immediateCheck = false;
CameraPreferences::GetPref("camera.control.test.permission", immediateCheck);
if ((status == nsIPrincipal::APP_STATUS_CERTIFIED || immediateCheck) && CheckPermission(mWindow)) {
PermissionAllowed(cameraId, aInitialConfig, promise);
return promise.forget();
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2015 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "FallbackCameraPlatform.h"
using namespace android;
MediaProfiles* MediaProfiles::sMediaProfiles = nullptr;
const char CameraParameters::KEY_PREVIEW_SIZE[] = "preview-size";
const char CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES[] = "preview-size-values";
const char CameraParameters::KEY_PREVIEW_FORMAT[] = "preview-format";
const char CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS[] = "preview-format-values";
const char CameraParameters::KEY_PREVIEW_FRAME_RATE[] = "preview-frame-rate";
const char CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES[] = "preview-frame-rate-values";
const char CameraParameters::KEY_PREVIEW_FPS_RANGE[] = "preview-fps-range";
const char CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE[] = "preview-fps-range-values";
const char CameraParameters::KEY_PICTURE_SIZE[] = "picture-size";
const char CameraParameters::KEY_SUPPORTED_PICTURE_SIZES[] = "picture-size-values";
const char CameraParameters::KEY_PICTURE_FORMAT[] = "picture-format";
const char CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS[] = "picture-format-values";
const char CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH[] = "jpeg-thumbnail-width";
const char CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT[] = "jpeg-thumbnail-height";
const char CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES[] = "jpeg-thumbnail-size-values";
const char CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY[] = "jpeg-thumbnail-quality";
const char CameraParameters::KEY_JPEG_QUALITY[] = "jpeg-quality";
const char CameraParameters::KEY_ROTATION[] = "rotation";
const char CameraParameters::KEY_GPS_LATITUDE[] = "gps-latitude";
const char CameraParameters::KEY_GPS_LONGITUDE[] = "gps-longitude";
const char CameraParameters::KEY_GPS_ALTITUDE[] = "gps-altitude";
const char CameraParameters::KEY_GPS_TIMESTAMP[] = "gps-timestamp";
const char CameraParameters::KEY_GPS_PROCESSING_METHOD[] = "gps-processing-method";
const char CameraParameters::KEY_WHITE_BALANCE[] = "whitebalance";
const char CameraParameters::KEY_SUPPORTED_WHITE_BALANCE[] = "whitebalance-values";
const char CameraParameters::KEY_EFFECT[] = "effect";
const char CameraParameters::KEY_SUPPORTED_EFFECTS[] = "effect-values";
const char CameraParameters::KEY_ANTIBANDING[] = "antibanding";
const char CameraParameters::KEY_SUPPORTED_ANTIBANDING[] = "antibanding-values";
const char CameraParameters::KEY_SCENE_MODE[] = "scene-mode";
const char CameraParameters::KEY_SUPPORTED_SCENE_MODES[] = "scene-mode-values";
const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode";
const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values";
const char CameraParameters::KEY_MAX_NUM_FOCUS_AREAS[] = "max-num-focus-areas";
const char CameraParameters::KEY_FOCUS_AREAS[] = "focus-areas";
const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
const char CameraParameters::KEY_EXPOSURE_COMPENSATION[] = "exposure-compensation";
const char CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION[] = "max-exposure-compensation";
const char CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION[] = "min-exposure-compensation";
const char CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP[] = "exposure-compensation-step";
const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK[] = "auto-exposure-lock";
const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[] = "auto-exposure-lock-supported";
const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK[] = "auto-whitebalance-lock";
const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED[] = "auto-whitebalance-lock-supported";
const char CameraParameters::KEY_MAX_NUM_METERING_AREAS[] = "max-num-metering-areas";
const char CameraParameters::KEY_METERING_AREAS[] = "metering-areas";
const char CameraParameters::KEY_ZOOM[] = "zoom";
const char CameraParameters::KEY_MAX_ZOOM[] = "max-zoom";
const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios";
const char CameraParameters::KEY_ZOOM_SUPPORTED[] = "zoom-supported";
const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supported";
const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances";
const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format";
const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw";
const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
const char CameraParameters::KEY_RECORDING_HINT[] = "recording-hint";
const char CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED[] = "video-snapshot-supported";
const char CameraParameters::KEY_VIDEO_STABILIZATION[] = "video-stabilization";
const char CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED[] = "video-stabilization-supported";
const char CameraParameters::KEY_LIGHTFX[] = "light-fx";

View File

@ -0,0 +1,300 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2015 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DOM_CAMERA_FALLBACKCAMERAPLATFORM_H
#define DOM_CAMERA_FALLBACKCAMERAPLATFORM_H
#include <inttypes.h>
#include <string.h>
typedef struct {
int32_t id;
int32_t score;
int32_t rect[4];
int32_t left_eye[2];
int32_t right_eye[2];
int32_t mouth[2];
} camera_face_t;
typedef struct {
uint32_t number_of_faces;
camera_face_t* faces;
} camera_frame_metadata_t;
namespace android {
enum camcorder_quality {
CAMCORDER_QUALITY_LOW,
CAMCORDER_QUALITY_HIGH,
CAMCORDER_QUALITY_QCIF,
CAMCORDER_QUALITY_CIF,
CAMCORDER_QUALITY_480P,
CAMCORDER_QUALITY_720P,
CAMCORDER_QUALITY_1080P,
CAMCORDER_QUALITY_QVGA,
CAMCORDER_QUALITY_VGA,
CAMCORDER_QUALITY_LIST_START = CAMCORDER_QUALITY_LOW,
CAMCORDER_QUALITY_LIST_END = CAMCORDER_QUALITY_VGA
};
enum output_format {
OUTPUT_FORMAT_THREE_GPP,
OUTPUT_FORMAT_MPEG_4
};
enum video_encoder {
VIDEO_ENCODER_H263,
VIDEO_ENCODER_H264,
VIDEO_ENCODER_MPEG_4_SP
};
enum audio_encoder {
AUDIO_ENCODER_AMR_WB,
AUDIO_ENCODER_AMR_NB,
AUDIO_ENCODER_AAC
};
template <class T>
class sp MOZ_FINAL
{
public:
sp()
: mPtr(nullptr)
{ }
sp(T *aPtr)
: mPtr(aPtr)
{ }
virtual ~sp() { }
T* get() const { return mPtr; }
void clear() { mPtr = nullptr; }
T* operator->() const { return get(); }
private:
nsRefPtr<T> mPtr;
};
typedef uint64_t nsecs_t;
enum error_t {
OK = 0,
UNKNOWN_ERROR,
INVALID_OPERATION
};
enum camera_msg_t {
CAMERA_MSG_SHUTTER,
CAMERA_MSG_COMPRESSED_IMAGE
};
class String8 MOZ_FINAL
{
public:
String8() { }
String8(const char* aData) { mData.AssignASCII(aData); }
virtual ~String8() { }
const char* string() const { return mData.Data(); }
private:
nsCString mData;
};
enum camera_facing_t {
CAMERA_FACING_BACK,
CAMERA_FACING_FRONT
};
struct CameraInfo {
camera_facing_t facing;
};
class Camera MOZ_FINAL : public nsISupports
{
public:
NS_DECL_ISUPPORTS;
void disconnect() { }
String8 getParameters() { return String8(); }
int setParameters(const String8& aParams) { return UNKNOWN_ERROR; }
int storeMetaDataInBuffers(bool aEnabled) { return UNKNOWN_ERROR; }
int autoFocus() { return UNKNOWN_ERROR; }
int cancelAutoFocus() { return UNKNOWN_ERROR; }
int takePicture(uint32_t flags) { return UNKNOWN_ERROR; }
int startPreview() { return UNKNOWN_ERROR; }
int stopPreview() { return UNKNOWN_ERROR; }
int startRecording() { return UNKNOWN_ERROR; }
int stopRecording() { return UNKNOWN_ERROR; }
int startFaceDetection() { return UNKNOWN_ERROR; }
int stopFaceDetection() { return UNKNOWN_ERROR; }
static int32_t getNumberOfCameras() { return 2; }
static int getCameraInfo(int32_t aDevice, CameraInfo* aInfo)
{
switch (aDevice) {
case 0:
aInfo->facing = CAMERA_FACING_BACK;
break;
case 1:
aInfo->facing = CAMERA_FACING_FRONT;
break;
default:
return UNKNOWN_ERROR;
}
return OK;
}
protected:
Camera() { }
virtual ~Camera() { }
private:
Camera(const Camera&) = delete;
Camera& operator=(const Camera&) = delete;
};
class CameraParameters MOZ_FINAL
{
public:
static const char KEY_PREVIEW_SIZE[];
static const char KEY_SUPPORTED_PREVIEW_SIZES[];
static const char KEY_PREVIEW_FPS_RANGE[];
static const char KEY_SUPPORTED_PREVIEW_FPS_RANGE[];
static const char KEY_PREVIEW_FORMAT[];
static const char KEY_SUPPORTED_PREVIEW_FORMATS[];
static const char KEY_PREVIEW_FRAME_RATE[];
static const char KEY_SUPPORTED_PREVIEW_FRAME_RATES[];
static const char KEY_PICTURE_SIZE[];
static const char KEY_SUPPORTED_PICTURE_SIZES[];
static const char KEY_PICTURE_FORMAT[];
static const char KEY_SUPPORTED_PICTURE_FORMATS[];
static const char KEY_JPEG_THUMBNAIL_WIDTH[];
static const char KEY_JPEG_THUMBNAIL_HEIGHT[];
static const char KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES[];
static const char KEY_JPEG_THUMBNAIL_QUALITY[];
static const char KEY_JPEG_QUALITY[];
static const char KEY_ROTATION[];
static const char KEY_GPS_LATITUDE[];
static const char KEY_GPS_LONGITUDE[];
static const char KEY_GPS_ALTITUDE[];
static const char KEY_GPS_TIMESTAMP[];
static const char KEY_GPS_PROCESSING_METHOD[];
static const char KEY_WHITE_BALANCE[];
static const char KEY_SUPPORTED_WHITE_BALANCE[];
static const char KEY_EFFECT[];
static const char KEY_SUPPORTED_EFFECTS[];
static const char KEY_ANTIBANDING[];
static const char KEY_SUPPORTED_ANTIBANDING[];
static const char KEY_SCENE_MODE[];
static const char KEY_SUPPORTED_SCENE_MODES[];
static const char KEY_FLASH_MODE[];
static const char KEY_SUPPORTED_FLASH_MODES[];
static const char KEY_FOCUS_MODE[];
static const char KEY_SUPPORTED_FOCUS_MODES[];
static const char KEY_MAX_NUM_FOCUS_AREAS[];
static const char KEY_FOCUS_AREAS[];
static const char KEY_FOCAL_LENGTH[];
static const char KEY_HORIZONTAL_VIEW_ANGLE[];
static const char KEY_VERTICAL_VIEW_ANGLE[];
static const char KEY_EXPOSURE_COMPENSATION[];
static const char KEY_MAX_EXPOSURE_COMPENSATION[];
static const char KEY_MIN_EXPOSURE_COMPENSATION[];
static const char KEY_EXPOSURE_COMPENSATION_STEP[];
static const char KEY_AUTO_EXPOSURE_LOCK[];
static const char KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[];
static const char KEY_AUTO_WHITEBALANCE_LOCK[];
static const char KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED[];
static const char KEY_MAX_NUM_METERING_AREAS[];
static const char KEY_METERING_AREAS[];
static const char KEY_ZOOM[];
static const char KEY_MAX_ZOOM[];
static const char KEY_ZOOM_RATIOS[];
static const char KEY_ZOOM_SUPPORTED[];
static const char KEY_SMOOTH_ZOOM_SUPPORTED[];
static const char KEY_FOCUS_DISTANCES[];
static const char KEY_VIDEO_SIZE[];
static const char KEY_SUPPORTED_VIDEO_SIZES[];
static const char KEY_MAX_NUM_DETECTED_FACES_HW[];
static const char KEY_MAX_NUM_DETECTED_FACES_SW[];
static const char KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[];
static const char KEY_VIDEO_FRAME_FORMAT[];
static const char KEY_RECORDING_HINT[];
static const char KEY_VIDEO_SNAPSHOT_SUPPORTED[];
static const char KEY_VIDEO_STABILIZATION[];
static const char KEY_VIDEO_STABILIZATION_SUPPORTED[];
static const char KEY_LIGHTFX[];
};
class MediaProfiles MOZ_FINAL
{
public:
static MediaProfiles* getInstance() {
if (!sMediaProfiles) {
sMediaProfiles = new MediaProfiles();
}
return sMediaProfiles;
}
bool hasCamcorderProfile(int aCameraId, camcorder_quality aQuality) const {
switch (aQuality) {
case CAMCORDER_QUALITY_LOW:
case CAMCORDER_QUALITY_HIGH:
case CAMCORDER_QUALITY_QVGA:
case CAMCORDER_QUALITY_VGA:
return true;
default:
break;
}
return false;
}
int getCamcorderProfileParamByName(const char* aParameter, int aCameraId, camcorder_quality aQuality) const {
switch (aQuality) {
case CAMCORDER_QUALITY_LOW:
case CAMCORDER_QUALITY_QVGA:
if (strcmp(aParameter, "vid.width") == 0) {
return 320;
} else if (strcmp(aParameter, "vid.height") == 0) {
return 240;
}
return 0;
case CAMCORDER_QUALITY_HIGH:
case CAMCORDER_QUALITY_VGA:
if (strcmp(aParameter, "vid.width") == 0) {
return 640;
} else if (strcmp(aParameter, "vid.height") == 0) {
return 480;
}
return 0;
default:
break;
}
return -1;
}
protected:
MediaProfiles() { }
virtual ~MediaProfiles() { }
private:
MediaProfiles(const MediaProfiles&) = delete;
MediaProfiles& operator=(const MediaProfiles&) = delete;
static MediaProfiles* sMediaProfiles;
};
}
#endif

View File

@ -22,25 +22,24 @@
#include <errno.h>
#include <libgen.h>
#include "base/basictypes.h"
#include "camera/CameraParameters.h"
#include "Layers.h"
#ifdef MOZ_WIDGET_GONK
#include <media/mediaplayer.h>
#include <media/MediaProfiles.h>
#include "GrallocImages.h"
#endif
#include "nsCOMPtr.h"
#include "nsMemory.h"
#include "nsThread.h"
#include <media/MediaProfiles.h>
#include "mozilla/FileUtils.h"
#include "mozilla/Services.h"
#include "mozilla/unused.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "nsAlgorithm.h"
#include <media/mediaplayer.h>
#include "nsPrintfCString.h"
#include "nsIObserverService.h"
#include "nsIVolume.h"
#include "nsIVolumeService.h"
#include "AutoRwLock.h"
#include "GonkCameraHwMgr.h"
#include "GonkRecorderProfiles.h"
#include "GrallocImages.h"
#include "CameraCommon.h"
#include "GonkCameraParameters.h"
#include "DeviceStorageFileDescriptor.h"
@ -71,7 +70,9 @@ nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId)
, mAutoFlashModeOverridden(false)
, mSeparateVideoAndPreviewSizesSupported(false)
, mDeferConfigUpdate(0)
#ifdef MOZ_WIDGET_GONK
, mRecorder(nullptr)
#endif
, mRecorderMonitor("GonkCameraControl::mRecorder.Monitor")
, mVideoFile(nullptr)
, mReentrantMonitor("GonkCameraControl::OnTakePicture.Monitor")
@ -1165,7 +1166,9 @@ nsGonkCameraControl::StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescri
ReentrantMonitorAutoEnter mon(mRecorderMonitor);
NS_ENSURE_TRUE(!mCurrentConfiguration.mRecorderProfile.IsEmpty(), NS_ERROR_NOT_INITIALIZED);
#ifdef MOZ_WIDGET_GONK
NS_ENSURE_FALSE(mRecorder, NS_ERROR_FAILURE);
#endif
/**
* Get the base path from device storage and append the app-specified
@ -1212,6 +1215,7 @@ nsGonkCameraControl::StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescri
return rv;
}
#ifdef MOZ_WIDGET_GONK
if (mRecorder->start() != OK) {
DOM_CAMERA_LOGE("mRecorder->start() failed\n");
// important: we MUST destroy the recorder if start() fails!
@ -1222,6 +1226,7 @@ nsGonkCameraControl::StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescri
}
return NS_ERROR_FAILURE;
}
#endif
OnRecorderStateChange(CameraControlListener::kRecorderStarted);
return NS_OK;
@ -1255,6 +1260,7 @@ nsGonkCameraControl::StopRecordingImpl()
ReentrantMonitorAutoEnter mon(mRecorderMonitor);
#ifdef MOZ_WIDGET_GONK
// nothing to do if we have no mRecorder
if (!mRecorder) {
return NS_OK;
@ -1277,6 +1283,9 @@ nsGonkCameraControl::StopRecordingImpl()
// notify DeviceStorage that the new video file is closed and ready
return NS_DispatchToMainThread(new RecordingComplete(mVideoFile));
#else
return NS_OK;
#endif
}
nsresult
@ -1697,6 +1706,7 @@ nsGonkCameraControl::SetVideoConfiguration(const Configuration& aConfig)
return NS_OK;
}
#ifdef MOZ_WIDGET_GONK
class GonkRecorderListener : public IMediaRecorderClient
{
public:
@ -1843,6 +1853,7 @@ nsGonkCameraControl::OnRecorderEvent(int msg, int ext1, int ext2)
// All unhandled cases wind up here
DOM_CAMERA_LOGW("recorder-event : unhandled: msg=%d, ext1=%d, ext2=%d\n", msg, ext1, ext2);
}
#endif
nsresult
nsGonkCameraControl::SetupRecording(int aFd, int aRotation,
@ -1851,6 +1862,7 @@ nsGonkCameraControl::SetupRecording(int aFd, int aRotation,
{
RETURN_IF_NO_CAMERA_HW();
#ifdef MOZ_WIDGET_GONK
// choosing a size big enough to hold the params
const size_t SIZE = 256;
char buffer[SIZE];
@ -1911,6 +1923,7 @@ nsGonkCameraControl::SetupRecording(int aFd, int aRotation,
// recording API needs file descriptor of output file
CHECK_SETARG_RETURN(mRecorder->setOutputFile(aFd, 0, 0), NS_ERROR_FAILURE);
CHECK_SETARG_RETURN(mRecorder->prepare(), NS_ERROR_FAILURE);
#endif
return NS_OK;
}
@ -2046,6 +2059,7 @@ nsGonkCameraControl::OnRateLimitPreview(bool aLimit)
void
nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer)
{
#ifdef MOZ_WIDGET_GONK
nsRefPtr<Image> frame = mImageContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
GrallocImage* videoImage = static_cast<GrallocImage*>(frame.get());
@ -2058,6 +2072,7 @@ nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer)
OnNewPreviewFrame(frame, mCurrentConfiguration.mPreviewSize.width,
mCurrentConfiguration.mPreviewSize.height);
#endif
}
void

View File

@ -19,18 +19,24 @@
#include "base/basictypes.h"
#include "nsRefPtrHashtable.h"
#include <media/MediaProfiles.h>
#include "mozilla/ReentrantMonitor.h"
#include "DeviceStorage.h"
#include "CameraControlImpl.h"
#include "CameraCommon.h"
#include "GonkRecorder.h"
#include "GonkCameraHwMgr.h"
#include "GonkCameraParameters.h"
#ifdef MOZ_WIDGET_GONK
#include <media/MediaProfiles.h>
#include <camera/Camera.h>
#include "GonkRecorder.h"
#else
#include "FallbackCameraPlatform.h"
#endif
namespace android {
class GonkCameraHardware;
class MediaProfiles;
class GonkRecorder;
class GonkCameraSource;
}
@ -56,7 +62,9 @@ public:
void OnTakePictureError();
void OnRateLimitPreview(bool aLimit);
void OnNewPreviewFrame(layers::TextureClient* aBuffer);
#ifdef MOZ_WIDGET_GONK
void OnRecorderEvent(int msg, int ext1, int ext2);
#endif
void OnSystemError(CameraControlListener::SystemContext aWhere, nsresult aError);
// See ICameraControl.h for getter/setter return values.
@ -177,7 +185,9 @@ protected:
nsRefPtr<mozilla::layers::ImageContainer> mImageContainer;
#ifdef MOZ_WIDGET_GONK
nsRefPtr<android::GonkRecorder> mRecorder;
#endif
// Touching mRecorder happens inside this monitor because the destructor
// can run on any thread, and we need to be able to clean up properly if
// GonkCameraControl goes away.

View File

@ -17,8 +17,11 @@
#include "GonkCameraHwMgr.h"
#include "TestGonkCameraHardware.h"
#ifdef MOZ_WIDGET_GONK
#include <binder/IPCThreadState.h>
#include <sys/system_properties.h>
#include "GonkNativeWindow.h"
#endif
#include "base/basictypes.h"
#include "nsDebug.h"
@ -29,19 +32,26 @@
#include "GonkBufferQueueProducer.h"
#endif
#include "GonkCameraControl.h"
#include "GonkNativeWindow.h"
#include "CameraCommon.h"
using namespace mozilla;
using namespace mozilla::layers;
using namespace android;
#ifndef MOZ_WIDGET_GONK
NS_IMPL_ISUPPORTS0(GonkCameraHardware);
NS_IMPL_ISUPPORTS0(android::Camera);
#endif
GonkCameraHardware::GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId, const sp<Camera>& aCamera)
: mCameraId(aCameraId)
, mClosing(false)
, mNumFrames(0)
#ifdef MOZ_WIDGET_GONK
, mCamera(aCamera)
#endif
, mTarget(aTarget)
, mRawSensorOrientation(0)
, mSensorOrientation(0)
{
DOM_CAMERA_LOGT("%s:%d : this=%p (aTarget=%p)\n", __func__, __LINE__, (void*)this, (void*)aTarget);
@ -53,6 +63,7 @@ GonkCameraHardware::OnRateLimitPreview(bool aLimit)
::OnRateLimitPreview(mTarget, aLimit);
}
#ifdef MOZ_WIDGET_GONK
void
GonkCameraHardware::OnNewFrame()
{
@ -150,12 +161,14 @@ GonkCameraHardware::postDataTimestamp(nsecs_t aTimestamp, int32_t aMsgType, cons
mCamera->releaseRecordingFrame(aDataPtr);
}
}
#endif
nsresult
GonkCameraHardware::Init()
{
DOM_CAMERA_LOGT("%s: this=%p\n", __func__, (void* )this);
#ifdef MOZ_WIDGET_GONK
CameraInfo info;
int rv = Camera::getCameraInfo(mCameraId, &info);
if (rv != 0) {
@ -184,8 +197,6 @@ GonkCameraHardware::Init()
// Disable shutter sound in android CameraService because gaia camera app will play it
mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
#if defined(MOZ_WIDGET_GONK)
#if ANDROID_VERSION >= 21
sp<IGraphicBufferProducer> producer;
sp<IGonkGraphicBufferConsumer> consumer;
@ -231,10 +242,12 @@ GonkCameraHardware::Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCam
CameraPreferences::GetPref("camera.control.test.enabled", test);
if (!test.EqualsASCII("hardware")) {
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
#ifdef MOZ_WIDGET_GONK
#if ANDROID_VERSION >= 18
camera = Camera::connect(aCameraId, /* clientPackageName */String16("gonk.camera"), Camera::USE_CALLING_UID);
#else
camera = Camera::connect(aCameraId);
#endif
#endif
if (camera.get() == nullptr) {
@ -270,21 +283,25 @@ GonkCameraHardware::Close()
mCamera->stopPreview();
mCamera->disconnect();
}
mCamera.clear();
#ifdef MOZ_WIDGET_GONK
if (mNativeWindow.get()) {
mNativeWindow->abandon();
}
mCamera.clear();
mNativeWindow.clear();
// Ensure that ICamera's destructor is actually executed
IPCThreadState::self()->flushCommands();
#endif
}
GonkCameraHardware::~GonkCameraHardware()
{
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, (void*)this);
mCamera.clear();
#ifdef MOZ_WIDGET_GONK
mNativeWindow.clear();
#endif
}
int
@ -370,13 +387,6 @@ GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
return mCamera->setParameters(s);
}
int
GonkCameraHardware::PushParameters(const CameraParameters& aParams)
{
String8 s = aParams.flatten();
return mCamera->setParameters(s);
}
nsresult
GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
{
@ -384,12 +394,21 @@ GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
return aParams.Unflatten(s);
}
#ifdef MOZ_WIDGET_GONK
int
GonkCameraHardware::PushParameters(const CameraParameters& aParams)
{
String8 s = aParams.flatten();
return mCamera->setParameters(s);
}
void
GonkCameraHardware::PullParameters(CameraParameters& aParams)
{
const String8 s = mCamera->getParameters();
aParams.unflatten(s);
}
#endif
int
GonkCameraHardware::StartPreview()
@ -426,6 +445,7 @@ GonkCameraHardware::StopRecording()
return OK;
}
#ifdef MOZ_WIDGET_GONK
int
GonkCameraHardware::SetListener(const sp<GonkCameraListener>& aListener)
{
@ -438,6 +458,7 @@ GonkCameraHardware::ReleaseRecordingFrame(const sp<IMemory>& aFrame)
{
mCamera->releaseRecordingFrame(aFrame);
}
#endif
int
GonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled)

View File

@ -17,18 +17,21 @@
#ifndef DOM_CAMERA_GONKCAMERAHWMGR_H
#define DOM_CAMERA_GONKCAMERAHWMGR_H
#include "GonkCameraControl.h"
#include "CameraCommon.h"
#include "GonkCameraParameters.h"
#include "mozilla/ReentrantMonitor.h"
#ifdef MOZ_WIDGET_GONK
#include <binder/IMemory.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
#include <utils/threads.h>
#include "GonkCameraControl.h"
#include "CameraCommon.h"
#include "GonkCameraListener.h"
#include "GonkNativeWindow.h"
#include "GonkCameraParameters.h"
#include "mozilla/ReentrantMonitor.h"
#else
#include "FallbackCameraPlatform.h"
#endif
namespace mozilla {
class nsGonkCameraControl;
@ -37,9 +40,18 @@ namespace mozilla {
namespace android {
class GonkCameraHardware : public GonkNativeWindowNewFrameCallback
, public CameraListener
class GonkCameraHardware
#ifdef MOZ_WIDGET_GONK
: public GonkNativeWindowNewFrameCallback
, public CameraListener
#else
: public nsISupports
#endif
{
#ifndef MOZ_WIDGET_GONK
NS_DECL_ISUPPORTS
#endif
protected:
GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId, const sp<Camera>& aCamera);
virtual ~GonkCameraHardware();
@ -57,6 +69,7 @@ public:
virtual void OnRateLimitPreview(bool aLimit);
#ifdef MOZ_WIDGET_GONK
// derived from GonkNativeWindowNewFrameCallback
virtual void OnNewFrame() MOZ_OVERRIDE;
@ -64,6 +77,7 @@ public:
virtual void notify(int32_t aMsgType, int32_t ext1, int32_t ext2);
virtual void postData(int32_t aMsgType, const sp<IMemory>& aDataPtr, camera_frame_metadata_t* metadata);
virtual void postDataTimestamp(nsecs_t aTimestamp, int32_t aMsgType, const sp<IMemory>& aDataPtr);
#endif
/**
* The physical orientation of the camera sensor: 0, 90, 180, or 270.
@ -103,13 +117,15 @@ public:
virtual int StartPreview();
virtual void StopPreview();
virtual int PushParameters(const mozilla::GonkCameraParameters& aParams);
virtual int PushParameters(const CameraParameters& aParams);
virtual nsresult PullParameters(mozilla::GonkCameraParameters& aParams);
#ifdef MOZ_WIDGET_GONK
virtual int PushParameters(const CameraParameters& aParams);
virtual void PullParameters(CameraParameters& aParams);
virtual int StartRecording();
virtual int StopRecording();
virtual int SetListener(const sp<GonkCameraListener>& aListener);
virtual void ReleaseRecordingFrame(const sp<IMemory>& aFrame);
#endif
virtual int StartRecording();
virtual int StopRecording();
virtual int StoreMetaDataInBuffers(bool aEnabled);
protected:
@ -118,8 +134,10 @@ protected:
uint32_t mNumFrames;
sp<Camera> mCamera;
mozilla::nsGonkCameraControl* mTarget;
#ifdef MOZ_WIDGET_GONK
sp<GonkNativeWindow> mNativeWindow;
sp<GonkCameraListener> mListener;
#endif
int mRawSensorOrientation;
int mSensorOrientation;

View File

@ -15,14 +15,17 @@
*/
#include "ICameraControl.h"
#include <camera/Camera.h>
#include "CameraCommon.h"
#include "GonkCameraControl.h"
#include "CameraPreferences.h"
#include "TestGonkCameraControl.h"
#ifdef MOZ_WIDGET_GONK
#include <camera/Camera.h>
#else
#include "FallbackCameraPlatform.h"
#endif
using namespace mozilla;
// From ICameraControl, gonk-specific management functions

View File

@ -15,12 +15,12 @@
*/
#include "GonkCameraParameters.h"
#include "camera/CameraParameters.h"
#include "CameraPreferences.h"
#include "ICameraControl.h"
#include "CameraCommon.h"
#include "mozilla/Hal.h"
#include "nsDataHashtable.h"
#include "nsPrintfCString.h"
using namespace mozilla;
using namespace android;
@ -52,13 +52,13 @@ GonkCameraParameters::IsLowMemoryPlatform()
}
const char*
GonkCameraParameters::Parameters::FindVendorSpecificKey(const char* aPotentialKeys[],
size_t aPotentialKeyCount)
GonkCameraParameters::FindVendorSpecificKey(const char* aPotentialKeys[],
size_t aPotentialKeyCount)
{
const char* val;
for (size_t i = 0; i < aPotentialKeyCount; ++i) {
get(aPotentialKeys[i], val);
GetImpl(aPotentialKeys[i], val);
if (val) {
// We received a value (potentially an empty-string one),
// which indicates that this key exists.
@ -69,59 +69,122 @@ GonkCameraParameters::Parameters::FindVendorSpecificKey(const char* aPotentialKe
return nullptr;
}
/* static */ PLDHashOperator
GonkCameraParameters::EnumerateFlatten(const nsACString& aKey,
nsCString* aValue,
void* aUserArg)
{
nsCString* data = static_cast<nsCString*>(aUserArg);
if (!data->IsEmpty()) {
data->Append(';');
}
data->Append(aKey);
data->Append('=');
data->Append(*aValue);
return PL_DHASH_NEXT;
}
String8
GonkCameraParameters::Flatten() const
{
MutexAutoLock lock(mLock);
nsCString data;
mParams.EnumerateRead(EnumerateFlatten, static_cast<void*>(&data));
return String8(data.Data());
}
nsresult
GonkCameraParameters::Unflatten(const String8& aFlatParameters)
{
MutexAutoLock lock(mLock);
mParams.Clear();
const char* data = aFlatParameters.string();
while (data && *data) {
const char* pos = strchr(data, '=');
if (!pos) {
break;
}
nsAutoCString key(data, pos - data);
data = pos + 1;
nsCString* value;
pos = strchr(data, ';');
if (pos) {
value = new nsCString(data, pos - data);
data = pos + 1;
} else {
value = new nsCString(data);
data = nullptr;
}
mParams.Put(key, value);
}
if (mInitialized) {
return NS_OK;
}
// We call Initialize() once when the parameter set is first loaded,
// to set up any constant values this class requires internally,
// e.g. the exposure compensation step and limits.
return Initialize();
}
const char*
GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
GonkCameraParameters::GetTextKey(uint32_t aKey)
{
switch (aKey) {
case CAMERA_PARAM_PREVIEWSIZE:
return KEY_PREVIEW_SIZE;
return CameraParameters::KEY_PREVIEW_SIZE;
case CAMERA_PARAM_PREVIEWFORMAT:
return KEY_PREVIEW_FORMAT;
return CameraParameters::KEY_PREVIEW_FORMAT;
case CAMERA_PARAM_PREVIEWFRAMERATE:
return KEY_PREVIEW_FRAME_RATE;
return CameraParameters::KEY_PREVIEW_FRAME_RATE;
case CAMERA_PARAM_EFFECT:
return KEY_EFFECT;
return CameraParameters::KEY_EFFECT;
case CAMERA_PARAM_WHITEBALANCE:
return KEY_WHITE_BALANCE;
return CameraParameters::KEY_WHITE_BALANCE;
case CAMERA_PARAM_SCENEMODE:
return KEY_SCENE_MODE;
return CameraParameters::KEY_SCENE_MODE;
case CAMERA_PARAM_FLASHMODE:
return KEY_FLASH_MODE;
return CameraParameters::KEY_FLASH_MODE;
case CAMERA_PARAM_FOCUSMODE:
return KEY_FOCUS_MODE;
return CameraParameters::KEY_FOCUS_MODE;
case CAMERA_PARAM_ZOOM:
return KEY_ZOOM;
return CameraParameters::KEY_ZOOM;
case CAMERA_PARAM_METERINGAREAS:
return KEY_METERING_AREAS;
return CameraParameters::KEY_METERING_AREAS;
case CAMERA_PARAM_FOCUSAREAS:
return KEY_FOCUS_AREAS;
return CameraParameters::KEY_FOCUS_AREAS;
case CAMERA_PARAM_FOCALLENGTH:
return KEY_FOCAL_LENGTH;
return CameraParameters::KEY_FOCAL_LENGTH;
case CAMERA_PARAM_FOCUSDISTANCENEAR:
return KEY_FOCUS_DISTANCES;
return CameraParameters::KEY_FOCUS_DISTANCES;
case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
return KEY_FOCUS_DISTANCES;
return CameraParameters::KEY_FOCUS_DISTANCES;
case CAMERA_PARAM_FOCUSDISTANCEFAR:
return KEY_FOCUS_DISTANCES;
return CameraParameters::KEY_FOCUS_DISTANCES;
case CAMERA_PARAM_EXPOSURECOMPENSATION:
return KEY_EXPOSURE_COMPENSATION;
return CameraParameters::KEY_EXPOSURE_COMPENSATION;
case CAMERA_PARAM_THUMBNAILQUALITY:
return KEY_JPEG_THUMBNAIL_QUALITY;
return CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY;
case CAMERA_PARAM_PICTURE_SIZE:
return KEY_PICTURE_SIZE;
return CameraParameters::KEY_PICTURE_SIZE;
case CAMERA_PARAM_PICTURE_FILEFORMAT:
return KEY_PICTURE_FORMAT;
return CameraParameters::KEY_PICTURE_FORMAT;
case CAMERA_PARAM_PICTURE_ROTATION:
return KEY_ROTATION;
return CameraParameters::KEY_ROTATION;
case CAMERA_PARAM_PICTURE_DATETIME:
// Not every platform defines a KEY_EXIF_DATETIME;
// Not every platform defines a CameraParameters::EXIF_DATETIME;
// for those that don't, we use the raw string key, and if the platform
// doesn't support it, it will be ignored.
//
// See bug 832494.
return "exif-datetime";
case CAMERA_PARAM_VIDEOSIZE:
return KEY_VIDEO_SIZE;
return CameraParameters::KEY_VIDEO_SIZE;
case CAMERA_PARAM_ISOMODE:
if (!mVendorSpecificKeyIsoMode) {
const char* isoModeKeys[] = {
@ -135,55 +198,55 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
case CAMERA_PARAM_LUMINANCE:
return "luminance-condition";
case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
// Not every platform defines KEY_QC_HDR_NEED_1X;
// Not every platform defines CameraParameters::QC_HDR_NEED_1X;
// for those that don't, we use the raw string key.
return "hdr-need-1x";
case CAMERA_PARAM_RECORDINGHINT:
return KEY_RECORDING_HINT;
return CameraParameters::KEY_RECORDING_HINT;
case CAMERA_PARAM_PICTURE_QUALITY:
return KEY_JPEG_QUALITY;
return CameraParameters::KEY_JPEG_QUALITY;
case CAMERA_PARAM_PREFERRED_PREVIEWSIZE_FOR_VIDEO:
return KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO;
return CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO;
case CAMERA_PARAM_METERINGMODE:
// Not every platform defines KEY_AUTO_EXPOSURE.
// Not every platform defines CameraParameters::AUTO_EXPOSURE.
return "auto-exposure";
case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
return KEY_SUPPORTED_PREVIEW_SIZES;
return CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES;
case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
return KEY_SUPPORTED_PICTURE_SIZES;
return CameraParameters::KEY_SUPPORTED_PICTURE_SIZES;
case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
return KEY_SUPPORTED_VIDEO_SIZES;
return CameraParameters::KEY_SUPPORTED_VIDEO_SIZES;
case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
return KEY_SUPPORTED_PICTURE_FORMATS;
return CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS;
case CAMERA_PARAM_SUPPORTED_WHITEBALANCES:
return KEY_SUPPORTED_WHITE_BALANCE;
return CameraParameters::KEY_SUPPORTED_WHITE_BALANCE;
case CAMERA_PARAM_SUPPORTED_SCENEMODES:
return KEY_SUPPORTED_SCENE_MODES;
return CameraParameters::KEY_SUPPORTED_SCENE_MODES;
case CAMERA_PARAM_SUPPORTED_EFFECTS:
return KEY_SUPPORTED_EFFECTS;
return CameraParameters::KEY_SUPPORTED_EFFECTS;
case CAMERA_PARAM_SUPPORTED_FLASHMODES:
return KEY_SUPPORTED_FLASH_MODES;
return CameraParameters::KEY_SUPPORTED_FLASH_MODES;
case CAMERA_PARAM_SUPPORTED_FOCUSMODES:
return KEY_SUPPORTED_FOCUS_MODES;
return CameraParameters::KEY_SUPPORTED_FOCUS_MODES;
case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS:
return KEY_MAX_NUM_FOCUS_AREAS;
return CameraParameters::KEY_MAX_NUM_FOCUS_AREAS;
case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS:
return KEY_MAX_NUM_METERING_AREAS;
return CameraParameters::KEY_MAX_NUM_METERING_AREAS;
case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
return KEY_MIN_EXPOSURE_COMPENSATION;
return CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION;
case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
return KEY_MAX_EXPOSURE_COMPENSATION;
return CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION;
case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP:
return KEY_EXPOSURE_COMPENSATION_STEP;
return CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP;
case CAMERA_PARAM_SUPPORTED_ZOOM:
return KEY_ZOOM_SUPPORTED;
return CameraParameters::KEY_ZOOM_SUPPORTED;
case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
return KEY_ZOOM_RATIOS;
return CameraParameters::KEY_ZOOM_RATIOS;
case CAMERA_PARAM_SUPPORTED_MAXDETECTEDFACES:
return KEY_MAX_NUM_DETECTED_FACES_HW;
return CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW;
case CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES:
return KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES;
return CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES;
case CAMERA_PARAM_SUPPORTED_ISOMODES:
if (!mVendorSpecificKeySupportedIsoModes) {
const char* supportedIsoModesKeys[] = {
@ -196,7 +259,7 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
}
return mVendorSpecificKeySupportedIsoModes;
case CAMERA_PARAM_SUPPORTED_METERINGMODES:
// Not every platform defines KEY_SUPPORTED_AUTO_EXPOSURE.
// Not every platform defines CameraParameters::SUPPORTED_AUTO_EXPOSURE.
return "auto-exposure-values";
default:
DOM_CAMERA_LOGE("Unhandled camera parameter value %u\n", aKey);
@ -205,26 +268,20 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
}
GonkCameraParameters::GonkCameraParameters()
: mLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraParameters.Lock"))
: mLock("mozilla::camera::GonkCameraParameters")
, mDirty(false)
, mInitialized(false)
, mExposureCompensationStep(0.0)
, mVendorSpecificKeyIsoMode(nullptr)
, mVendorSpecificKeySupportedIsoModes(nullptr)
{
MOZ_COUNT_CTOR(GonkCameraParameters);
if (!mLock) {
MOZ_CRASH("Out of memory getting new PRRWLock");
}
}
GonkCameraParameters::~GonkCameraParameters()
{
MOZ_COUNT_DTOR(GonkCameraParameters);
mIsoModeMap.Clear();
MOZ_ASSERT(mLock, "mLock missing in ~GonkCameraParameters()");
if (mLock) {
PR_DestroyRWLock(mLock);
mLock = nullptr;
}
}
nsresult
@ -278,17 +335,17 @@ GonkCameraParameters::Initialize()
{
nsresult rv;
rv = GetImpl(Parameters::KEY_EXPOSURE_COMPENSATION_STEP, mExposureCompensationStep);
rv = GetImpl(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mExposureCompensationStep);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to initialize exposure compensation step size");
mExposureCompensationStep = 0.0;
}
rv = GetImpl(Parameters::KEY_MIN_EXPOSURE_COMPENSATION, mExposureCompensationMinIndex);
rv = GetImpl(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mExposureCompensationMinIndex);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to initialize minimum exposure compensation index");
mExposureCompensationMinIndex = 0;
}
rv = GetImpl(Parameters::KEY_MAX_EXPOSURE_COMPENSATION, mExposureCompensationMaxIndex);
rv = GetImpl(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mExposureCompensationMaxIndex);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to initialize maximum exposure compensation index");
mExposureCompensationMaxIndex = 0;
@ -425,9 +482,9 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Size& a
// This is a special case--for some reason the thumbnail size
// is accessed as two separate values instead of a tuple.
// XXXmikeh - make this restore the original values on error
rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast<int>(aSize.width));
rv = SetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast<int>(aSize.width));
if (NS_SUCCEEDED(rv)) {
rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast<int>(aSize.height));
rv = SetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast<int>(aSize.height));
}
break;
@ -461,14 +518,14 @@ GonkCameraParameters::GetTranslated(uint32_t aKey, ICameraControl::Size& aSize)
int width;
int height;
rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
rv = GetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
if (NS_FAILED(rv)) {
return rv;
}
if (width < 0) {
return NS_ERROR_NOT_AVAILABLE;
}
rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
rv = GetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
if (NS_FAILED(rv)) {
return rv;
}
@ -572,27 +629,27 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Positio
// Add any specified location information -- we don't care if these fail.
if (!isnan(aPosition.latitude)) {
DOM_CAMERA_LOGI("setting picture latitude to %lf\n", aPosition.latitude);
SetImpl(Parameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get());
SetImpl(CameraParameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get());
} else {
ClearImpl(Parameters::KEY_GPS_LATITUDE);
ClearImpl(CameraParameters::KEY_GPS_LATITUDE);
}
if (!isnan(aPosition.longitude)) {
DOM_CAMERA_LOGI("setting picture longitude to %lf\n", aPosition.longitude);
SetImpl(Parameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get());
SetImpl(CameraParameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get());
} else {
ClearImpl(Parameters::KEY_GPS_LONGITUDE);
ClearImpl(CameraParameters::KEY_GPS_LONGITUDE);
}
if (!isnan(aPosition.altitude)) {
DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aPosition.altitude);
SetImpl(Parameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get());
SetImpl(CameraParameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get());
} else {
ClearImpl(Parameters::KEY_GPS_ALTITUDE);
ClearImpl(CameraParameters::KEY_GPS_ALTITUDE);
}
if (!isnan(aPosition.timestamp)) {
DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aPosition.timestamp);
SetImpl(Parameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get());
SetImpl(CameraParameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get());
} else {
ClearImpl(Parameters::KEY_GPS_TIMESTAMP);
ClearImpl(CameraParameters::KEY_GPS_TIMESTAMP);
}
return NS_OK;

View File

@ -18,14 +18,18 @@
#define DOM_CAMERA_GONKCAMERAPARAMETERS_H
#include <math.h>
#include "camera/CameraParameters.h"
#include "nsTArray.h"
#include "nsString.h"
#include "AutoRwLock.h"
#include "nsPrintfCString.h"
#include "mozilla/Mutex.h"
#include "nsClassHashtable.h"
#include "ICameraControl.h"
#ifdef MOZ_WIDGET_GONK
#include <camera/CameraParameters.h>
#else
#include "FallbackCameraPlatform.h"
#endif
namespace mozilla {
class GonkCameraParameters
@ -44,7 +48,7 @@ public:
template<class T> nsresult
Set(uint32_t aKey, const T& aValue)
{
RwLockAutoEnterWrite lock(mLock);
MutexAutoLock lock(mLock);
nsresult rv = SetTranslated(aKey, aValue);
mDirty = mDirty || NS_SUCCEEDED(rv);
return rv;
@ -53,7 +57,7 @@ public:
template<class T> nsresult
Get(uint32_t aKey, T& aValue)
{
RwLockAutoEnterRead lock(mLock);
MutexAutoLock lock(mLock);
return GetTranslated(aKey, aValue);
}
@ -62,36 +66,17 @@ public:
{
bool dirty;
RwLockAutoEnterWrite lock(mLock);
MutexAutoLock lock(mLock);
dirty = mDirty;
mDirty = false;
return dirty;
}
android::String8
Flatten() const
{
RwLockAutoEnterRead lock(mLock);
return mParams.flatten();
}
nsresult
Unflatten(const android::String8& aFlatParameters)
{
RwLockAutoEnterWrite lock(mLock);
mParams.unflatten(aFlatParameters);
if (mInitialized) {
return NS_OK;
}
// We call Initialize() once when the parameter set is first loaded,
// to set up any constant values this class requires internally,
// e.g. the exposure compensation step and limits.
return Initialize();
}
android::String8 Flatten() const;
nsresult Unflatten(const android::String8& aFlatParameters);
protected:
PRRWLock* mLock;
mutable Mutex mLock;
bool mDirty;
bool mInitialized;
@ -99,55 +84,123 @@ protected:
double mExposureCompensationStep;
int32_t mExposureCompensationMinIndex;
int32_t mExposureCompensationMaxIndex;
const char* mVendorSpecificKeyIsoMode;
const char* mVendorSpecificKeySupportedIsoModes;
nsTArray<int> mZoomRatios;
nsTArray<nsString> mIsoModes;
nsTArray<nsString> mSceneModes;
nsTArray<nsString> mMeteringModes;
nsClassHashtable<nsStringHashKey, nsCString> mIsoModeMap;
nsClassHashtable<nsCStringHashKey, nsCString> mParams;
// This subclass of android::CameraParameters just gives
// all of the AOSP getters and setters the same signature.
class Parameters : public android::CameraParameters
static PLDHashOperator EnumerateFlatten(const nsACString& aKey, nsCString* aValue, void* aUserArg);
nsresult SetImpl(const char* aKey, const char* aValue)
{
public:
Parameters()
: mVendorSpecificKeyIsoMode(nullptr)
, mVendorSpecificKeySupportedIsoModes(nullptr)
{ }
virtual ~Parameters() { }
nsCString key(aKey);
mParams.Put(key, new nsCString(aValue));
return NS_OK;
}
using android::CameraParameters::set;
using android::CameraParameters::get;
using android::CameraParameters::TRUE;
using android::CameraParameters::FALSE;
nsresult SetImpl(const char* aKey, int aValue)
{
nsCString key(aKey);
nsCString* value = new nsCString();
value->AppendInt(aValue);
mParams.Put(key, value);
return NS_OK;
}
void set(const char* aKey, float aValue) { setFloat(aKey, aValue); }
void set(const char* aKey, double aValue) { setFloat(aKey, aValue); }
void set(const char* aKey, bool aValue) { set(aKey, aValue ? TRUE : FALSE); }
void get(const char* aKey, float& aRet) { aRet = getFloat(aKey); }
void get(const char* aKey, double& aRet) { aRet = getFloat(aKey); }
void get(const char* aKey, const char*& aRet) { aRet = get(aKey); }
void get(const char* aKey, int& aRet) { aRet = getInt(aKey); }
nsresult SetImpl(const char* aKey, double aValue)
{
nsCString key(aKey);
nsCString* value = new nsCString();
value->AppendFloat(aValue);
mParams.Put(key, value);
return NS_OK;
}
void
get(const char* aKey, bool& aRet)
{
const char* value = get(aKey);
aRet = value ? strcmp(value, TRUE) == 0 : false;
nsresult SetImpl(const char* aKey, float aValue)
{
nsCString key(aKey);
nsCString* value = new nsCString();
value->AppendFloat(aValue);
mParams.Put(key, value);
return NS_OK;
}
nsresult SetImpl(const char* aKey, bool aValue)
{
nsCString key(aKey);
mParams.Put(key, new nsCString(aValue ? "true" : "false"));
return NS_OK;
}
nsresult GetImpl(const char* aKey, const char*& aRet)
{
nsCString key(aKey);
nsCString* value;
if (!mParams.Get(key, &value)) {
aRet = nullptr;
return NS_ERROR_FAILURE;
}
aRet = value->Data();
return NS_OK;
}
void remove(const char* aKey) { android::CameraParameters::remove(aKey); }
nsresult GetImpl(const char* aKey, float& aRet)
{
nsCString key(aKey);
nsCString* value;
nsresult rv = NS_ERROR_FAILURE;
if (mParams.Get(key, &value)) {
aRet = value->ToFloat(&rv);
} else {
aRet = 0.0;
}
return rv;
}
const char* GetTextKey(uint32_t aKey);
nsresult GetImpl(const char* aKey, double& aRet)
{
nsCString key(aKey);
nsCString* value;
nsresult rv = NS_ERROR_FAILURE;
if (mParams.Get(key, &value)) {
aRet = value->ToFloat(&rv);
} else {
aRet = 0.0;
}
return rv;
}
protected:
const char* FindVendorSpecificKey(const char* aPotentialKeys[], size_t aPotentialKeyCount);
nsresult GetImpl(const char* aKey, int& aRet)
{
nsCString key(aKey);
nsCString* value;
nsresult rv = NS_ERROR_FAILURE;
if (mParams.Get(key, &value)) {
aRet = value->ToInteger(&rv);
} else {
aRet = 0.0;
}
return rv;
}
const char* mVendorSpecificKeyIsoMode;
const char* mVendorSpecificKeySupportedIsoModes;
};
nsresult GetImpl(const char* aKey, bool& aRet)
{
nsCString key(aKey);
nsCString* value;
if (!mParams.Get(key, &value)) {
aRet = false;
return NS_ERROR_FAILURE;
}
aRet = value->EqualsLiteral("true");
return NS_OK;
}
Parameters mParams;
const char* GetTextKey(uint32_t aKey);
const char* FindVendorSpecificKey(const char* aPotentialKeys[], size_t aPotentialKeyCount);
// The *Impl() templates handle converting the parameter keys from
// their enum values to string types, if necessary. These are the
@ -159,41 +212,24 @@ protected:
template<typename T> nsresult
SetImpl(uint32_t aKey, const T& aValue)
{
const char* key = mParams.GetTextKey(aKey);
const char* key = GetTextKey(aKey);
NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED);
mParams.set(key, aValue);
return NS_OK;
return SetImpl(key, aValue);
}
template<typename T> nsresult
GetImpl(uint32_t aKey, T& aValue)
{
const char* key = mParams.GetTextKey(aKey);
const char* key = GetTextKey(aKey);
NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED);
mParams.get(key, aValue);
return NS_OK;
}
template<class T> nsresult
SetImpl(const char* aKey, const T& aValue)
{
mParams.set(aKey, aValue);
return NS_OK;
}
template<class T> nsresult
GetImpl(const char* aKey, T& aValue)
{
mParams.get(aKey, aValue);
return NS_OK;
return GetImpl(key, aValue);
}
nsresult
ClearImpl(const char* aKey)
{
mParams.remove(aKey);
nsCString key(aKey);
mParams.Remove(key);
return NS_OK;
}

View File

@ -15,12 +15,14 @@
*/
#include "GonkRecorderProfiles.h"
#include <media/MediaProfiles.h>
#include "nsMimeTypes.h"
#include "GonkRecorder.h"
#include "CameraControlImpl.h"
#include "CameraCommon.h"
#ifdef MOZ_WIDGET_GONK
#include "GonkRecorder.h"
#endif
using namespace mozilla;
using namespace android;
@ -374,10 +376,11 @@ GonkRecorderProfile::GetAll(uint32_t aCameraId,
aProfiles.Clear();
profiles->EnumerateRead(Enumerate, static_cast<void*>(&aProfiles));
return NS_OK;
}
#ifdef MOZ_WIDGET_GONK
nsresult
GonkRecorderProfile::ConfigureRecorder(GonkRecorder& aRecorder)
{
@ -425,3 +428,4 @@ GonkRecorderProfile::ConfigureRecorder(android::GonkRecorder& aRecorder,
return profile->ConfigureRecorder(aRecorder);
}
#endif

View File

@ -5,7 +5,12 @@
#ifndef DOM_CAMERA_GONK_RECORDER_PROFILES_H
#define DOM_CAMERA_GONK_RECORDER_PROFILES_H
#ifdef MOZ_WIDGET_GONK
#include <media/MediaProfiles.h>
#else
#include "FallbackCameraPlatform.h"
#endif
#include "ICameraControl.h"
#include "nsClassHashtable.h"
#include "nsRefPtrHashtable.h"
@ -109,6 +114,7 @@ public:
static nsresult GetAll(uint32_t aCameraId,
nsTArray<nsRefPtr<ICameraControl::RecorderProfile>>& aProfiles);
#ifdef MOZ_WIDGET_GONK
// Configures the specified recorder using the specified profile.
//
// Return values:
@ -118,6 +124,7 @@ public:
static nsresult ConfigureRecorder(android::GonkRecorder& aRecorder,
uint32_t aCameraId,
const nsAString& aProfileName);
#endif
protected:
GonkRecorderProfile(uint32_t aCameraId,
@ -129,7 +136,9 @@ protected:
bool GetMimeType(android::output_format aContainer, nsAString& aMimeType);
bool IsValid() const { return mIsValid; };
#ifdef MOZ_WIDGET_GONK
nsresult ConfigureRecorder(android::GonkRecorder& aRecorder);
#endif
static already_AddRefed<GonkRecorderProfile> CreateProfile(uint32_t aCameraId,
int aQuality);
static ProfileHashtable* GetProfileHashtable(uint32_t aCameraId);

View File

@ -31,6 +31,10 @@ using namespace android;
using namespace mozilla;
using namespace mozilla::dom;
#ifndef MOZ_WIDGET_GONK
NS_IMPL_ISUPPORTS_INHERITED0(TestGonkCameraHardware, GonkCameraHardware);
#endif
static void
CopyFaceFeature(int32_t (&aDst)[2], bool aExists, const DOMPoint* aSrc)
{
@ -633,6 +637,7 @@ TestGonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
return NS_OK;
}
#ifdef MOZ_WIDGET_GONK
int
TestGonkCameraHardware::PushParameters(const CameraParameters& aParams)
{
@ -658,6 +663,7 @@ TestGonkCameraHardware::PullParameters(CameraParameters& aParams)
String8 s(NS_LossyConvertUTF16toASCII(as).get());
aParams.unflatten(s);
}
#endif
int
TestGonkCameraHardware::StartRecording()

View File

@ -26,6 +26,10 @@ namespace mozilla {
class TestGonkCameraHardware : public android::GonkCameraHardware
{
#ifndef MOZ_WIDGET_GONK
NS_DECL_ISUPPORTS_INHERITED
#endif
public:
virtual nsresult Init() MOZ_OVERRIDE;
virtual int AutoFocus() MOZ_OVERRIDE;
@ -40,8 +44,10 @@ public:
virtual int StartRecording() MOZ_OVERRIDE;
virtual int StopRecording() MOZ_OVERRIDE;
virtual int StoreMetaDataInBuffers(bool aEnabled) MOZ_OVERRIDE;
#ifdef MOZ_WIDGET_GONK
virtual int PushParameters(const android::CameraParameters& aParams) MOZ_OVERRIDE;
virtual void PullParameters(android::CameraParameters& aParams) MOZ_OVERRIDE;
#endif
TestGonkCameraHardware(mozilla::nsGonkCameraControl* aTarget,
uint32_t aCameraId,

View File

@ -4,7 +4,7 @@
# 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/.
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
if CONFIG['MOZ_B2G_CAMERA']:
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
EXPORTS += [
@ -36,13 +36,21 @@ if CONFIG['MOZ_B2G_CAMERA']:
'GonkCameraHwMgr.cpp',
'GonkCameraManager.cpp',
'GonkCameraParameters.cpp',
'GonkCameraSource.cpp',
'GonkRecorder.cpp',
'GonkRecorderProfiles.cpp',
'TestGonkCameraControl.cpp',
'TestGonkCameraHardware.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
UNIFIED_SOURCES += [
'GonkCameraSource.cpp',
'GonkRecorder.cpp',
]
else:
UNIFIED_SOURCES += [
'FallbackCameraPlatform.cpp',
]
EXTRA_COMPONENTS += [
'CameraTestHardware.js',
'CameraTestHardware.manifest',

View File

@ -68,12 +68,18 @@ function CameraTestSuite() {
this.logError = this._logError.bind(this);
this.expectedError = this._expectedError.bind(this);
this.expectedRejectGetCamera = this._expectedRejectGetCamera.bind(this);
this.expectedRejectConfigure = this._expectedRejectConfigure.bind(this);
this.expectedRejectAutoFocus = this._expectedRejectAutoFocus.bind(this);
this.expectedRejectTakePicture = this._expectedRejectTakePicture.bind(this);
this.expectedRejectStartRecording = this._expectedRejectStartRecording.bind(this);
this.expectedRejectStopRecording = this._expectedRejectStopRecording.bind(this);
this.rejectGetCamera = this._rejectGetCamera.bind(this);
this.rejectConfigure = this._rejectConfigure.bind(this);
this.rejectRelease = this._rejectRelease.bind(this);
this.rejectAutoFocus = this._rejectAutoFocus.bind(this);
this.rejectTakePicture = this._rejectTakePicture.bind(this);
this.rejectStartRecording = this._rejectStartRecording.bind(this);
this.rejectStopRecording = this._rejectStopRecording.bind(this);
this.rejectPreviewStarted = this._rejectPreviewStarted.bind(this);
var self = this;
@ -95,20 +101,35 @@ CameraTestSuite.prototype = {
camera: null,
hw: null,
_lowMemSet: false,
_reloading: false,
/* Returns a promise which is resolved when the test suite is ready
to be executing individual test cases. One may provide the expected
hardware type here if desired; the default is to use the JS test
hardware. Use '' for the native emulated camera hardware. */
_setup: function(hwType) {
/* Depending on how we run the mochitest, we may not have the necessary
permissions yet. If we do need to request them, then we have to reload
the window to ensure the reconfiguration propogated properly. */
if (!SpecialPowers.hasPermission("camera", document)) {
info("requesting camera permission");
this._reloading = true;
SpecialPowers.addPermission("camera", true, document);
window.location.reload();
return Promise.reject();
}
info("has camera permission");
if (!isDefined(hwType)) {
hwType = 'hardware';
}
this._hwType = hwType;
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() {
resolve();
SpecialPowers.pushPrefEnv({'set': [['camera.control.test.permission', true]]}, function() {
SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() {
resolve();
});
});
});
},
@ -158,6 +179,10 @@ CameraTestSuite.prototype = {
/* Execute all test cases (after setup is called). */
_run: function() {
if (this._reloading) {
return;
}
var test = this._tests.shift();
var self = this;
if (test) {
@ -348,6 +373,10 @@ CameraTestSuite.prototype = {
return this.logError('get camera failed', e);
},
_rejectConfigure: function(e) {
return this.logError('set configuration failed', e);
},
_rejectRelease: function(e) {
return this.logError('release camera failed', e);
},
@ -360,6 +389,14 @@ CameraTestSuite.prototype = {
return this.logError('take picture failed', e);
},
_rejectStartRecording: function(e) {
return this.logError('start recording failed', e);
},
_rejectStopRecording: function(e) {
return this.logError('stop recording failed', e);
},
_rejectPreviewStarted: function(e) {
return this.logError('preview start failed', e);
},
@ -384,6 +421,10 @@ CameraTestSuite.prototype = {
return this.expectedError('expected get camera to fail');
},
_expectedRejectConfigure: function(p) {
return this.expectedError('expected set configuration to fail');
},
_expectedRejectAutoFocus: function(p) {
return this.expectedError('expected auto focus to fail');
},
@ -391,6 +432,14 @@ CameraTestSuite.prototype = {
_expectedRejectTakePicture: function(p) {
return this.expectedError('expected take picture to fail');
},
_expectedRejectStartRecording: function(p) {
return this.expectedError('expected start recording to fail');
},
_expectedRejectStopRecording: function(p) {
return this.expectedError('expected stop recording to fail');
},
};
ise(SpecialPowers.sanityCheck(), "foo", "SpecialPowers passed sanity check");

View File

@ -2,8 +2,11 @@
support-files = camera_common.js
[test_camera.html]
skip-if = toolkit != 'gonk'
[test_camera_2.html]
skip-if = toolkit != 'gonk'
[test_camera_3.html]
skip-if = toolkit != 'gonk'
[test_camera_hardware_init_failure.html]
[test_camera_hardware_failures.html]
[test_bug975472.html]
@ -14,4 +17,5 @@ support-files = camera_common.js
[test_bug1037322.html]
[test_bug1099390.html]
[test_bug1104913.html]
skip-if = toolkit != 'gonk'
[test_camera_bad_initial_config.html]

View File

@ -12,76 +12,56 @@
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var config = {
mode: 'picture',
recorderProfile: 'high',
previewSize: {
width: 320,
height: 240
}
};
var suite = new CameraTestSuite();
function onError(e) {
ok(false, "Error: " + JSON.stringify(e));
}
suite.test('bug-1037322', function() {
var cameraManager = navigator.mozCameras;
var whichCamera = cameraManager.getListOfCameras()[0];
var Camera = {
cameraObj: null,
get viewfinder() {
return document.getElementById('viewfinder');
},
start: function test_start() {
function setConfig_onSuccess(cfg) {
// Check our specific configuration
ok(cfg.mode === config.mode, "Configured mode = " + cfg.mode);
ok(cfg.previewSize.width === config.previewSize.width &&
cfg.previewSize.height === config.previewSize.height,
"Configured preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height);
ok(cfg.recorderProfile === config.recorderProfile,
"Configured recorder profile = '" + cfg.recorderProfile + "'");
SimpleTest.finish();
var postConfig = {
mode: 'picture',
recorderProfile: 'low',
previewSize: {
width: 320,
height: 240
}
};
function getCamera_onSuccess(d) {
var camera = d.camera;
var cfg = d.configuration;
Camera.cameraObj = camera;
Camera.viewfinder.mozSrcObject = camera;
Camera.viewfinder.play();
function resolveGetCamera(p) {
suite.camera = p.camera;
// Check the default configuration
ok(cfg.mode === "unspecified", "Initial mode = " + cfg.mode);
ok(cfg.previewSize.width === 0 && cfg.previewSize.height === 0,
"Initial preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height);
ok(cfg.recorderProfile === "default",
"Initial recorder profile = '" + cfg.recorderProfile + "'");
// Apply our specific configuration
camera.setConfiguration(config).then(setConfig_onSuccess, onError);
}
var cfg = {
mode: 'unspecified',
};
navigator.mozCameras.getCamera(whichCamera, cfg).then(getCamera_onSuccess, onError);
// Check the default configuration
var cfg = p.configuration;
ok(cfg.mode === "unspecified", "Initial mode = " + cfg.mode);
ok(cfg.previewSize.width === 0 && cfg.previewSize.height === 0,
"Initial preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height);
ok(cfg.recorderProfile === "default",
"Initial recorder profile = '" + cfg.recorderProfile + "'");
}
}
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
if (Camera.cameraObj) {
Camera.cameraObj.release();
Camera.cameraObj = null;
function configure(p) {
// Apply our specific configuration
return suite.camera.setConfiguration(postConfig);
}
function resolveConfigure(cfg) {
// Check our specific configuration
ok(cfg.mode === postConfig.mode, "Configured mode = " + cfg.mode);
ok(cfg.previewSize.width === postConfig.previewSize.width &&
cfg.previewSize.height === postConfig.previewSize.height,
"Configured preview size = " + cfg.previewSize.width + "x" + cfg.previewSize.height);
ok(cfg.recorderProfile === postConfig.recorderProfile,
"Configured recorder profile = '" + cfg.recorderProfile + "'");
}
return cameraManager.getCamera(whichCamera, {mode: 'unspecified'})
.then(resolveGetCamera, suite.rejectGetCamera)
.then(configure)
.then(resolveConfigure, suite.rejectConfigure);
});
Camera.start();
suite.setup()
.then(suite.run);
</script>
</body>

View File

@ -12,95 +12,42 @@
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var config = {
mode: 'picture',
recorderProfile: 'high',
previewSize: {
width: 352,
height: 288
}
};
var suite = new CameraTestSuite();
function onError(e) {
ok(false, "Error " + e);
}
suite.test('bug-1099390', function() {
function release(p) {
return new Promise(function(resolve, reject) {
var gotCloseEvent = false;
var gotReleasePromise = false;
var Camera = {
_cameraObj: null,
get viewfinder() {
return document.getElementById('viewfinder');
},
release: function release() {
viewfinder.mozSrcObject = null;
if (Camera._cameraObj) {
Camera._cameraObj.release();
Camera._cameraObj = null;
}
},
test: function test(cam) {
var gotCloseEvent = false;
var gotReleasePromise = false;
function gotAll() {
var all = gotCloseEvent && gotReleasePromise;
if (all) {
info("Got all expected notifications");
}
return all;
};
var onClosed = function(e) {
cam.removeEventListener('close', onClosed);
ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent);
ok(e.reason === "HardwareReleased", "'close' event reason is: " + e.reason);
gotCloseEvent = true;
if (gotAll()) {
SimpleTest.finish();
}
};
cam.addEventListener('close', onClosed);
var onResolve = function() {
ok(!gotReleasePromise, "gotReleasePromise was " + gotReleasePromise);
gotReleasePromise = true;
if (gotAll()) {
SimpleTest.finish();
}
};
cam.release().then(onResolve, onError);
}, // test()
start: function start() {
function onSuccess(d) {
Camera._cameraObj = d.camera;
var cam = d.camera;
var onPreviewStateChange = function(e) {
if (e.newState === 'started') {
cam.removeEventListener('previewstatechange', onPreviewStateChange);
Camera.test(cam);
var onClosed = function(e) {
suite.camera.removeEventListener('close', onClosed);
ok(!gotCloseEvent, "gotCloseEvent was " + gotCloseEvent);
ok(e.reason === "HardwareReleased", "'close' event reason is: " + e.reason);
gotCloseEvent = true;
if (gotReleasePromise) {
resolve();
}
}; // onPreviewStateChange
cam.addEventListener('previewstatechange', onPreviewStateChange);
}; // onSuccess()
};
navigator.mozCameras.getCamera(whichCamera, config).then(onSuccess, onError);
}, // start()
}
suite.camera.addEventListener('close', onClosed);
SimpleTest.waitForExplicitFinish();
suite.camera.release().then(function(p) {
ok(true, "released camera");
gotReleasePromise = true;
if (gotCloseEvent) {
resolve();
}
}).catch(reject);
});
}
window.addEventListener('beforeunload', function() {
Camera.release();
return suite.getCamera()
.then(release, suite.rejectGetCamera);
});
Camera.start();
suite.setup()
.then(suite.run);
</script>
</body>

View File

@ -12,237 +12,170 @@
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
const Cr = Components.results;
var suite = new CameraTestSuite();
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var config = {
mode: 'picture',
recorderProfile: 'high',
previewSize: {
width: 320,
height: 240
}
};
var options = {
rotation: 0,
position: {
latitude: 43.645687,
longitude: -79.393661
},
dateTime: Date.now()
};
function onError(e) {
ok(false, "Error " + e);
}
function next() {
Camera.nextTest();
function cameraRelease(p) {
return suite.camera.release();
}
// The array of tests
var tests = [
{
key: "release-after-release",
func: function testAutoFocus(camera) {
function onSuccess(success) {
ok(true, "release() succeeded");
next();
}
function onError(error) {
ok(false, "release() failed with: " + error);
}
camera.release().then(onSuccess, onError);
}
},
{
key: "set-picture-size-after-release",
func: function testSetPictureSize(camera) {
try {
camera.setPictureSize({ width: 0, height: 0 });
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"setPictureSize() failed with: " + e.name);
next();
}
}
},
{
key: "set-thumbnail-size-after-release",
func: function testSetThumbnailSize(camera) {
try {
camera.setThumbnailSize({ width: 0, height: 0 });
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"setThumbnailSize() failed with: " + e.name);
next();
}
}
},
{
key: "get-sensor-angle-after-release",
func: function testGetSensorAngle(camera) {
ok(camera.sensorAngle == 0, "camera.sensorAngle = " + camera.sensorAngle);
next();
}
},
{
key: "resume-preview-after-release",
func: function testResumePreview(camera) {
try {
camera.resumePreview();
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"resumePreview() failed with: " + e.name);
next();
}
}
},
{
key: "auto-focus-after-release",
func: function testAutoFocus(camera) {
function onSuccess(success) {
ok(false, "autoFocus() succeeded incorrectly");
}
function onError(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"autoFocus() failed with: " + error.name);
next();
}
camera.autoFocus().then(onSuccess, onError);
}
},
{
key: "take-picture-after-release",
func: function testTakePicture(camera) {
function onSuccess(picture) {
ok(false, "takePicture() succeeded incorrectly");
}
function onError(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"takePicture() failed with: " + error.name);
next();
}
camera.takePicture(null).then(onSuccess, onError);
}
},
{
key: "start-recording-after-release",
func: function testStartRecording(camera) {
function onSuccess(picture) {
ok(false, "startRecording() process succeeded incorrectly");
}
function onError(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"startRecording() failed with: " + error.name);
next();
}
var recordingOptions = {
profile: 'high',
rotation: 0
};
camera.startRecording(recordingOptions,
navigator.getDeviceStorage('videos'),
'bug975472.mp4').then(onSuccess, onError);
}
},
{
key: "stop-recording-after-release",
func: function testStopRecording(camera) {
try {
camera.stopRecording();
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"stopRecording() failed with: " + e.name);
next();
}
}
},
{
key: "set-configuration-after-release",
func: function testSetConfiguration(camera) {
function onSuccess(picture) {
ok(false, "setConfiguration() process succeeded incorrectly");
}
function onError(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"setConfiguration() failed with: " + error.name);
next();
}
camera.setConfiguration(config).then(onSuccess, onError);
}
},
];
var testGenerator = function() {
for (var i = 0; i < tests.length; ++i ) {
yield tests[i];
}
}();
var Camera = {
cameraObj: null,
_otherPictureSize: null,
get viewfinder() {
return document.getElementById('viewfinder');
},
onCameraReady: function () {
Camera.nextTest = function() {
try {
var t = testGenerator.next();
info("test: " + t.key);
t.func(Camera.cameraObj);
} catch(e) {
if (e instanceof StopIteration) {
SimpleTest.finish();
} else {
throw e;
}
}
};
// Release the camera hardware, and call all of the asynchronous methods
// to make sure they properly handle being in this state.
Camera.cameraObj.release();
next();
},
release: function release() {
cameraObj = null;
},
start: function run_test() {
function onSuccess(d) {
var camera = d.camera;
Camera.cameraObj = camera;
var onPreviewStateChange = function(e) {
if (e.newState === 'started') {
info("viewfinder is ready and playing");
Camera.cameraObj.removeEventListener('previewstatechange', onPreviewStateChange);
Camera.onCameraReady();
}
};
camera.addEventListener('previewstatechange', onPreviewStateChange);
Camera.viewfinder.mozSrcObject = camera;
Camera.viewfinder.play();
ok(camera.capabilities.pictureSizes.length > 0,
"capabilities.pictureSizes.length = " +
camera.capabilities.pictureSizes.length);
Camera._otherPictureSize = camera.capabilities.pictureSizes.slice(-1)[0];
camera.setPictureSize(camera.capabilities.pictureSizes[0]);
options.pictureSize = Camera._otherPictureSize;
options.fileFormat = camera.capabilities.fileFormats[0];
info("getCamera callback, setting pictureSize = " + options.pictureSize.toSource());
};
navigator.mozCameras.getCamera(whichCamera, config).then(onSuccess, onError);
}
}
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.cameraObj.release();
Camera.cameraObj = null;
suite.test('release-after-release', function() {
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(cameraRelease, suite.rejectRelease)
.catch(suite.rejectRelease);
});
Camera.start();
suite.test('set-picture-size-after-release', function() {
function setPictureSize(p) {
try {
suite.camera.setPictureSize({ width: 0, height: 0 });
ok(false, "SetPictureSize() should have failed");
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"setPictureSize() failed with: " + e.name);
}
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(setPictureSize, suite.rejectRelease);
});
suite.test('set-thumbnail-size-after-release', function() {
function setThumbnailSize(p) {
try {
suite.camera.setThumbnailSize({ width: 0, height: 0 });
ok(false, "SetThumbnailSize() should have failed");
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"setThumbnailSize() failed with: " + e.name);
}
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(setThumbnailSize, suite.rejectRelease);
});
suite.test('get-sensor-angle-after-release', function() {
function getSensorAngle(p) {
ok(suite.camera.sensorAngle == 0, "camera.sensorAngle = " + suite.camera.sensorAngle);
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(getSensorAngle, suite.rejectRelease);
});
suite.test('resume-preview-after-release', function() {
function resumePreview(p) {
try {
suite.camera.resumePreview();
ok(false, "resumePreview() should have failed");
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"resumePreview() failed with: " + e.name);
}
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(resumePreview, suite.rejectRelease);
});
suite.test('auto-focus-after-release', function() {
function autoFocus(p) {
return suite.camera.autoFocus();
}
function rejectAutoFocus(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"autoFocus() failed with: " + error.name);
return Promise.resolve();
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(autoFocus, suite.rejectRelease)
.then(suite.expectedRejectAutoFocus, rejectAutoFocus);
});
suite.test('take-picture-after-release', function() {
function takePicture(p) {
return suite.camera.takePicture(null);
}
function rejectTakePicture(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"takePicture() failed with: " + error.name);
return Promise.resolve();
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(takePicture, suite.rejectRelease)
.then(suite.expectedRejectTakePicture, rejectTakePicture);
});
suite.test('start-recording-after-release', function() {
function startRecording(p) {
return suite.camera.startRecording(
{
profile: 'high',
rotation: 0
},
navigator.getDeviceStorage('videos'),
'bug975472.mp4'
);
}
function rejectStartRecording(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"takePicture() failed with: " + error.name);
return Promise.resolve();
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(startRecording, suite.rejectRelease)
.then(suite.expectedRejectStartRecording, rejectStartRecording);
});
suite.test('stop-recording-after-release', function() {
function stopRecording(p) {
try {
suite.camera.stopRecording();
ok(false, "stopRecording() should have failed");
} catch(e) {
ok(e.result === SpecialPowers.Cr.NS_ERROR_NOT_AVAILABLE,
"stopRecording() failed with: " + e.name);
}
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(stopRecording, suite.rejectRelease);
});
suite.test('set-configuration-after-release', function() {
function configure(p) {
return suite.camera.setConfiguration(null);
}
function rejectConfigure(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"takePicture() failed with: " + error.name);
return Promise.resolve();
}
return suite.getCamera()
.then(cameraRelease, suite.rejectGetCamera)
.then(configure, suite.rejectRelease)
.then(suite.expectedRejectConfigure, rejectConfigure);
});
suite.setup()
.then(suite.run);
</script>
</body>

View File

@ -12,45 +12,31 @@
<img src="#" alt="This image is going to load" id="testimage"/>
<script class="testbody" type="text/javascript;version=1.7">
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var config = {
mode: 'picture',
recorderProfile: 'foobar',
};
var suite = new CameraTestSuite();
var Camera = {
cameraObj: null,
suite.test('bad-initial-config', function() {
function getCamera() {
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
var config = {
mode: 'picture',
recorderProfile: 'foobar',
};
get viewfinder() {
return document.getElementById('viewfinder');
},
start: function test_start() {
function getCamera_onSuccess(d) {
ok(false, "Get camera should have failed");
SimpleTest.finish();
}
function getCamera_onError(e) {
ok(true, "Get camera failed as expected: " + JSON.stringify(e));
SimpleTest.finish();
}
navigator.mozCameras.getCamera(whichCamera, config).then(getCamera_onSuccess, getCamera_onError);
return navigator.mozCameras.getCamera(whichCamera, config);
}
}
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
if (Camera.cameraObj) {
Camera.cameraObj.release();
Camera.cameraObj = null;
function rejectGetCamera(error) {
ok(error.name === "NS_ERROR_NOT_AVAILABLE",
"getCamera() failed with: " + error.name);
return Promise.resolve();
}
return getCamera()
.then(suite.expectedRejectGetCamera, rejectGetCamera);
});
Camera.start();
suite.setup()
.then(suite.run);
</script>
</body>

View File

@ -391,7 +391,7 @@ MediaDevice::MediaDevice(MediaEngineSource* aSource)
VideoDevice::VideoDevice(MediaEngineVideoSource* aSource)
: MediaDevice(aSource) {
#ifdef MOZ_B2G_CAMERA
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
if (mName.EqualsLiteral("back")) {
mHasFacingMode = true;
mFacingMode = dom::VideoFacingModeEnum::Environment;
@ -1705,7 +1705,7 @@ MediaManager::GetUserMedia(
}
}
#ifdef MOZ_B2G_CAMERA
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
if (mCameraManager == nullptr) {
mCameraManager = nsDOMCameraManager::CreateInstance(aWindow);
}

View File

@ -630,7 +630,7 @@ private:
static StaticRefPtr<MediaManager> sSingleton;
#ifdef MOZ_B2G_CAMERA
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
nsRefPtr<nsDOMCameraManager> mCameraManager;
#endif
};

View File

@ -31,7 +31,7 @@ GetUserMediaLog()
#include "AndroidBridge.h"
#endif
#ifdef MOZ_B2G_CAMERA
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
#include "ICameraControl.h"
#include "MediaEngineGonkVideoSource.h"
#endif
@ -62,7 +62,9 @@ MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
compMgr->IsContractIDRegistered(NS_TABSOURCESERVICE_CONTRACTID, &mHasTabVideoSource);
}
#else
#ifdef MOZ_WIDGET_GONK
AsyncLatencyLogger::Get()->AddRef();
#endif
#endif
// XXX
gFarendObserver = new AudioOutputObserver();
@ -78,7 +80,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
// We spawn threads to handle gUM runnables, so we must protect the member vars
MutexAutoLock lock(mMutex);
#ifdef MOZ_B2G_CAMERA
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
if (aMediaSource != dom::MediaSourceEnum::Camera) {
// only supports camera sources
return;

View File

@ -255,7 +255,7 @@ public:
private:
~MediaEngineWebRTC() {
Shutdown();
#ifdef MOZ_B2G_CAMERA
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
AsyncLatencyLogger::Get()->Release();
#endif
gFarendObserver = nullptr;

View File

@ -36,7 +36,7 @@ if CONFIG['MOZ_WEBRTC']:
'/media/webrtc/trunk',
]
# Gonk camera source.
if CONFIG['MOZ_B2G_CAMERA']:
if CONFIG['MOZ_B2G_CAMERA'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
EXPORTS += [
'GonkCameraImage.h',
'MediaEngineGonkVideoSource.h',

View File

@ -201,7 +201,7 @@ if CONFIG['MOZ_B2G_BT_BLUEZ'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
'dbus',
]
if CONFIG['MOZ_B2G_CAMERA']:
if CONFIG['MOZ_B2G_CAMERA'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
OS_LIBS += [
'stagefright',
'stagefright_omx',