Bug 910498 - Camera changes to use CreateFd. r=mikeh

This commit is contained in:
Dave Hylands 2014-01-16 17:01:43 -08:00
Родитель 00a803aa36
Коммит 9cf076ba4e
6 изменённых файлов: 87 добавлений и 53 удалений

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

@ -450,12 +450,9 @@ CameraControlImpl::TakePicture(const CameraSize& aSize, int32_t aRotation, const
}
nsresult
CameraControlImpl::StartRecording(CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
CameraControlImpl::StartRecording(CameraStartRecordingOptions* aOptions, DeviceStorageFileDescriptor* aFileDescriptor, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
{
nsCOMPtr<nsIFile> clone;
aFolder->Clone(getter_AddRefs(clone));
nsCOMPtr<nsIRunnable> startRecordingTask = new StartRecordingTask(this, *aOptions, clone, aFilename, onSuccess, onError, mWindowId);
nsCOMPtr<nsIRunnable> startRecordingTask = new StartRecordingTask(this, *aOptions, aFileDescriptor, onSuccess, onError, mWindowId);
return mCameraThread->Dispatch(startRecordingTask, NS_DISPATCH_NORMAL);
}

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

@ -14,6 +14,9 @@
#include "DOMCameraPreview.h"
#include "ICameraControl.h"
#include "CameraCommon.h"
#include "DeviceStorage.h"
class DeviceStorageFileDescriptor;
namespace mozilla {
@ -54,7 +57,7 @@ public:
void StopPreview();
nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError);
nsresult TakePicture(const idl::CameraSize& aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError);
nsresult StartRecording(idl::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError);
nsresult StartRecording(idl::CameraStartRecordingOptions* aOptions, DeviceStorageFileDescriptor *aDSFileDescriptor, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError);
nsresult StopRecording();
nsresult GetPreviewStreamVideoMode(idl::CameraRecorderOptions* aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError);
nsresult ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError);
@ -452,11 +455,15 @@ protected:
class StartRecordingTask : public nsRunnable
{
public:
StartRecordingTask(CameraControlImpl* aCameraControl, idl::CameraStartRecordingOptions aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId)
StartRecordingTask(CameraControlImpl* aCameraControl,
idl::CameraStartRecordingOptions aOptions,
DeviceStorageFileDescriptor *aDSFileDescriptor,
nsICameraStartRecordingCallback* onSuccess,
nsICameraErrorCallback* onError,
uint64_t aWindowId)
: mCameraControl(aCameraControl)
, mOptions(aOptions)
, mFolder(aFolder)
, mFilename(aFilename)
, mDSFileDescriptor(aDSFileDescriptor)
, mOnSuccessCb(new nsMainThreadPtrHolder<nsICameraStartRecordingCallback>(onSuccess))
, mOnErrorCb(new nsMainThreadPtrHolder<nsICameraErrorCallback>(onError))
, mWindowId(aWindowId)
@ -491,8 +498,7 @@ public:
nsRefPtr<CameraControlImpl> mCameraControl;
idl::CameraStartRecordingOptions mOptions;
nsCOMPtr<nsIFile> mFolder;
nsString mFilename;
nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
nsMainThreadPtrHandle<nsICameraStartRecordingCallback> mOnSuccessCb;
nsMainThreadPtrHandle<nsICameraErrorCallback> mOnErrorCb;
uint64_t mWindowId;

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

@ -349,13 +349,12 @@ nsDOMCameraControl::StartRecording(JSContext* aCx,
ErrorResult& aRv)
{
MOZ_ASSERT(onSuccess, "no onSuccess handler passed");
mozilla::idl::CameraStartRecordingOptions options;
// Default values, until the dictionary parser can handle them.
options.rotation = 0;
options.maxFileSizeBytes = 0;
options.maxVideoLengthMs = 0;
aRv = options.Init(aCx, aOptions.address());
mOptions.rotation = 0;
mOptions.maxFileSizeBytes = 0;
mOptions.maxVideoLengthMs = 0;
aRv = mOptions.Init(aCx, aOptions.address());
if (aRv.Failed()) {
return;
}
@ -375,13 +374,53 @@ nsDOMCameraControl::StartRecording(JSContext* aCx,
}
#endif
nsCOMPtr<nsIFile> folder;
aRv = storageArea.GetRootDirectoryForFile(filename, getter_AddRefs(folder));
nsCOMPtr<nsIDOMDOMRequest> request;
mDSFileDescriptor = new DeviceStorageFileDescriptor();
aRv = storageArea.CreateFileDescriptor(filename, mDSFileDescriptor.get(),
getter_AddRefs(request));
if (aRv.Failed()) {
return;
}
aRv = mCameraControl->StartRecording(&options, folder, filename, onSuccess,
onError.WasPassed() ? onError.Value() : nullptr);
mOnSuccessCb = onSuccess;
mOnErrorCb = onError.WasPassed() ? onError.Value() : nullptr;
request->AddEventListener(NS_LITERAL_STRING("success"), this, false);
request->AddEventListener(NS_LITERAL_STRING("error"), this, false);
}
NS_IMETHODIMP
nsDOMCameraControl::HandleEvent(nsIDOMEvent* aEvent)
{
nsString eventType;
aEvent->GetType(eventType);
ErrorResult rv;
if ((eventType.EqualsLiteral("success")) &&
mDSFileDescriptor->mFileDescriptor.IsValid()) {
rv = mCameraControl->StartRecording(&mOptions,
mDSFileDescriptor.get(),
mOnSuccessCb.get(),
mOnErrorCb.get());
if (!rv.Failed()) {
return rv.ErrorCode();
}
// An error happened. Fall through and call the error callback.
}
// We're already be on the main thread, so go ahead and call the
// error callback directly.
MOZ_ASSERT(NS_IsMainThread());
if (mOnErrorCb &&
nsDOMCameraManager::IsWindowStillActive(mWindow->WindowID())) {
mOnErrorCb->HandleEvent(NS_LITERAL_STRING("FAILURE"));
}
return NS_OK;
}
void

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

@ -8,6 +8,7 @@
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMEventListener.h"
#include "DictionaryHelpers.h"
#include "ICameraControl.h"
#include "DOMCameraPreview.h"
@ -16,6 +17,7 @@
#include "AudioChannelAgent.h"
#include "nsProxyRelease.h"
#include "nsHashPropertyBag.h"
#include "DeviceStorage.h"
class nsDOMDeviceStorage;
class nsPIDOMWindow;
@ -28,11 +30,12 @@ template<typename T> class Optional;
class ErrorResult;
// Main camera control.
class nsDOMCameraControl MOZ_FINAL : public nsISupports,
class nsDOMCameraControl MOZ_FINAL : public nsIDOMEventListener,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMCameraControl)
nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread,
@ -107,6 +110,11 @@ private:
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
nsresult NotifyRecordingStatusChange(const nsString& aMsg);
mozilla::idl::CameraStartRecordingOptions mOptions;
nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
nsCOMPtr<nsICameraStartRecordingCallback> mOnSuccessCb;
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
protected:
/* additional members */
nsRefPtr<ICameraControl> mCameraControl; // non-DOM camera control

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

@ -1023,7 +1023,7 @@ nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
// is meant to be stored as a local time. Since we are given seconds from
// Epoch GMT, we use localtime_r() to handle the conversion.
time_t time = aTakePicture->mDateTime;
if (time != aTakePicture->mDateTime) {
if ((uint64_t)time != aTakePicture->mDateTime) {
DOM_CAMERA_LOGE("picture date/time '%llu' is too far in the future\n", aTakePicture->mDateTime);
} else {
struct tm t;
@ -1097,42 +1097,24 @@ nsGonkCameraControl::StartRecordingImpl(StartRecordingTask* aStartRecording)
* The camera app needs to provide the file extension '.3gp' for now.
* See bug 795202.
*/
nsCOMPtr<nsIFile> filename = aStartRecording->mFolder;
filename->AppendRelativePath(aStartRecording->mFilename);
nsString fullpath;
filename->GetPath(fullpath);
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE);
nsCOMPtr<nsIVolume> vol;
nsresult rv = vs->GetVolumeByPath(fullpath, getter_AddRefs(vol));
NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG);
nsString volName;
vol->GetName(volName);
mVideoFile = new DeviceStorageFile(NS_LITERAL_STRING("videos"),
volName,
aStartRecording->mFilename);
nsAutoCString nativeFilename;
filename->GetNativePath(nativeFilename);
DOM_CAMERA_LOGI("Video filename is '%s'\n", nativeFilename.get());
nsRefPtr<DeviceStorageFileDescriptor> dsfd = aStartRecording->mDSFileDescriptor;
NS_ENSURE_TRUE(dsfd, NS_ERROR_FAILURE);
nsAutoString fullPath;
mVideoFile = dsfd->mDSFile;
mVideoFile->GetFullPath(fullPath);
DOM_CAMERA_LOGI("Video filename is '%s'\n",
NS_LossyConvertUTF16toASCII(fullPath).get());
if (!mVideoFile->IsSafePath()) {
DOM_CAMERA_LOGE("Invalid video file name\n");
return NS_ERROR_INVALID_ARG;
}
ScopedClose fd(open(nativeFilename.get(), O_RDWR | O_CREAT, 0644));
if (fd < 0) {
DOM_CAMERA_LOGE("Couldn't create file '%s': (%d) %s\n", nativeFilename.get(), errno, strerror(errno));
return NS_ERROR_FAILURE;
}
rv = SetupRecording(fd, aStartRecording->mOptions.rotation, aStartRecording->mOptions.maxFileSizeBytes, aStartRecording->mOptions.maxVideoLengthMs);
nsresult rv;
rv = SetupRecording(dsfd->mFileDescriptor.PlatformHandle(),
aStartRecording->mOptions.rotation,
aStartRecording->mOptions.maxFileSizeBytes,
aStartRecording->mOptions.maxVideoLengthMs);
NS_ENSURE_SUCCESS(rv, rv);
if (mRecorder->start() != OK) {

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

@ -10,6 +10,8 @@
#include "DictionaryHelpers.h"
#include "CameraCommon.h"
class DeviceStorageFileDescriptor;
namespace mozilla {
class DOMCameraPreview;
@ -25,7 +27,7 @@ public:
virtual void StopPreview() = 0;
virtual nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
virtual nsresult TakePicture(const idl::CameraSize& aSize, int32_t aRotation, const nsAString& aFileFormat, idl::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
virtual nsresult StartRecording(idl::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
virtual nsresult StartRecording(idl::CameraStartRecordingOptions* aOptions, DeviceStorageFileDescriptor *aFileDescriptor, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
virtual nsresult StopRecording() = 0;
virtual nsresult GetPreviewStreamVideoMode(idl::CameraRecorderOptions* aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
virtual nsresult ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError) = 0;