author | Dave Hylands <dhylands@mozilla.com> |
Thu, 16 Jan 2014 17:01:43 -0800 | |
changeset 164548 | 2b74b0de04a4c7244ea1b53afe92bbb269a3b59c |
parent 164547 | 4a1217f771c1646969eea35f7aa346972d9d37e4 |
child 164549 | 585ff8eb2be77d01dc6d8a7a01fd5ca66ffcda25 |
push id | 38744 |
push user | kwierso@gmail.com |
push date | Wed, 22 Jan 2014 01:36:02 +0000 |
treeherder | mozilla-inbound@554475555e21 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mikeh |
bugs | 910498 |
milestone | 29.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/camera/CameraControlImpl.cpp +++ b/dom/camera/CameraControlImpl.cpp @@ -4,16 +4,17 @@ #include "base/basictypes.h" #include "mozilla/Assertions.h" #include "DOMCameraPreview.h" #include "CameraRecorderProfiles.h" #include "CameraControlImpl.h" #include "CameraCommon.h" #include "nsGlobalWindow.h" +#include "DeviceStorageFileDescriptor.h" using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::idl; CameraControlImpl::CameraControlImpl(uint32_t aCameraId, nsIThread* aCameraThread, uint64_t aWindowId) : mCameraId(aCameraId) , mCameraThread(aCameraThread) @@ -445,22 +446,19 @@ CameraControlImpl::TakePicture(const Cam cancel = true; } nsCOMPtr<nsIRunnable> takePictureTask = new TakePictureTask(this, cancel, aSize, aRotation, aFileFormat, aPosition, aDateTime, onSuccess, onError); return mCameraThread->Dispatch(takePictureTask, NS_DISPATCH_NORMAL); } 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); } nsresult CameraControlImpl::StopRecording() { nsCOMPtr<nsIRunnable> stopRecordingTask = new StopRecordingTask(this); return mCameraThread->Dispatch(stopRecordingTask, NS_DISPATCH_NORMAL);
--- a/dom/camera/CameraControlImpl.h +++ b/dom/camera/CameraControlImpl.h @@ -9,16 +9,20 @@ #include "nsDOMFile.h" #include "nsProxyRelease.h" #include "DictionaryHelpers.h" #include "nsIDOMDeviceStorage.h" #include "DOMCameraManager.h" #include "DOMCameraPreview.h" #include "ICameraControl.h" #include "CameraCommon.h" +#include "DeviceStorage.h" +#include "DeviceStorageFileDescriptor.h" + +class DeviceStorageFileDescriptor; namespace mozilla { class GetPreviewStreamTask; class StartPreviewTask; class StopPreviewTask; class AutoFocusTask; class TakePictureTask; @@ -49,17 +53,17 @@ class CameraControlImpl : public ICamera public: CameraControlImpl(uint32_t aCameraId, nsIThread* aCameraThread, uint64_t aWindowId); nsresult GetPreviewStream(idl::CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError); nsresult StartPreview(DOMCameraPreview* aDOMPreview); 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); nsresult Set(uint32_t aKey, const nsAString& aValue); nsresult Get(uint32_t aKey, nsAString& aValue); nsresult Set(uint32_t aKey, double aValue); nsresult Get(uint32_t aKey, double* aValue); @@ -447,21 +451,25 @@ protected: nsMainThreadPtrHandle<nsICameraStartRecordingCallback> mOnSuccessCb; uint64_t mWindowId; }; // Start video recording. 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) { DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); } virtual ~StartRecordingTask() @@ -486,18 +494,17 @@ public: if (NS_FAILED(rv)) { DOM_CAMERA_LOGE("Failed to dispatch start recording result to main thread (%d)!", rv); } return rv; } nsRefPtr<CameraControlImpl> mCameraControl; idl::CameraStartRecordingOptions mOptions; - nsCOMPtr<nsIFile> mFolder; - nsString mFilename; + nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor; nsMainThreadPtrHandle<nsICameraStartRecordingCallback> mOnSuccessCb; nsMainThreadPtrHandle<nsICameraErrorCallback> mOnErrorCb; uint64_t mWindowId; }; // Stop video recording. class StopRecordingTask : public nsRunnable {
--- a/dom/camera/DOMCameraControl.cpp +++ b/dom/camera/DOMCameraControl.cpp @@ -3,16 +3,17 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "base/basictypes.h" #include "nsCOMPtr.h" #include "nsDOMClassInfo.h" #include "nsHashPropertyBag.h" #include "nsThread.h" #include "DeviceStorage.h" +#include "DeviceStorageFileDescriptor.h" #include "mozilla/dom/CameraControlBinding.h" #include "mozilla/dom/TabChild.h" #include "mozilla/MediaManager.h" #include "mozilla/Services.h" #include "mozilla/unused.h" #include "nsIAppsService.h" #include "nsIObserverService.h" #include "nsIDOMDeviceStorage.h" @@ -344,23 +345,22 @@ nsDOMCameraControl::StartRecording(JSCon JS::Handle<JS::Value> aOptions, nsDOMDeviceStorage& storageArea, const nsAString& filename, nsICameraStartRecordingCallback* onSuccess, const Optional<nsICameraErrorCallback*>& onError, 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; } aRv = NotifyRecordingStatusChange(NS_LITERAL_STRING("starting")); #ifdef MOZ_B2G if (!mAudioChannelAgent) { @@ -370,23 +370,63 @@ nsDOMCameraControl::StartRecording(JSCon mAudioChannelAgent->Init(AUDIO_CHANNEL_CONTENT, nullptr); // Video recording doesn't output any sound, so it's not necessary to check canPlay. int32_t canPlay; mAudioChannelAgent->StartPlaying(&canPlay); } } #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 nsDOMCameraControl::StopRecording(ErrorResult& aRv) { aRv = NotifyRecordingStatusChange(NS_LITERAL_STRING("shutdown")); #ifdef MOZ_B2G
--- a/dom/camera/DOMCameraControl.h +++ b/dom/camera/DOMCameraControl.h @@ -3,41 +3,44 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef DOM_CAMERA_DOMCAMERACONTROL_H #define DOM_CAMERA_DOMCAMERACONTROL_H #include "nsCOMPtr.h" #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" +#include "nsIDOMEventListener.h" #include "DictionaryHelpers.h" #include "ICameraControl.h" #include "DOMCameraPreview.h" #include "nsIDOMCameraManager.h" #include "CameraCommon.h" #include "AudioChannelAgent.h" #include "nsProxyRelease.h" #include "nsHashPropertyBag.h" +#include "DeviceStorage.h" class nsDOMDeviceStorage; class nsPIDOMWindow; namespace mozilla { namespace dom { class CameraPictureOptions; 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, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, nsPIDOMWindow* aWindow); nsresult Result(nsresult aResult, const nsMainThreadPtrHandle<nsICameraGetCameraCallback>& onSuccess, const nsMainThreadPtrHandle<nsICameraErrorCallback>& onError, @@ -102,16 +105,21 @@ protected: private: nsDOMCameraControl(const nsDOMCameraControl&) MOZ_DELETE; nsDOMCameraControl& operator=(const nsDOMCameraControl&) MOZ_DELETE; 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 nsCOMPtr<nsICameraCapabilities> mDOMCapabilities; // An agent used to join audio channel service. nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent; nsCOMPtr<nsPIDOMWindow> mWindow; };
--- a/dom/camera/GonkCameraControl.cpp +++ b/dom/camera/GonkCameraControl.cpp @@ -37,16 +37,17 @@ #include "nsIVolumeService.h" #include "DOMCameraManager.h" #include "GonkCameraHwMgr.h" #include "DOMCameraCapabilities.h" #include "DOMCameraControl.h" #include "GonkRecorderProfiles.h" #include "GonkCameraControl.h" #include "CameraCommon.h" +#include "DeviceStorageFileDescriptor.h" using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::layers; using namespace android; using mozilla::gfx::IntSize; /** @@ -1018,17 +1019,17 @@ nsGonkCameraControl::TakePictureImpl(Tak SetParameter(CameraParameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aTakePicture->mPosition.timestamp).get()); } // Add the non-GPS timestamp. The EXIF date/time field is formatted as // "YYYY:MM:DD HH:MM:SS", without room for a time-zone; as such, the time // 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; if (localtime_r(&time, &t)) { char dateTime[20]; if (strftime(dateTime, sizeof(dateTime), "%Y:%m:%d %T", &t)) { DOM_CAMERA_LOGI("setting picture date/time to %s\n", dateTime); // Not every platform defines a CameraParameters::KEY_EXIF_DATETIME; @@ -1092,52 +1093,34 @@ nsGonkCameraControl::StartRecordingImpl( /** * Get the base path from device storage and append the app-specified * filename to it. The filename may include a relative subpath * (e.g.) "DCIM/IMG_0001.jpg". * * 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) { DOM_CAMERA_LOGE("mRecorder->start() failed\n"); // important: we MUST destroy the recorder if start() fails! mRecorder = nullptr; return NS_ERROR_FAILURE; }
--- a/dom/camera/ICameraControl.h +++ b/dom/camera/ICameraControl.h @@ -5,32 +5,34 @@ #ifndef DOM_CAMERA_ICAMERACONTROL_H #define DOM_CAMERA_ICAMERACONTROL_H #include "nsIFile.h" #include "nsIDOMCameraManager.h" #include "DictionaryHelpers.h" #include "CameraCommon.h" +class DeviceStorageFileDescriptor; + namespace mozilla { class DOMCameraPreview; class RecorderProfileManager; class ICameraControl { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ICameraControl) virtual nsresult GetPreviewStream(idl::CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError) = 0; virtual nsresult StartPreview(DOMCameraPreview* aDOMPreview) = 0; virtual void StopPreview() = 0; virtual nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError) = 0; virtual nsresult TakePicture(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; virtual nsresult Set(uint32_t aKey, const nsAString& aValue) = 0; virtual nsresult Get(uint32_t aKey, nsAString& aValue) = 0; virtual nsresult Set(uint32_t aKey, double aValue) = 0; virtual nsresult Get(uint32_t aKey, double* aValue) = 0;