2012-07-31 01:59:05 +04:00
/*
* 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 <string.h>
2012-09-29 09:30:52 +04:00
# include <sys/stat.h>
# include <fcntl.h>
# include <errno.h>
# include <libgen.h>
2012-08-17 14:56:55 +04:00
# include "base/basictypes.h"
2012-07-31 01:59:05 +04:00
# include "libcameraservice/CameraHardwareInterface.h"
# include "camera/CameraParameters.h"
# include "nsCOMPtr.h"
# include "nsDOMClassInfo.h"
# include "nsMemory.h"
# include "jsapi.h"
# include "nsThread.h"
2012-09-29 09:30:52 +04:00
# include <media/MediaProfiles.h>
# include "nsDirectoryServiceDefs.h" // for NS_GetSpecialDirectory
2012-07-31 01:59:05 +04:00
# include "nsPrintfCString.h"
# include "DOMCameraManager.h"
# include "GonkCameraHwMgr.h"
2012-09-05 05:01:56 +04:00
# include "DOMCameraCapabilities.h"
# include "DOMCameraControl.h"
2012-07-31 01:59:05 +04:00
# include "GonkCameraControl.h"
# include "CameraCommon.h"
using namespace mozilla ;
2012-09-05 05:01:56 +04:00
using namespace android ;
2012-07-31 01:59:05 +04:00
2012-08-22 19:56:38 +04:00
static const char * getKeyText ( uint32_t aKey )
2012-07-31 01:59:05 +04:00
{
switch ( aKey ) {
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_EFFECT :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_EFFECT ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_WHITEBALANCE :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_WHITE_BALANCE ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SCENEMODE :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SCENE_MODE ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_FLASHMODE :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_FLASH_MODE ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_FOCUSMODE :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_FOCUS_MODE ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_ZOOM :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_ZOOM ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_METERINGAREAS :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_METERING_AREAS ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_FOCUSAREAS :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_FOCUS_AREAS ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_FOCALLENGTH :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_FOCAL_LENGTH ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_FOCUSDISTANCENEAR :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_FOCUS_DISTANCES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_FOCUS_DISTANCES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_FOCUSDISTANCEFAR :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_FOCUS_DISTANCES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_EXPOSURECOMPENSATION :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_EXPOSURE_COMPENSATION ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_PREVIEW_SIZES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_VIDEOSIZES :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_VIDEO_SIZES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_PICTURESIZES :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_PICTURE_SIZES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_PICTURE_FORMATS ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_WHITEBALANCES :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_WHITE_BALANCE ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_SCENEMODES :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_SCENE_MODES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_EFFECTS :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_EFFECTS ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_FLASHMODES :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_FLASH_MODES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_FOCUSMODES :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_SUPPORTED_FOCUS_MODES ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_MAX_NUM_FOCUS_AREAS ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_MAX_NUM_METERING_AREAS ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_MIN_EXPOSURE_COMPENSATION ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_MAX_EXPOSURE_COMPENSATION ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_EXPOSURE_COMPENSATION_STEP ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_ZOOM :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_ZOOM_SUPPORTED ;
2012-09-05 05:01:56 +04:00
case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS :
2012-07-31 01:59:05 +04:00
return CameraParameters : : KEY_ZOOM_RATIOS ;
default :
return nullptr ;
}
}
2012-09-05 05:01:56 +04:00
// 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 ) ;
}
2012-07-31 01:59:05 +04:00
// Gonk-specific CameraControl implementation.
2012-09-05 05:01:56 +04:00
// 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 )
2012-07-31 01:59:05 +04:00
, mHwHandle ( 0 )
, mExposureCompensationMin ( 0.0 )
, mExposureCompensationStep ( 0.0 )
, mDeferConfigUpdate ( false )
2012-09-05 05:01:56 +04:00
, 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 ( )
2012-07-31 01:59:05 +04:00
{
mHwHandle = GonkCameraHardware : : GetHandle ( this , mCameraId ) ;
2012-09-05 05:01:56 +04:00
DOM_CAMERA_LOGI ( " Initializing camera %d (this=%p, mHwHandle=%d) \n " , mCameraId , this , mHwHandle ) ;
2012-07-31 01:59:05 +04:00
// Initialize our camera configuration database.
2012-09-05 05:01:56 +04:00
PullParametersImpl ( ) ;
// 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 ) ;
// 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 ;
2012-07-31 01:59:05 +04:00
}
nsGonkCameraControl : : ~ nsGonkCameraControl ( )
{
2012-09-05 05:01:56 +04:00
DOM_CAMERA_LOGT ( " %s:%d : this=%p, mHwHandle = %d \n " , __func__ , __LINE__ , this , mHwHandle ) ;
2012-07-31 01:59:05 +04:00
GonkCameraHardware : : ReleaseHandle ( mHwHandle ) ;
if ( mRwLock ) {
PRRWLock * lock = mRwLock ;
mRwLock = nullptr ;
PR_DestroyRWLock ( lock ) ;
}
2012-09-05 05:01:56 +04:00
DOM_CAMERA_LOGT ( " %s:%d \n " , __func__ , __LINE__ ) ;
2012-07-31 01:59:05 +04:00
}
class RwAutoLockRead
{
public :
RwAutoLockRead ( PRRWLock * aRwLock )
: mRwLock ( aRwLock )
{
PR_RWLock_Rlock ( mRwLock ) ;
}
~ RwAutoLockRead ( )
{
PR_RWLock_Unlock ( mRwLock ) ;
}
protected :
PRRWLock * mRwLock ;
} ;
class RwAutoLockWrite
{
public :
RwAutoLockWrite ( PRRWLock * aRwLock )
: mRwLock ( aRwLock )
{
PR_RWLock_Wlock ( mRwLock ) ;
}
~ RwAutoLockWrite ( )
{
PR_RWLock_Unlock ( mRwLock ) ;
}
protected :
PRRWLock * mRwLock ;
} ;
const char *
nsGonkCameraControl : : GetParameter ( const char * aKey )
{
RwAutoLockRead lock ( mRwLock ) ;
return mParams . get ( aKey ) ;
}
const char *
2012-08-22 19:56:38 +04:00
nsGonkCameraControl : : GetParameterConstChar ( uint32_t aKey )
2012-07-31 01:59:05 +04:00
{
const char * key = getKeyText ( aKey ) ;
if ( ! key ) {
return nullptr ;
}
RwAutoLockRead lock ( mRwLock ) ;
return mParams . get ( key ) ;
}
double
2012-08-22 19:56:38 +04:00
nsGonkCameraControl : : GetParameterDouble ( uint32_t aKey )
2012-07-31 01:59:05 +04:00
{
double val ;
int index = 0 ;
double focusDistance [ 3 ] ;
const char * s ;
const char * key = getKeyText ( aKey ) ;
if ( ! key ) {
// return 1x when zooming is not supported
return aKey = = CAMERA_PARAM_ZOOM ? 1.0 : 0.0 ;
}
RwAutoLockRead lock ( mRwLock ) ;
switch ( aKey ) {
case CAMERA_PARAM_ZOOM :
val = mParams . getInt ( key ) ;
return val / 100 ;
/**
* The gonk camera parameters API only exposes one focus distance property
* that contains " Near,Optimum,Far " distances , in metres , where ' Far ' may
* be ' Infinity ' .
*/
case CAMERA_PARAM_FOCUSDISTANCEFAR :
+ + index ;
// intentional fallthrough
case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM :
+ + index ;
// intentional fallthrough
case CAMERA_PARAM_FOCUSDISTANCENEAR :
s = mParams . get ( key ) ;
if ( sscanf ( s , " %lf,%lf,%lf " , & focusDistance [ 0 ] , & focusDistance [ 1 ] , & focusDistance [ 2 ] ) = = 3 ) {
return focusDistance [ index ] ;
}
return 0.0 ;
case CAMERA_PARAM_EXPOSURECOMPENSATION :
index = mParams . getInt ( key ) ;
if ( ! index ) {
// NaN indicates automatic exposure compensation
return NAN ;
}
val = ( index - 1 ) * mExposureCompensationStep + mExposureCompensationMin ;
DOM_CAMERA_LOGI ( " index = %d --> compensation = %f \n " , index , val ) ;
return val ;
default :
return mParams . getFloat ( key ) ;
}
}
void
2012-08-22 19:56:38 +04:00
nsGonkCameraControl : : GetParameter ( uint32_t aKey , nsTArray < CameraRegion > & aRegions )
2012-07-31 01:59:05 +04:00
{
aRegions . Clear ( ) ;
const char * key = getKeyText ( aKey ) ;
if ( ! key ) {
return ;
}
RwAutoLockRead lock ( mRwLock ) ;
const char * value = mParams . get ( key ) ;
DOM_CAMERA_LOGI ( " key='%s' --> value='%s' \n " , key , value ) ;
if ( ! value ) {
return ;
}
const char * p = value ;
2012-08-22 19:56:38 +04:00
uint32_t count = 1 ;
2012-07-31 01:59:05 +04:00
// count the number of regions in the string
while ( ( p = strstr ( p , " ),( " ) ) ) {
+ + count ;
p + = 3 ;
}
aRegions . SetCapacity ( count ) ;
CameraRegion * r ;
// parse all of the region sets
2012-08-22 19:56:38 +04:00
uint32_t i ;
2012-07-31 01:59:05 +04:00
for ( i = 0 , p = value ; p & & i < count ; + + i , p = strchr ( p + 1 , ' ( ' ) ) {
r = aRegions . AppendElement ( ) ;
if ( sscanf ( p , " (%d,%d,%d,%d,%u) " , & r - > top , & r - > left , & r - > bottom , & r - > right , & r - > weight ) ! = 5 ) {
DOM_CAMERA_LOGE ( " %s:%d : region tuple has bad format: '%s' \n " , __func__ , __LINE__ , p ) ;
goto GetParameter_error ;
}
}
return ;
GetParameter_error :
aRegions . Clear ( ) ;
}
2012-09-05 05:01:56 +04:00
nsresult
2012-07-31 01:59:05 +04:00
nsGonkCameraControl : : PushParameters ( )
{
2012-09-05 05:01:56 +04:00
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 ) ;
2012-07-31 01:59:05 +04:00
}
2012-09-05 05:01:56 +04:00
DOM_CAMERA_LOGT ( " %s:%d \n " , __func__ , __LINE__ ) ;
return PushParametersImpl ( ) ;
2012-07-31 01:59:05 +04:00
}
void
nsGonkCameraControl : : SetParameter ( const char * aKey , const char * aValue )
{
{
RwAutoLockWrite lock ( mRwLock ) ;
mParams . set ( aKey , aValue ) ;
}
PushParameters ( ) ;
}
void
2012-08-22 19:56:38 +04:00
nsGonkCameraControl : : SetParameter ( uint32_t aKey , const char * aValue )
2012-07-31 01:59:05 +04:00
{
const char * key = getKeyText ( aKey ) ;
if ( ! key ) {
return ;
}
{
RwAutoLockWrite lock ( mRwLock ) ;
mParams . set ( key , aValue ) ;
}
PushParameters ( ) ;
}
void
2012-08-22 19:56:38 +04:00
nsGonkCameraControl : : SetParameter ( uint32_t aKey , double aValue )
2012-07-31 01:59:05 +04:00
{
2012-08-22 19:56:38 +04:00
uint32_t index ;
2012-07-31 01:59:05 +04:00
const char * key = getKeyText ( aKey ) ;
if ( ! key ) {
return ;
}
{
RwAutoLockWrite lock ( mRwLock ) ;
if ( aKey = = CAMERA_PARAM_EXPOSURECOMPENSATION ) {
/**
* Convert from real value to a Gonk index , round
* to the nearest step ; index is 1 - based .
*/
index = ( aValue - mExposureCompensationMin + mExposureCompensationStep / 2 ) / mExposureCompensationStep + 1 ;
DOM_CAMERA_LOGI ( " compensation = %f --> index = %d \n " , aValue , index ) ;
mParams . set ( key , index ) ;
} else {
mParams . setFloat ( key , aValue ) ;
}
}
PushParameters ( ) ;
}
void
2012-08-22 19:56:38 +04:00
nsGonkCameraControl : : SetParameter ( uint32_t aKey , const nsTArray < CameraRegion > & aRegions )
2012-07-31 01:59:05 +04:00
{
const char * key = getKeyText ( aKey ) ;
if ( ! key ) {
return ;
}
2012-08-22 19:56:38 +04:00
uint32_t length = aRegions . Length ( ) ;
2012-07-31 01:59:05 +04:00
if ( ! length ) {
// This tells the camera driver to revert to automatic regioning.
mParams . set ( key , " (0,0,0,0,0) " ) ;
PushParameters ( ) ;
return ;
}
nsCString s ;
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < length ; + + i ) {
2012-07-31 01:59:05 +04:00
const CameraRegion * r = & aRegions [ i ] ;
s . AppendPrintf ( " (%d,%d,%d,%d,%d), " , r - > top , r - > left , r - > bottom , r - > right , r - > weight ) ;
}
// remove the trailing comma
s . Trim ( " , " , false , true , true ) ;
DOM_CAMERA_LOGI ( " camera region string '%s' \n " , s . get ( ) ) ;
{
RwAutoLockWrite lock ( mRwLock ) ;
mParams . set ( key , s . get ( ) ) ;
}
PushParameters ( ) ;
}
nsresult
nsGonkCameraControl : : GetPreviewStreamImpl ( GetPreviewStreamTask * aGetPreviewStream )
{
2012-09-05 05:01:56 +04:00
SetPreviewSize ( aGetPreviewStream - > mSize . width , aGetPreviewStream - > mSize . height ) ;
2012-07-31 01:59:05 +04:00
2012-09-05 05:01:56 +04:00
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 ) ;
2012-07-31 01:59:05 +04:00
}
2012-09-05 05:01:56 +04:00
mDOMPreview = aStartPreview - > mDOMPreview ;
} else if ( ! mDOMPreview ) {
return NS_ERROR_INVALID_ARG ;
}
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 ;
2012-07-31 01:59:05 +04:00
}
2012-09-05 05:01:56 +04:00
if ( aStartPreview - > mDOMPreview ) {
mDOMPreview - > Started ( ) ;
}
return NS_OK ;
}
nsresult
2012-09-29 09:30:52 +04:00
nsGonkCameraControl : : StopPreviewInternal ( bool aForced )
2012-09-05 05:01:56 +04:00
{
DOM_CAMERA_LOGI ( " %s: stopping preview \n " , __func__ ) ;
// StopPreview() is a synchronous call--it doesn't return
// until the camera preview thread exits.
2012-09-29 09:30:52 +04:00
if ( mDOMPreview ) {
GonkCameraHardware : : StopPreview ( mHwHandle ) ;
mDOMPreview - > Stopped ( aForced ) ;
mDOMPreview = nullptr ;
}
2012-09-05 05:01:56 +04:00
return NS_OK ;
2012-07-31 01:59:05 +04:00
}
2012-09-29 09:30:52 +04:00
nsresult
nsGonkCameraControl : : StopPreviewImpl ( StopPreviewTask * aStopPreview )
{
return StopPreviewInternal ( ) ;
}
2012-07-31 01:59:05 +04:00
nsresult
nsGonkCameraControl : : AutoFocusImpl ( AutoFocusTask * aAutoFocus )
{
nsCOMPtr < nsICameraAutoFocusCallback > cb = mAutoFocusOnSuccessCb ;
if ( cb ) {
/**
* We already have a callback , so someone has already
* called autoFocus ( ) - - cancel it .
*/
mAutoFocusOnSuccessCb = nullptr ;
nsCOMPtr < nsICameraErrorCallback > ecb = mAutoFocusOnErrorCb ;
mAutoFocusOnErrorCb = nullptr ;
if ( ecb ) {
nsresult rv = NS_DispatchToMainThread ( new CameraErrorResult ( ecb , NS_LITERAL_STRING ( " CANCELLED " ) ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
GonkCameraHardware : : CancelAutoFocus ( mHwHandle ) ;
}
mAutoFocusOnSuccessCb = aAutoFocus - > mOnSuccessCb ;
mAutoFocusOnErrorCb = aAutoFocus - > mOnErrorCb ;
if ( GonkCameraHardware : : AutoFocus ( mHwHandle ) ! = OK ) {
return NS_ERROR_FAILURE ;
}
return NS_OK ;
}
nsresult
nsGonkCameraControl : : TakePictureImpl ( TakePictureTask * aTakePicture )
{
2012-09-05 05:01:56 +04:00
nsCOMPtr < nsICameraTakePictureCallback > cb = mTakePictureOnSuccessCb ;
2012-07-31 01:59:05 +04:00
if ( cb ) {
/**
* We already have a callback , so someone has already
* called TakePicture ( ) - - cancel it .
*/
mTakePictureOnSuccessCb = nullptr ;
nsCOMPtr < nsICameraErrorCallback > ecb = mTakePictureOnErrorCb ;
mTakePictureOnErrorCb = nullptr ;
if ( ecb ) {
nsresult rv = NS_DispatchToMainThread ( new CameraErrorResult ( ecb , NS_LITERAL_STRING ( " CANCELLED " ) ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
GonkCameraHardware : : CancelTakePicture ( mHwHandle ) ;
}
mTakePictureOnSuccessCb = aTakePicture - > mOnSuccessCb ;
mTakePictureOnErrorCb = aTakePicture - > mOnErrorCb ;
// batch-update camera configuration
mDeferConfigUpdate = true ;
/**
* height and width : some drivers are less friendly about getting one of
* these set to zero , so if either is not specified , ignore both and go
* with current or default settings .
*/
if ( aTakePicture - > mSize . width & & aTakePicture - > mSize . height ) {
nsCString s ;
s . AppendPrintf ( " %dx%d " , aTakePicture - > mSize . width , aTakePicture - > mSize . height ) ;
DOM_CAMERA_LOGI ( " setting picture size to '%s' \n " , s . get ( ) ) ;
SetParameter ( CameraParameters : : KEY_PICTURE_SIZE , s . get ( ) ) ;
}
// Picture format -- need to keep it for the callback.
mFileFormat = aTakePicture - > mFileFormat ;
SetParameter ( CameraParameters : : KEY_PICTURE_FORMAT , NS_ConvertUTF16toUTF8 ( mFileFormat ) . get ( ) ) ;
// Convert 'rotation' to a positive value from 0..270 degrees, in steps of 90.
2012-08-22 19:56:38 +04:00
uint32_t r = static_cast < uint32_t > ( aTakePicture - > mRotation ) ;
2012-07-31 01:59:05 +04:00
r % = 360 ;
r + = 45 ;
r / = 90 ;
r * = 90 ;
DOM_CAMERA_LOGI ( " setting picture rotation to %d degrees (mapped from %d) \n " , r , aTakePicture - > mRotation ) ;
SetParameter ( CameraParameters : : KEY_ROTATION , nsPrintfCString ( " %u " , r ) . get ( ) ) ;
// Add any specified positional information -- don't care if these fail.
if ( ! isnan ( aTakePicture - > mPosition . latitude ) ) {
DOM_CAMERA_LOGI ( " setting picture latitude to %lf \n " , aTakePicture - > mPosition . latitude ) ;
SetParameter ( CameraParameters : : KEY_GPS_LATITUDE , nsPrintfCString ( " %lf " , aTakePicture - > mPosition . latitude ) . get ( ) ) ;
}
if ( ! isnan ( aTakePicture - > mPosition . longitude ) ) {
DOM_CAMERA_LOGI ( " setting picture longitude to %lf \n " , aTakePicture - > mPosition . longitude ) ;
SetParameter ( CameraParameters : : KEY_GPS_LONGITUDE , nsPrintfCString ( " %lf " , aTakePicture - > mPosition . longitude ) . get ( ) ) ;
}
if ( ! isnan ( aTakePicture - > mPosition . altitude ) ) {
DOM_CAMERA_LOGI ( " setting picture altitude to %lf \n " , aTakePicture - > mPosition . altitude ) ;
SetParameter ( CameraParameters : : KEY_GPS_ALTITUDE , nsPrintfCString ( " %lf " , aTakePicture - > mPosition . altitude ) . get ( ) ) ;
}
if ( ! isnan ( aTakePicture - > mPosition . timestamp ) ) {
DOM_CAMERA_LOGI ( " setting picture timestamp to %lf \n " , aTakePicture - > mPosition . timestamp ) ;
SetParameter ( CameraParameters : : KEY_GPS_TIMESTAMP , nsPrintfCString ( " %lf " , aTakePicture - > mPosition . timestamp ) . get ( ) ) ;
}
mDeferConfigUpdate = false ;
PushParameters ( ) ;
if ( GonkCameraHardware : : TakePicture ( mHwHandle ) ! = OK ) {
return NS_ERROR_FAILURE ;
}
return NS_OK ;
}
nsresult
2012-09-05 05:01:56 +04:00
nsGonkCameraControl : : PushParametersImpl ( )
2012-07-31 01:59:05 +04:00
{
2012-09-05 05:01:56 +04:00
DOM_CAMERA_LOGI ( " Pushing camera parameters \n " ) ;
2012-07-31 01:59:05 +04:00
RwAutoLockRead lock ( mRwLock ) ;
if ( GonkCameraHardware : : PushParameters ( mHwHandle , mParams ) ! = OK ) {
return NS_ERROR_FAILURE ;
}
return NS_OK ;
}
nsresult
2012-09-05 05:01:56 +04:00
nsGonkCameraControl : : PullParametersImpl ( )
2012-07-31 01:59:05 +04:00
{
2012-09-05 05:01:56 +04:00
DOM_CAMERA_LOGI ( " Pulling camera parameters \n " ) ;
2012-07-31 01:59:05 +04:00
RwAutoLockWrite lock ( mRwLock ) ;
GonkCameraHardware : : PullParameters ( mHwHandle , mParams ) ;
return NS_OK ;
}
nsresult
nsGonkCameraControl : : StartRecordingImpl ( StartRecordingTask * aStartRecording )
{
2012-09-29 09:30:52 +04:00
mStartRecordingOnSuccessCb = aStartRecording - > mOnSuccessCb ;
mStartRecordingOnErrorCb = aStartRecording - > mOnErrorCb ;
/**
* We need to pull in the base path from aStartRecording - > mStorageArea
* once that feature lands . See bug 795201.
*
* For now , we just assume / sdcard / Movies .
*
* Also , the camera app needs to provide the file extension ' .3 gp ' for now .
* See bug 795202.
*/
# if 1
nsCOMPtr < nsIFile > filename ;
aStartRecording - > mStorageArea - > GetRootDirectory ( getter_AddRefs ( filename ) ) ;
filename - > Append ( aStartRecording - > mFilename ) ;
nsAutoCString pathname ;
filename - > GetNativePath ( pathname ) ;
# else
nsAutoCString pathname ( NS_LITERAL_CSTRING ( " /sdcard/Movies/ " ) ) ;
nsAutoCString filename ( NS_ConvertUTF16toUTF8 ( aStartRecording - > mFilename ) ) ;
// Make sure that the file name doesn't contain any directory components.
if ( strcmp ( filename . get ( ) , basename ( filename . get ( ) ) ) ! = 0 ) {
DOM_CAMERA_LOGE ( " Video filename '%s' is not valid \n " , filename . get ( ) ) ;
return NS_ERROR_INVALID_ARG ;
}
pathname . Append ( filename ) ;
# endif
DOM_CAMERA_LOGI ( " Video pathname is '%s' \n " , pathname . get ( ) ) ;
int fd = open ( pathname . get ( ) , O_RDWR | O_CREAT , 0644 ) ;
if ( fd < 0 ) {
DOM_CAMERA_LOGE ( " Couldn't create file '%s' with error (%d) %s \n " , pathname . get ( ) , errno , strerror ( errno ) ) ;
return NS_ERROR_FAILURE ;
}
if ( SetupRecording ( fd ) ! = NS_OK ) {
DOM_CAMERA_LOGE ( " SetupRecording() failed \n " ) ;
close ( fd ) ;
return NS_ERROR_FAILURE ;
}
if ( mRecorder - > start ( ) ! = OK ) {
DOM_CAMERA_LOGE ( " mRecorder->start() failed \n " ) ;
close ( fd ) ;
return NS_ERROR_FAILURE ;
}
// dispatch the callback
nsCOMPtr < nsIRunnable > startRecordingResult = new StartRecordingResult ( mStartRecordingOnSuccessCb ) ;
nsresult rv = NS_DispatchToMainThread ( startRecordingResult ) ;
if ( NS_FAILED ( rv ) ) {
DOM_CAMERA_LOGE ( " Failed to dispatch start recording result to main thread (%d)! " , rv ) ;
}
return NS_OK ;
2012-07-31 01:59:05 +04:00
}
nsresult
nsGonkCameraControl : : StopRecordingImpl ( StopRecordingTask * aStopRecording )
{
2012-09-29 09:30:52 +04:00
mRecorder - > stop ( ) ;
delete mRecorder ;
mRecorder = nullptr ;
return NS_OK ;
2012-07-31 01:59:05 +04:00
}
void
2012-09-05 05:01:56 +04:00
nsGonkCameraControl : : 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 ( ) ;
/**
* 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 )
2012-07-31 01:59:05 +04:00
{
2012-09-05 05:01:56 +04:00
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! " ) ;
}
}
2012-07-31 01:59:05 +04:00
2012-09-05 05:01:56 +04:00
void
nsGonkCameraControl : : SetPreviewSize ( uint32_t aWidth , uint32_t aHeight )
{
Vector < Size > previewSizes ;
uint32_t bestWidth = aWidth ;
uint32_t bestHeight = aHeight ;
2012-09-28 10:57:33 +04:00
uint32_t minSizeDelta = UINT32_MAX ;
2012-09-05 05:01:56 +04:00
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 ;
}
}
2012-07-31 01:59:05 +04:00
}
2012-09-05 05:01:56 +04:00
mWidth = bestWidth ;
mHeight = bestHeight ;
mParams . setPreviewSize ( mWidth , mHeight ) ;
PushParameters ( ) ;
2012-07-31 01:59:05 +04:00
}
2012-09-29 09:30:52 +04:00
nsresult
nsGonkCameraControl : : SetupVideoMode ( )
{
// read preferences for camcorder
mMediaProfiles = MediaProfiles : : getInstance ( ) ;
/**
* Right now default to profile 3 , which is 352 x288 on Otoro . In the
* future , allow the application to select a recording quality and
* configuration .
*
* See bug 795379.
*/
int quality = 3 ; // cif:352x288
camcorder_quality q = static_cast < camcorder_quality > ( quality ) ;
mDuration = mMediaProfiles - > getCamcorderProfileParamByName ( " duration " , ( int ) mCameraId , q ) ;
mVideoFileFormat = mMediaProfiles - > getCamcorderProfileParamByName ( " file.format " , ( int ) mCameraId , q ) ;
mVideoCodec = mMediaProfiles - > getCamcorderProfileParamByName ( " vid.codec " , ( int ) mCameraId , q ) ;
mVideoBitRate = mMediaProfiles - > getCamcorderProfileParamByName ( " vid.bps " , ( int ) mCameraId , q ) ;
mVideoFrameRate = mMediaProfiles - > getCamcorderProfileParamByName ( " vid.fps " , ( int ) mCameraId , q ) ;
mVideoFrameWidth = mMediaProfiles - > getCamcorderProfileParamByName ( " vid.width " , ( int ) mCameraId , q ) ;
mVideoFrameHeight = mMediaProfiles - > getCamcorderProfileParamByName ( " vid.height " , ( int ) mCameraId , q ) ;
mAudioCodec = mMediaProfiles - > getCamcorderProfileParamByName ( " aud.codec " , ( int ) mCameraId , q ) ;
mAudioBitRate = mMediaProfiles - > getCamcorderProfileParamByName ( " aud.bps " , ( int ) mCameraId , q ) ;
mAudioSampleRate = mMediaProfiles - > getCamcorderProfileParamByName ( " aud.hz " , ( int ) mCameraId , q ) ;
mAudioChannels = mMediaProfiles - > getCamcorderProfileParamByName ( " aud.ch " , ( int ) mCameraId , q ) ;
if ( mVideoFrameRate = = - 1 ) {
DOM_CAMERA_LOGE ( " Failed to get a valid frame rate! \n " ) ;
DOM_CAMERA_LOGE ( " Also got width=%d, height=%d \n " , mVideoFrameWidth , mVideoFrameHeight ) ;
return NS_ERROR_FAILURE ;
}
PullParametersImpl ( ) ;
// Configure camera video recording parameters.
const size_t SIZE = 256 ;
char buffer [ SIZE ] ;
/**
* Ignore the width and height settings from app , just use the one in profile .
* Eventually , will try to choose a profile which respects the settings from app .
* See bug 795330.
*/
mParams . setPreviewSize ( mVideoFrameWidth , mVideoFrameHeight ) ;
mParams . setPreviewFrameRate ( mVideoFrameRate ) ;
snprintf ( buffer , SIZE , " %dx%d " , mVideoFrameWidth , mVideoFrameHeight ) ;
/**
* " record-size " is probably deprecated in later ICS ;
* might need to set " video-size " instead of " record-size " .
* See bug 795332.
*/
mParams . set ( " record-size " , buffer ) ;
/**
* If we want to enable picture - taking _while_ recording video , this sets the
* size of the captured picture . For now , just set it to the same dimensions
* as the video we ' re recording ; ideally , we should probably make sure it
* matches one of the supported picture sizes .
*/
mParams . setPictureSize ( mVideoFrameWidth , mVideoFrameHeight ) ;
PushParametersImpl ( ) ;
return NS_OK ;
}
# ifndef CHECK_SETARG
# define CHECK_SETARG(x) \
do { \
if ( x ) { \
DOM_CAMERA_LOGE ( # x " failed \n " ) ; \
return NS_ERROR_INVALID_ARG ; \
} \
} while ( 0 )
# endif
nsresult
nsGonkCameraControl : : SetupRecording ( int aFd )
{
// choosing a size big enough to hold the params
const size_t SIZE = 256 ;
char buffer [ SIZE ] ;
mRecorder = new GonkRecorder ( ) ;
CHECK_SETARG ( mRecorder - > init ( ) ) ;
// set all the params
CHECK_SETARG ( mRecorder - > setCameraHandle ( ( int32_t ) mHwHandle ) ) ;
CHECK_SETARG ( mRecorder - > setAudioSource ( AUDIO_SOURCE_CAMCORDER ) ) ;
CHECK_SETARG ( mRecorder - > setVideoSource ( VIDEO_SOURCE_CAMERA ) ) ;
CHECK_SETARG ( mRecorder - > setOutputFormat ( ( output_format ) mVideoFileFormat ) ) ;
CHECK_SETARG ( mRecorder - > setVideoFrameRate ( mVideoFrameRate ) ) ;
CHECK_SETARG ( mRecorder - > setVideoSize ( mVideoFrameWidth , mVideoFrameHeight ) ) ;
snprintf ( buffer , SIZE , " video-param-encoding-bitrate=%d " , mVideoBitRate ) ;
CHECK_SETARG ( mRecorder - > setParameters ( String8 ( buffer ) ) ) ;
CHECK_SETARG ( mRecorder - > setVideoEncoder ( ( video_encoder ) mVideoCodec ) ) ;
snprintf ( buffer , SIZE , " audio-param-encoding-bitrate=%d " , mAudioBitRate ) ;
CHECK_SETARG ( mRecorder - > setParameters ( String8 ( buffer ) ) ) ;
snprintf ( buffer , SIZE , " audio-param-number-of-channels=%d " , mAudioChannels ) ;
CHECK_SETARG ( mRecorder - > setParameters ( String8 ( buffer ) ) ) ;
snprintf ( buffer , SIZE , " audio-param-sampling-rate=%d " , mAudioSampleRate ) ;
CHECK_SETARG ( mRecorder - > setParameters ( String8 ( buffer ) ) ) ;
CHECK_SETARG ( mRecorder - > setAudioEncoder ( ( audio_encoder ) mAudioCodec ) ) ;
// TODO: For now there is no limit on recording duration (See bug 795090)
CHECK_SETARG ( mRecorder - > setParameters ( String8 ( " max-duration=-1 " ) ) ) ;
// TODO: For now there is no limit on file size (See bug 795090)
CHECK_SETARG ( mRecorder - > setParameters ( String8 ( " max-filesize=-1 " ) ) ) ;
snprintf ( buffer , SIZE , " video-param-rotation-angle-degrees=%d " , mVideoRotation ) ;
CHECK_SETARG ( mRecorder - > setParameters ( String8 ( buffer ) ) ) ;
// recording API needs file descriptor of output file
CHECK_SETARG ( mRecorder - > setOutputFile ( aFd , 0 , 0 ) ) ;
CHECK_SETARG ( mRecorder - > prepare ( ) ) ;
return NS_OK ;
}
nsresult
nsGonkCameraControl : : GetPreviewStreamVideoModeImpl ( GetPreviewStreamVideoModeTask * aGetPreviewStreamVideoMode )
{
nsCOMPtr < GetPreviewStreamResult > getPreviewStreamResult = nullptr ;
// stop any currently running preview
StopPreviewInternal ( true /* forced */ ) ;
// copy the recording preview options
mVideoRotation = aGetPreviewStreamVideoMode - > mOptions . rotation ;
mVideoWidth = aGetPreviewStreamVideoMode - > mOptions . width ;
mVideoHeight = aGetPreviewStreamVideoMode - > mOptions . height ;
DOM_CAMERA_LOGI ( " recording preview format: %d x %d (w x h) (rotated %d degrees) \n " , mVideoWidth , mVideoHeight , mVideoRotation ) ;
// setup the video mode
nsresult rv = SetupVideoMode ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// create and return new preview stream object
getPreviewStreamResult = new GetPreviewStreamResult ( this , mVideoWidth , mVideoHeight , mVideoFrameRate , aGetPreviewStreamVideoMode - > mOnSuccessCb ) ;
rv = NS_DispatchToMainThread ( getPreviewStreamResult ) ;
if ( NS_FAILED ( rv ) ) {
NS_WARNING ( " Failed to dispatch GetPreviewStreamVideoMode() onSuccess callback to main thread! " ) ;
return rv ;
}
return NS_OK ;
}
2012-07-31 01:59:05 +04:00
// Gonk callback handlers.
namespace mozilla {
void
2012-08-22 19:56:38 +04:00
ReceiveImage ( nsGonkCameraControl * gc , uint8_t * aData , uint32_t aLength )
2012-07-31 01:59:05 +04:00
{
gc - > TakePictureComplete ( aData , aLength ) ;
}
void
2012-09-05 05:01:56 +04:00
AutoFocusComplete ( nsGonkCameraControl * gc , bool aSuccess )
{
gc - > AutoFocusComplete ( aSuccess ) ;
}
static void
GonkFrameBuilder ( Image * aImage , void * aBuffer , uint32_t aWidth , uint32_t aHeight )
2012-07-31 01:59:05 +04:00
{
2012-09-05 05:01:56 +04:00
/**
* 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 ) ;
2012-07-31 01:59:05 +04:00
}
void
2012-09-05 05:01:56 +04:00
ReceiveFrame ( nsGonkCameraControl * gc , layers : : GraphicBufferLocked * aBuffer )
2012-07-31 01:59:05 +04:00
{
2012-09-08 00:23:01 +04:00
if ( ! gc - > ReceiveFrame ( aBuffer , ImageFormat : : GONK_IO_SURFACE , GonkFrameBuilder ) ) {
aBuffer - > Unlock ( ) ;
}
2012-07-31 01:59:05 +04:00
}
} // namespace mozilla