mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 818933 - Provide a hardware release API so that we don't have to rely on CC of CameraControl objects. r=mhabicher
This commit is contained in:
parent
2b635dfd91
commit
518afe6c97
@ -367,6 +367,13 @@ CameraControlImpl::GetPreviewStreamVideoMode(CameraRecorderOptions* aOptions, ns
|
||||
return mCameraThread->Dispatch(getPreviewStreamVideoModeTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraControlImpl::ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> releaseHardwareTask = new ReleaseHardwareTask(this, onSuccess, onError);
|
||||
return mCameraThread->Dispatch(releaseHardwareTask, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
bool
|
||||
CameraControlImpl::ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder)
|
||||
{
|
||||
|
@ -27,6 +27,7 @@ class StopRecordingTask;
|
||||
class SetParameterTask;
|
||||
class GetParameterTask;
|
||||
class GetPreviewStreamVideoModeTask;
|
||||
class ReleaseHardwareTask;
|
||||
|
||||
class DOMCameraPreview;
|
||||
class RecorderProfileManager;
|
||||
@ -43,6 +44,7 @@ class CameraControlImpl : public ICameraControl
|
||||
friend class SetParameterTask;
|
||||
friend class GetParameterTask;
|
||||
friend class GetPreviewStreamVideoModeTask;
|
||||
friend class ReleaseHardwareTask;
|
||||
|
||||
public:
|
||||
CameraControlImpl(uint32_t aCameraId, nsIThread* aCameraThread, uint64_t aWindowId);
|
||||
@ -55,6 +57,7 @@ public:
|
||||
nsresult StartRecording(dom::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError);
|
||||
nsresult StopRecording();
|
||||
nsresult GetPreviewStreamVideoMode(dom::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);
|
||||
@ -117,6 +120,7 @@ protected:
|
||||
virtual nsresult PushParametersImpl() = 0;
|
||||
virtual nsresult PullParametersImpl() = 0;
|
||||
virtual nsresult GetPreviewStreamVideoModeImpl(GetPreviewStreamVideoModeTask* aGetPreviewStreamVideoMode) = 0;
|
||||
virtual nsresult ReleaseHardwareImpl(ReleaseHardwareTask* aReleaseHardware) = 0;
|
||||
virtual already_AddRefed<RecorderProfileManager> GetRecorderProfileManagerImpl() = 0;
|
||||
|
||||
void OnShutterInternal();
|
||||
@ -610,7 +614,73 @@ public:
|
||||
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
|
||||
};
|
||||
|
||||
// Error result runnable
|
||||
// Return the result of releasing the camera hardware. Runs on the main thread.
|
||||
class ReleaseHardwareResult : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ReleaseHardwareResult(nsICameraReleaseCallback* onSuccess, uint64_t aWindowId)
|
||||
: mOnSuccessCb(onSuccess)
|
||||
, mWindowId(aWindowId)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~ReleaseHardwareResult()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mOnSuccessCb && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
|
||||
mOnSuccessCb->HandleEvent();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsICameraReleaseCallback> mOnSuccessCb;
|
||||
uint64_t mWindowId;
|
||||
};
|
||||
|
||||
// Release the camera hardware.
|
||||
class ReleaseHardwareTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ReleaseHardwareTask(CameraControlImpl* aCameraControl, nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
: mCameraControl(aCameraControl)
|
||||
, mOnSuccessCb(onSuccess)
|
||||
, mOnErrorCb(onError)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
virtual ~ReleaseHardwareTask()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
nsresult rv = mCameraControl->ReleaseHardwareImpl(this);
|
||||
DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
|
||||
|
||||
if (NS_FAILED(rv) && mOnErrorCb) {
|
||||
rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE"), mCameraControl->GetWindowId()));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<CameraControlImpl> mCameraControl;
|
||||
nsCOMPtr<nsICameraReleaseCallback> mOnSuccessCb;
|
||||
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
|
||||
};
|
||||
|
||||
// Report that the video recorder state has changed.
|
||||
class CameraRecorderStateChange : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -373,6 +373,12 @@ nsDOMCameraControl::GetPreviewStreamVideoMode(const JS::Value& aOptions, nsICame
|
||||
return mCameraControl->GetPreviewStreamVideoMode(&options, onSuccess, onError);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMCameraControl::ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError)
|
||||
{
|
||||
return mCameraControl->ReleaseHardware(onSuccess, onError);
|
||||
}
|
||||
|
||||
class GetCameraResult : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -212,7 +212,7 @@ DOMCameraPreview::Start()
|
||||
* This reference is removed in SetStateStopped().
|
||||
*/
|
||||
NS_ADDREF_THIS();
|
||||
mState = STARTING;
|
||||
DOM_CAMERA_SETSTATE(STARTING);
|
||||
mCameraControl->StartPreview(this);
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ DOMCameraPreview::SetStateStarted()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "SetStateStarted() not called from main thread");
|
||||
|
||||
mState = STARTED;
|
||||
DOM_CAMERA_SETSTATE(STARTED);
|
||||
DOM_CAMERA_LOGI("Preview stream started\n");
|
||||
}
|
||||
|
||||
@ -249,7 +249,7 @@ DOMCameraPreview::StopPreview()
|
||||
}
|
||||
|
||||
DOM_CAMERA_LOGI("Stopping preview stream\n");
|
||||
mState = STOPPING;
|
||||
DOM_CAMERA_SETSTATE(STOPPING);
|
||||
mCameraControl->StopPreview();
|
||||
mInput->EndTrack(TRACK_VIDEO);
|
||||
mInput->Finish();
|
||||
@ -265,7 +265,7 @@ DOMCameraPreview::SetStateStopped()
|
||||
mInput->EndTrack(TRACK_VIDEO);
|
||||
mInput->Finish();
|
||||
}
|
||||
mState = STOPPED;
|
||||
DOM_CAMERA_SETSTATE(STOPPED);
|
||||
DOM_CAMERA_LOGI("Preview stream stopped\n");
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "nsDOMMediaStream.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef void (*FrameBuilder)(mozilla::layers::Image* aImage, void* aBuffer, uint32_t aWidth, uint32_t aHeight);
|
||||
@ -57,6 +56,23 @@ protected:
|
||||
};
|
||||
uint32_t mState;
|
||||
|
||||
// Helper function, used in conjunction with the macro below, to make
|
||||
// it easy to track state changes, which must happen only on the main
|
||||
// thread.
|
||||
void
|
||||
SetState(uint32_t aNewState, const char* aFileOrFunc, int aLine)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
const char* states[] = { "stopped", "starting", "started", "stopping" };
|
||||
MOZ_ASSERT(mState < sizeof(states) / sizeof(states[0]));
|
||||
MOZ_ASSERT(aNewState < sizeof(states) / sizeof(states[0]));
|
||||
DOM_CAMERA_LOGI("SetState: (this=%p) '%s' --> '%s' : %s:%d\n", this, states[mState], states[aNewState], aFileOrFunc, aLine);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(NS_IsMainThread(), "Preview state set OFF OF main thread!");
|
||||
mState = aNewState;
|
||||
}
|
||||
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mFramesPerSecond;
|
||||
@ -76,4 +92,6 @@ private:
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#define DOM_CAMERA_SETSTATE(newState) SetState((newState), __func__, __LINE__)
|
||||
|
||||
#endif // DOM_CAMERA_DOMCAMERAPREVIEW_H
|
||||
|
@ -282,7 +282,7 @@ nsGonkCameraControl::Init()
|
||||
nsGonkCameraControl::~nsGonkCameraControl()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p, mHwHandle = %d\n", __func__, __LINE__, this, mHwHandle);
|
||||
GonkCameraHardware::ReleaseHandle(mHwHandle);
|
||||
ReleaseHardwareImpl(nullptr);
|
||||
if (mRwLock) {
|
||||
PRRWLock* lock = mRwLock;
|
||||
mRwLock = nullptr;
|
||||
@ -1309,6 +1309,32 @@ nsGonkCameraControl::GetPreviewStreamVideoModeImpl(GetPreviewStreamVideoModeTask
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::ReleaseHardwareImpl(ReleaseHardwareTask* aReleaseHardware)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
// if we're recording, stop recording
|
||||
if (mRecorder) {
|
||||
DOM_CAMERA_LOGI("shutting down existing video recorder\n");
|
||||
mRecorder->stop();
|
||||
mRecorder = nullptr;
|
||||
}
|
||||
|
||||
// stop the preview
|
||||
StopPreviewInternal(true /* forced */);
|
||||
|
||||
// release the hardware handle
|
||||
GonkCameraHardware::ReleaseHandle(mHwHandle);
|
||||
|
||||
if (aReleaseHardware && aReleaseHardware->mOnSuccessCb) {
|
||||
nsCOMPtr<nsIRunnable> releaseHardwareResult = new ReleaseHardwareResult(aReleaseHardware->mOnSuccessCb, mWindowId);
|
||||
return NS_DispatchToMainThread(releaseHardwareResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<GonkRecorderProfileManager>
|
||||
nsGonkCameraControl::GetGonkRecorderProfileManager()
|
||||
{
|
||||
|
@ -76,6 +76,7 @@ protected:
|
||||
nsresult PushParametersImpl();
|
||||
nsresult PullParametersImpl();
|
||||
nsresult GetPreviewStreamVideoModeImpl(GetPreviewStreamVideoModeTask* aGetPreviewStreamVideoMode);
|
||||
nsresult ReleaseHardwareImpl(ReleaseHardwareTask* aReleaseHardware);
|
||||
already_AddRefed<RecorderProfileManager> GetRecorderProfileManagerImpl();
|
||||
already_AddRefed<GonkRecorderProfileManager> GetGonkRecorderProfileManager();
|
||||
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
virtual nsresult StartRecording(dom::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
|
||||
virtual nsresult StopRecording() = 0;
|
||||
virtual nsresult GetPreviewStreamVideoMode(dom::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;
|
||||
|
@ -241,6 +241,12 @@ interface nsICameraRecorderStateChange : nsISupports
|
||||
void handleStateChange(in DOMString newState);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(f84d607b-554c-413d-8810-cf848642765a)]
|
||||
interface nsICameraReleaseCallback : nsISupports
|
||||
{
|
||||
void handleEvent();
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(a302c6c9-3776-4d1d-a395-f4105d47c3d3)]
|
||||
interface nsICameraErrorCallback : nsISupports
|
||||
{
|
||||
@ -251,7 +257,7 @@ interface nsICameraErrorCallback : nsISupports
|
||||
attributes here affect the preview, any pictures taken, and/or
|
||||
any video recorded by the camera.
|
||||
*/
|
||||
[scriptable, uuid(70f45209-b69b-4937-bbac-57d82600e2af)]
|
||||
[scriptable, uuid(c8e7418d-8913-4b66-bd9f-562fba627266)]
|
||||
interface nsICameraControl : nsISupports
|
||||
{
|
||||
readonly attribute nsICameraCapabilities capabilities;
|
||||
@ -391,6 +397,17 @@ interface nsICameraControl : nsISupports
|
||||
/* call in or after the takePicture() onSuccess callback to
|
||||
resume the camera preview stream. */
|
||||
void resumePreview();
|
||||
|
||||
/* release the camera so that other applications can use it; you should
|
||||
probably call this whenever the camera is not longer in the foreground
|
||||
(depending on your usage model).
|
||||
|
||||
the callbacks are optional, unless you really need to know when
|
||||
the hardware is ultimately released.
|
||||
|
||||
once this is called, the camera control object is to be considered
|
||||
defunct; a new instance will need to be created to access the camera. */
|
||||
[binaryname(ReleaseHardware)] void release([optional] in nsICameraReleaseCallback onSuccess, [optional] in nsICameraErrorCallback onError);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(a267afbc-d91c-413a-8de5-0b94aecffa3e)]
|
||||
|
Loading…
Reference in New Issue
Block a user