summaryrefslogtreecommitdiffstats
path: root/tinyDAV/src/video/winm/tdav_producer_winm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'tinyDAV/src/video/winm/tdav_producer_winm.cxx')
-rwxr-xr-xtinyDAV/src/video/winm/tdav_producer_winm.cxx845
1 files changed, 394 insertions, 451 deletions
diff --git a/tinyDAV/src/video/winm/tdav_producer_winm.cxx b/tinyDAV/src/video/winm/tdav_producer_winm.cxx
index 398340a..3854cdc 100755
--- a/tinyDAV/src/video/winm/tdav_producer_winm.cxx
+++ b/tinyDAV/src/video/winm/tdav_producer_winm.cxx
@@ -1,17 +1,17 @@
/*Copyright (C) 2013 Doubango Telecom <http://www.doubango.org>
-*
+*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*/
@@ -44,88 +44,84 @@ struct tdav_producer_winm_s;
namespace Doubango
{
- namespace VoIP
- {
- class CaptureSampleSink :
- public Microsoft::WRL::RuntimeClass<
- Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>,
- ICameraCaptureSampleSink>
- {
- DWORD m_dwSampleCount;
- const struct tdav_producer_winm_s* m_pProducer;
-
- public:
-
- STDMETHODIMP RuntimeClassInitialize(const struct tdav_producer_winm_s* pProducer)
- {
- m_dwSampleCount = 0;
- m_pProducer = pProducer;
- return S_OK;
- }
+namespace VoIP
+{
+class CaptureSampleSink :
+ public Microsoft::WRL::RuntimeClass<
+ Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>,
+ ICameraCaptureSampleSink>
+{
+ DWORD m_dwSampleCount;
+ const struct tdav_producer_winm_s* m_pProducer;
- DWORD GetSampleCount()
- {
- return m_dwSampleCount;
- }
+public:
- IFACEMETHODIMP_(void)
- OnSampleAvailable(
- ULONGLONG hnsPresentationTime,
- ULONGLONG hnsSampleDuration,
- DWORD cbSample,
- BYTE* pSample)
- {
- m_dwSampleCount++;
- if(m_pProducer && TMEDIA_PRODUCER(m_pProducer)->enc_cb.callback)
- {
- TMEDIA_PRODUCER(m_pProducer)->enc_cb.callback(TMEDIA_PRODUCER(m_pProducer)->enc_cb.callback_data, pSample, cbSample);
- }
- }
- };
+ STDMETHODIMP RuntimeClassInitialize(const struct tdav_producer_winm_s* pProducer) {
+ m_dwSampleCount = 0;
+ m_pProducer = pProducer;
+ return S_OK;
+ }
- ref class VideoCapturePhone sealed
- {
- public:
- virtual ~VideoCapturePhone();
- internal:
- VideoCapturePhone();
+ DWORD GetSampleCount() {
+ return m_dwSampleCount;
+ }
- int Prepare(const struct tdav_producer_winm_s* winm);
- int Start();
- int Pause();
- int Stop();
- void SetCameraLocation(Windows::Phone::Media::Capture::CameraSensorLocation cameraLocation);
- void ToggleCamera();
+ IFACEMETHODIMP_(void)
+ OnSampleAvailable(
+ ULONGLONG hnsPresentationTime,
+ ULONGLONG hnsSampleDuration,
+ DWORD cbSample,
+ BYTE* pSample) {
+ m_dwSampleCount++;
+ if(m_pProducer && TMEDIA_PRODUCER(m_pProducer)->enc_cb.callback) {
+ TMEDIA_PRODUCER(m_pProducer)->enc_cb.callback(TMEDIA_PRODUCER(m_pProducer)->enc_cb.callback_data, pSample, cbSample);
+ }
+ }
+};
+
+ref class VideoCapturePhone sealed
+{
+public:
+ virtual ~VideoCapturePhone();
+internal:
+ VideoCapturePhone();
+
+ int Prepare(const struct tdav_producer_winm_s* winm);
+ int Start();
+ int Pause();
+ int Stop();
+ void SetCameraLocation(Windows::Phone::Media::Capture::CameraSensorLocation cameraLocation);
+ void ToggleCamera();
- private:
- int UnPrepare();
- void ToggleCameraThread(Windows::Foundation::IAsyncAction^ operation);
+private:
+ int UnPrepare();
+ void ToggleCameraThread(Windows::Foundation::IAsyncAction^ operation);
- tsk_mutex_handle_t* m_hMutex;
+ tsk_mutex_handle_t* m_hMutex;
- const tdav_producer_winm_s* m_pWrappedPlugin;
+ const tdav_producer_winm_s* m_pWrappedPlugin;
- // Has capture started?
- bool m_bStarted, m_bPrepared;
+ // Has capture started?
+ bool m_bStarted, m_bPrepared;
- // Events to signal whether capture has stopped/started
- HANDLE m_hStopCompleted;
- HANDLE m_hStartCompleted;
+ // Events to signal whether capture has stopped/started
+ HANDLE m_hStopCompleted;
+ HANDLE m_hStartCompleted;
- IAsyncOperation<AudioVideoCaptureDevice^> ^m_pOpenOperation;
+ IAsyncOperation<AudioVideoCaptureDevice^> ^m_pOpenOperation;
- Windows::Foundation::IAsyncAction^ m_ToggleThread;
+ Windows::Foundation::IAsyncAction^ m_ToggleThread;
- // Native sink and video device
- CaptureSampleSink *m_pVideoSink;
- IAudioVideoCaptureDeviceNative *m_pVideoDevice;
+ // Native sink and video device
+ CaptureSampleSink *m_pVideoSink;
+ IAudioVideoCaptureDeviceNative *m_pVideoDevice;
- Windows::Phone::Media::Capture::CameraSensorLocation m_eCameraLocation;
+ Windows::Phone::Media::Capture::CameraSensorLocation m_eCameraLocation;
- Windows::Phone::Media::Capture::AudioVideoCaptureDevice ^m_pVideoOnlyDevice;
- Windows::Foundation::IAsyncAction ^m_pVideoCaptureAction;
- };
- }
+ Windows::Phone::Media::Capture::AudioVideoCaptureDevice ^m_pVideoOnlyDevice;
+ Windows::Foundation::IAsyncAction ^m_pVideoCaptureAction;
+};
+}
}
using namespace Doubango::VoIP;
@@ -133,11 +129,10 @@ using namespace Doubango::VoIP;
#endif
-typedef struct tdav_producer_winm_s
-{
- TMEDIA_DECLARE_PRODUCER;
+typedef struct tdav_producer_winm_s {
+ TMEDIA_DECLARE_PRODUCER;
#if TDAV_UNDER_WINDOWS_PHONE
- VideoCapturePhone^ videoCapturePhone;
+ VideoCapturePhone^ videoCapturePhone;
#endif
}
tdav_producer_winm_t;
@@ -146,104 +141,103 @@ tdav_producer_winm_t;
/* ============ Media Producer Interface ================= */
static int tdav_producer_winm_set(tmedia_producer_t *self, const tmedia_param_t* param)
{
- int ret = 0;
- tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
-
- if(!producer || !param){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(param->value_type == tmedia_pvt_int32){
- if(tsk_striequals(param->key, "camera-location")){
- Windows::Phone::Media::Capture::CameraSensorLocation cameraLocation = (Windows::Phone::Media::Capture::CameraSensorLocation)*((int32_t*)param->value);
- if(producer->videoCapturePhone)
- {
- producer->videoCapturePhone->SetCameraLocation(cameraLocation);
- return 0;
- }
- }
- }
-
- return ret;
+ int ret = 0;
+ tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
+
+ if(!producer || !param) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(param->value_type == tmedia_pvt_int32) {
+ if(tsk_striequals(param->key, "camera-location")) {
+ Windows::Phone::Media::Capture::CameraSensorLocation cameraLocation = (Windows::Phone::Media::Capture::CameraSensorLocation)*((int32_t*)param->value);
+ if(producer->videoCapturePhone) {
+ producer->videoCapturePhone->SetCameraLocation(cameraLocation);
+ return 0;
+ }
+ }
+ }
+
+ return ret;
}
static int tdav_producer_winm_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
{
- tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
-
- if(!producer || !codec && codec->plugin){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(codec->id == tmedia_codec_id_h264_bp || codec->id == tmedia_codec_id_h264_mp) {
- TMEDIA_PRODUCER(producer)->encoder.codec_id = codec->id;
- }
- else {
- TMEDIA_PRODUCER(producer)->encoder.codec_id = tmedia_codec_id_none;
- }
- TMEDIA_PRODUCER(producer)->video.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps;
- TMEDIA_PRODUCER(producer)->video.width = TMEDIA_CODEC_VIDEO(codec)->out.width;
- TMEDIA_PRODUCER(producer)->video.height = TMEDIA_CODEC_VIDEO(codec)->out.height;
+ tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
+
+ if(!producer || !codec && codec->plugin) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(codec->id == tmedia_codec_id_h264_bp || codec->id == tmedia_codec_id_h264_mp) {
+ TMEDIA_PRODUCER(producer)->encoder.codec_id = codec->id;
+ }
+ else {
+ TMEDIA_PRODUCER(producer)->encoder.codec_id = tmedia_codec_id_none;
+ }
+ TMEDIA_PRODUCER(producer)->video.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps;
+ TMEDIA_PRODUCER(producer)->video.width = TMEDIA_CODEC_VIDEO(codec)->out.width;
+ TMEDIA_PRODUCER(producer)->video.height = TMEDIA_CODEC_VIDEO(codec)->out.height;
#if TDAV_UNDER_WINDOWS_PHONE
- return producer->videoCapturePhone->Prepare(producer);
+ return producer->videoCapturePhone->Prepare(producer);
#else
- TSK_DEBUG_ERROR("Unexpected code called");
- return -1;
+ TSK_DEBUG_ERROR("Unexpected code called");
+ return -1;
#endif
}
static int tdav_producer_winm_start(tmedia_producer_t* self)
{
- tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
+ tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
- if(!producer){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!producer) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
#if TDAV_UNDER_WINDOWS_PHONE
- return producer->videoCapturePhone->Start();
+ return producer->videoCapturePhone->Start();
#else
- TSK_DEBUG_ERROR("Unexpected code called");
- return -1;
+ TSK_DEBUG_ERROR("Unexpected code called");
+ return -1;
#endif
}
static int tdav_producer_winm_pause(tmedia_producer_t* self)
{
- tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
+ tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
- if(!producer){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!producer) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
#if TDAV_UNDER_WINDOWS_PHONE
- return producer->videoCapturePhone->Pause();
+ return producer->videoCapturePhone->Pause();
#else
- TSK_DEBUG_ERROR("Unexpected code called");
- return -1;
+ TSK_DEBUG_ERROR("Unexpected code called");
+ return -1;
#endif
}
static int tdav_producer_winm_stop(tmedia_producer_t* self)
{
- tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
+ tdav_producer_winm_t* producer = (tdav_producer_winm_t*)self;
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
#if TDAV_UNDER_WINDOWS_PHONE
- return producer->videoCapturePhone->Stop();
+ return producer->videoCapturePhone->Stop();
#else
- TSK_DEBUG_ERROR("Unexpected code called");
- return -1;
+ TSK_DEBUG_ERROR("Unexpected code called");
+ return -1;
#endif
}
@@ -252,273 +246,242 @@ static int tdav_producer_winm_stop(tmedia_producer_t* self)
VideoCapturePhone::VideoCapturePhone() :
m_bStarted(false),
- m_bPrepared(false),
+ m_bPrepared(false),
m_pVideoOnlyDevice(nullptr),
m_pVideoSink(NULL),
m_pVideoDevice(NULL),
- m_pWrappedPlugin(NULL),
- m_pOpenOperation(nullptr),
+ m_pWrappedPlugin(NULL),
+ m_pOpenOperation(nullptr),
m_eCameraLocation(CameraSensorLocation::Front)
{
- if(!(m_hMutex = tsk_mutex_create())){
- throw ref new Platform::FailureException(L"Failed to create mutex");
- }
+ if(!(m_hMutex = tsk_mutex_create())) {
+ throw ref new Platform::FailureException(L"Failed to create mutex");
+ }
m_hStopCompleted = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
- if (!m_hStopCompleted)
- {
+ if (!m_hStopCompleted) {
throw ref new Platform::Exception(HRESULT_FROM_WIN32(GetLastError()), L"Could not create shutdown event");
}
m_hStartCompleted = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
- if (!m_hStartCompleted)
- {
+ if (!m_hStartCompleted) {
throw ref new Platform::Exception(HRESULT_FROM_WIN32(GetLastError()), L"Could not create start event");
}
}
VideoCapturePhone::~VideoCapturePhone()
{
- Stop();
+ Stop();
- if(m_ToggleThread)
- {
+ if(m_ToggleThread) {
m_ToggleThread->Cancel();
m_ToggleThread->Close();
m_ToggleThread = nullptr;
}
- tsk_mutex_destroy(&m_hMutex);
+ tsk_mutex_destroy(&m_hMutex);
}
int VideoCapturePhone::Prepare(const struct tdav_producer_winm_s* winm)
{
- HRESULT hr = E_FAIL;
- int ret = 0;
- Windows::Foundation::Size dimensionsRequested, dimensionsClosest;
- Collections::IVectorView<Size> ^availableSizes;
- Collections::IIterator<Windows::Foundation::Size> ^availableSizesIterator;
- bool bClosestFound = false;
-
- #define WINM_SET_ERROR(code) ret = (code); goto bail;
-
- tsk_mutex_lock(m_hMutex);
-
- if(m_bPrepared)
- {
- TSK_DEBUG_INFO("#WASAPI: Audio producer already prepared");
- goto bail;
- }
-
- if(!winm)
- {
- TSK_DEBUG_ERROR("Invalid parameter");
- WINM_SET_ERROR(-1);
- }
-
- if(m_pVideoCaptureAction || m_pVideoDevice || m_pVideoOnlyDevice || m_pVideoSink || m_pOpenOperation){
- TSK_DEBUG_ERROR("Producer already prepared");
- WINM_SET_ERROR(-2);
- }
-
- dimensionsClosest.Width = dimensionsRequested.Width = (float)TMEDIA_PRODUCER(winm)->video.width;
- dimensionsClosest.Height = dimensionsRequested.Height = (float)TMEDIA_PRODUCER(winm)->video.height;
+ HRESULT hr = E_FAIL;
+ int ret = 0;
+ Windows::Foundation::Size dimensionsRequested, dimensionsClosest;
+ Collections::IVectorView<Size> ^availableSizes;
+ Collections::IIterator<Windows::Foundation::Size> ^availableSizesIterator;
+ bool bClosestFound = false;
+
+#define WINM_SET_ERROR(code) ret = (code); goto bail;
+
+ tsk_mutex_lock(m_hMutex);
+
+ if(m_bPrepared) {
+ TSK_DEBUG_INFO("#WASAPI: Audio producer already prepared");
+ goto bail;
+ }
+
+ if(!winm) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ WINM_SET_ERROR(-1);
+ }
+
+ if(m_pVideoCaptureAction || m_pVideoDevice || m_pVideoOnlyDevice || m_pVideoSink || m_pOpenOperation) {
+ TSK_DEBUG_ERROR("Producer already prepared");
+ WINM_SET_ERROR(-2);
+ }
+
+ dimensionsClosest.Width = dimensionsRequested.Width = (float)TMEDIA_PRODUCER(winm)->video.width;
+ dimensionsClosest.Height = dimensionsRequested.Height = (float)TMEDIA_PRODUCER(winm)->video.height;
availableSizes = AudioVideoCaptureDevice::GetAvailableCaptureResolutions(m_eCameraLocation);
availableSizesIterator = availableSizes->First();
-
- while(!m_pOpenOperation && availableSizesIterator->HasCurrent)
- {
- TSK_DEBUG_INFO("Camera Supported size: (%f, %f)", availableSizesIterator->Current.Width, availableSizesIterator->Current.Height);
- if(availableSizesIterator->Current.Height == dimensionsRequested.Width && availableSizesIterator->Current.Width == dimensionsRequested.Height)
- {
+
+ while(!m_pOpenOperation && availableSizesIterator->HasCurrent) {
+ TSK_DEBUG_INFO("Camera Supported size: (%f, %f)", availableSizesIterator->Current.Width, availableSizesIterator->Current.Height);
+ if(availableSizesIterator->Current.Height == dimensionsRequested.Width && availableSizesIterator->Current.Width == dimensionsRequested.Height) {
m_pOpenOperation = AudioVideoCaptureDevice::OpenForVideoOnlyAsync(m_eCameraLocation, dimensionsRequested);
- TSK_DEBUG_INFO("Camera::Open(%d, %d)", dimensionsRequested.Width, dimensionsRequested.Height);
- break;
+ TSK_DEBUG_INFO("Camera::Open(%d, %d)", dimensionsRequested.Width, dimensionsRequested.Height);
+ break;
+ }
+ else if(!bClosestFound && (availableSizesIterator->Current.Height <= dimensionsRequested.Height && availableSizesIterator->Current.Width <= dimensionsRequested.Width)) {
+ dimensionsClosest.Height = availableSizesIterator->Current.Height;
+ dimensionsClosest.Width = availableSizesIterator->Current.Width;
+ bClosestFound = true;
}
- else if(!bClosestFound && (availableSizesIterator->Current.Height <= dimensionsRequested.Height && availableSizesIterator->Current.Width <= dimensionsRequested.Width))
- {
- dimensionsClosest.Height = availableSizesIterator->Current.Height;
- dimensionsClosest.Width = availableSizesIterator->Current.Width;
- bClosestFound = true;
- }
availableSizesIterator->MoveNext();
}
- if(!m_pOpenOperation)
- {
- m_pOpenOperation = AudioVideoCaptureDevice::OpenForVideoOnlyAsync(m_eCameraLocation, dimensionsClosest);
- TSK_DEBUG_INFO("Camera::Open(%f, %f)", dimensionsClosest.Width, dimensionsClosest.Height);
- }
+ if(!m_pOpenOperation) {
+ m_pOpenOperation = AudioVideoCaptureDevice::OpenForVideoOnlyAsync(m_eCameraLocation, dimensionsClosest);
+ TSK_DEBUG_INFO("Camera::Open(%f, %f)", dimensionsClosest.Width, dimensionsClosest.Height);
+ }
bail:
- if(ret != 0){
- UnPrepare();
- }
- if((m_bPrepared = (ret == 0)))
- {
- m_pWrappedPlugin = winm;
- }
+ if(ret != 0) {
+ UnPrepare();
+ }
+ if((m_bPrepared = (ret == 0))) {
+ m_pWrappedPlugin = winm;
+ }
- tsk_mutex_unlock(m_hMutex);
+ tsk_mutex_unlock(m_hMutex);
- return ret;
+ return ret;
}
int VideoCapturePhone::Start()
{
- tsk_mutex_lock(m_hMutex);
-
- if(m_bStarted)
- {
- TSK_DEBUG_INFO("#WINM: Video producer already started");
- goto bail;
- }
- if(!m_bPrepared)
- {
- TSK_DEBUG_ERROR("#WINM: Video producer not prepared");
- goto bail;
- }
-
- m_bStarted = true;
-
- m_pOpenOperation->Completed = ref new AsyncOperationCompletedHandler<AudioVideoCaptureDevice^>([this] (IAsyncOperation<AudioVideoCaptureDevice^> ^operation, Windows::Foundation::AsyncStatus status)
- {
- tsk_mutex_lock(m_hMutex);
- if(m_bStarted)
- {
-
- if(status == Windows::Foundation::AsyncStatus::Completed)
- {
-
- TSK_DEBUG_INFO("+[VideoCapturePhone::Prepare] => OpenAsyncOperation started");
-
- auto videoDevice = operation->GetResults();
-
- m_pVideoOnlyDevice = videoDevice;
- IAudioVideoCaptureDeviceNative *pNativeDevice = NULL;
- HRESULT hr = reinterpret_cast<IUnknown*>(videoDevice)->QueryInterface(__uuidof(IAudioVideoCaptureDeviceNative), (void**) &pNativeDevice);
-
- if (NULL == pNativeDevice || FAILED(hr))
- {
- throw ref new FailureException("Unable to QI IAudioVideoCaptureDeviceNative");
- }
-
- // Save off the native device
- m_pVideoDevice = pNativeDevice;
-
- // Set Fps
- CameraCapturePropertyRange^ cameraCapturePropertyRange = m_pVideoOnlyDevice->GetSupportedPropertyRange(m_eCameraLocation, KnownCameraAudioVideoProperties::VideoFrameRate);
- if(cameraCapturePropertyRange)
- {
- try
- {
- Windows::Foundation::IPropertyValue^ vMin = dynamic_cast<Windows::Foundation::IPropertyValue^>(cameraCapturePropertyRange->Min);
- Windows::Foundation::IPropertyValue^ vMax = dynamic_cast<Windows::Foundation::IPropertyValue^>(cameraCapturePropertyRange->Max);
- UINT32 nFps = TSK_CLAMP(vMin->GetUInt32(), (UINT32)TMEDIA_PRODUCER(m_pWrappedPlugin)->video.fps, vMax->GetUInt32());
- m_pVideoOnlyDevice->SetProperty(KnownCameraAudioVideoProperties::VideoFrameRate, nFps);
- }
- catch(...){ }
- }
-
- // Set Camera Rotation
- try
- {
- m_pVideoOnlyDevice->SetProperty(
- KnownCameraGeneralProperties::EncodeWithOrientation,
- m_eCameraLocation == Windows::Phone::Media::Capture::CameraSensorLocation::Back ? 90 : -90
- );
- }
- catch(...){ }
-
- // Create the sink
- MakeAndInitialize<CaptureSampleSink>(&(m_pVideoSink), m_pWrappedPlugin);
- pNativeDevice->SetVideoSampleSink(m_pVideoSink);
-
- // Use the same encoding format as in VideoMediaStreamSource.cs
- videoDevice->VideoEncodingFormat = CameraCaptureVideoFormat::H264;
-
- SetEvent(m_hStartCompleted);
-
- // Start recording to our sink
- m_pVideoCaptureAction = videoDevice->StartRecordingToSinkAsync();
- m_pVideoCaptureAction->Completed = ref new AsyncActionCompletedHandler([this] (IAsyncAction ^asyncInfo, Windows::Foundation::AsyncStatus status)
- {
- if(status == Windows::Foundation::AsyncStatus::Completed)
- {
- TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => StartRecordingToSinkAsync completed");
- }
- else if(status == Windows::Foundation::AsyncStatus::Error || status == Windows::Foundation::AsyncStatus::Canceled)
- {
- TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => StartRecordingToSinkAsync did not complete");
- }
- });
-
- TSK_DEBUG_INFO("-[VideoCapturePhone::Prepare] => OpenAsyncOperation Completed");
- }
- else if(status == Windows::Foundation::AsyncStatus::Canceled)
- {
- TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => OpenAsyncOperation Canceled");
- }
- else if(status == Windows::Foundation::AsyncStatus::Error)
- {
- TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => OpenAsyncOperation encountered an error");
- }
- }
-
- tsk_mutex_unlock(m_hMutex);
+ tsk_mutex_lock(m_hMutex);
+
+ if(m_bStarted) {
+ TSK_DEBUG_INFO("#WINM: Video producer already started");
+ goto bail;
+ }
+ if(!m_bPrepared) {
+ TSK_DEBUG_ERROR("#WINM: Video producer not prepared");
+ goto bail;
+ }
+
+ m_bStarted = true;
+
+ m_pOpenOperation->Completed = ref new AsyncOperationCompletedHandler<AudioVideoCaptureDevice^>([this] (IAsyncOperation<AudioVideoCaptureDevice^> ^operation, Windows::Foundation::AsyncStatus status) {
+ tsk_mutex_lock(m_hMutex);
+ if(m_bStarted) {
+
+ if(status == Windows::Foundation::AsyncStatus::Completed) {
+
+ TSK_DEBUG_INFO("+[VideoCapturePhone::Prepare] => OpenAsyncOperation started");
+
+ auto videoDevice = operation->GetResults();
+
+ m_pVideoOnlyDevice = videoDevice;
+ IAudioVideoCaptureDeviceNative *pNativeDevice = NULL;
+ HRESULT hr = reinterpret_cast<IUnknown*>(videoDevice)->QueryInterface(__uuidof(IAudioVideoCaptureDeviceNative), (void**) &pNativeDevice);
+
+ if (NULL == pNativeDevice || FAILED(hr)) {
+ throw ref new FailureException("Unable to QI IAudioVideoCaptureDeviceNative");
+ }
+
+ // Save off the native device
+ m_pVideoDevice = pNativeDevice;
+
+ // Set Fps
+ CameraCapturePropertyRange^ cameraCapturePropertyRange = m_pVideoOnlyDevice->GetSupportedPropertyRange(m_eCameraLocation, KnownCameraAudioVideoProperties::VideoFrameRate);
+ if(cameraCapturePropertyRange) {
+ try {
+ Windows::Foundation::IPropertyValue^ vMin = dynamic_cast<Windows::Foundation::IPropertyValue^>(cameraCapturePropertyRange->Min);
+ Windows::Foundation::IPropertyValue^ vMax = dynamic_cast<Windows::Foundation::IPropertyValue^>(cameraCapturePropertyRange->Max);
+ UINT32 nFps = TSK_CLAMP(vMin->GetUInt32(), (UINT32)TMEDIA_PRODUCER(m_pWrappedPlugin)->video.fps, vMax->GetUInt32());
+ m_pVideoOnlyDevice->SetProperty(KnownCameraAudioVideoProperties::VideoFrameRate, nFps);
+ }
+ catch(...) { }
+ }
+
+ // Set Camera Rotation
+ try {
+ m_pVideoOnlyDevice->SetProperty(
+ KnownCameraGeneralProperties::EncodeWithOrientation,
+ m_eCameraLocation == Windows::Phone::Media::Capture::CameraSensorLocation::Back ? 90 : -90
+ );
+ }
+ catch(...) { }
+
+ // Create the sink
+ MakeAndInitialize<CaptureSampleSink>(&(m_pVideoSink), m_pWrappedPlugin);
+ pNativeDevice->SetVideoSampleSink(m_pVideoSink);
+
+ // Use the same encoding format as in VideoMediaStreamSource.cs
+ videoDevice->VideoEncodingFormat = CameraCaptureVideoFormat::H264;
+
+ SetEvent(m_hStartCompleted);
+
+ // Start recording to our sink
+ m_pVideoCaptureAction = videoDevice->StartRecordingToSinkAsync();
+ m_pVideoCaptureAction->Completed = ref new AsyncActionCompletedHandler([this] (IAsyncAction ^asyncInfo, Windows::Foundation::AsyncStatus status) {
+ if(status == Windows::Foundation::AsyncStatus::Completed) {
+ TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => StartRecordingToSinkAsync completed");
+ }
+ else if(status == Windows::Foundation::AsyncStatus::Error || status == Windows::Foundation::AsyncStatus::Canceled) {
+ TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => StartRecordingToSinkAsync did not complete");
+ }
+ });
+
+ TSK_DEBUG_INFO("-[VideoCapturePhone::Prepare] => OpenAsyncOperation Completed");
+ }
+ else if(status == Windows::Foundation::AsyncStatus::Canceled) {
+ TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => OpenAsyncOperation Canceled");
+ }
+ else if(status == Windows::Foundation::AsyncStatus::Error) {
+ TSK_DEBUG_INFO("[VideoCapturePhone::Prepare] => OpenAsyncOperation encountered an error");
+ }
+ }
+
+ tsk_mutex_unlock(m_hMutex);
});
-
+
bail:
- tsk_mutex_unlock(m_hMutex);
+ tsk_mutex_unlock(m_hMutex);
return (m_bStarted ? 0 : -2);
}
int VideoCapturePhone::Pause()
{
- tsk_mutex_lock(m_hMutex);
+ tsk_mutex_lock(m_hMutex);
- if(m_bStarted)
- {
+ if(m_bStarted) {
- }
+ }
- tsk_mutex_unlock(m_hMutex);
+ tsk_mutex_unlock(m_hMutex);
- return 0;
+ return 0;
}
int VideoCapturePhone::Stop()
{
- tsk_mutex_lock(m_hMutex);
+ tsk_mutex_lock(m_hMutex);
- TSK_DEBUG_INFO("+[VideoCapturePhone::Stop] => Trying to stop capture");
- if (m_pVideoOnlyDevice)
- {
+ TSK_DEBUG_INFO("+[VideoCapturePhone::Stop] => Trying to stop capture");
+ if (m_pVideoOnlyDevice) {
TSK_DEBUG_INFO("Destroying VideoCaptureDevice");
- try
- {
- if(m_bStarted)
- {
- m_pVideoOnlyDevice->StopRecordingAsync()->Completed = ref new AsyncActionCompletedHandler([this] (IAsyncAction ^action, Windows::Foundation::AsyncStatus status){
- if(status == Windows::Foundation::AsyncStatus::Completed)
- {
- TSK_DEBUG_INFO("[VideoCapturePhone::StopRecordingAsync] Video successfully stopped");
- }
- else
- {
- TSK_DEBUG_INFO("[VideoCapturePhone::StopRecordingAsync] Error occurred while stopping recording");
- }
- m_pVideoCaptureAction = nullptr;
- m_pVideoOnlyDevice = nullptr;
- m_bStarted = false;
- SetEvent(m_hStopCompleted);
- });
- }
+ try {
+ if(m_bStarted) {
+ m_pVideoOnlyDevice->StopRecordingAsync()->Completed = ref new AsyncActionCompletedHandler([this] (IAsyncAction ^action, Windows::Foundation::AsyncStatus status) {
+ if(status == Windows::Foundation::AsyncStatus::Completed) {
+ TSK_DEBUG_INFO("[VideoCapturePhone::StopRecordingAsync] Video successfully stopped");
+ }
+ else {
+ TSK_DEBUG_INFO("[VideoCapturePhone::StopRecordingAsync] Error occurred while stopping recording");
+ }
+ m_pVideoCaptureAction = nullptr;
+ m_pVideoOnlyDevice = nullptr;
+ m_bStarted = false;
+ SetEvent(m_hStopCompleted);
+ });
+ }
}
- catch(...)
- {
+ catch(...) {
// A Platform::ObjectDisposedException can be raised if the app has had its access
// to video revoked (most commonly when the app is going out of the foreground)
TSK_DEBUG_ERROR("Exception caught while destroying video capture");
@@ -528,90 +491,79 @@ int VideoCapturePhone::Stop()
SetEvent(m_hStopCompleted);
}
- if (m_pVideoDevice)
- {
+ if (m_pVideoDevice) {
m_pVideoDevice->Release();
m_pVideoDevice = NULL;
}
- if (m_pVideoSink)
- {
+ if (m_pVideoSink) {
m_pVideoSink->Release();
m_pVideoSink = NULL;
}
}
- else
- {
- m_bStarted = false;
- }
+ else {
+ m_bStarted = false;
+ }
- TSK_DEBUG_INFO("-[VideoCapturePhone::Stop] => finished stopping capture\n");
+ TSK_DEBUG_INFO("-[VideoCapturePhone::Stop] => finished stopping capture\n");
- // will be prepared again before next start()
- UnPrepare();
+ // will be prepared again before next start()
+ UnPrepare();
- tsk_mutex_unlock(m_hMutex);
+ tsk_mutex_unlock(m_hMutex);
- return 0;
+ return 0;
}
void VideoCapturePhone::SetCameraLocation(Windows::Phone::Media::Capture::CameraSensorLocation cameraLocation)
{
- if(m_eCameraLocation != cameraLocation)
- {
- if(m_bStarted)
- {
- ToggleCamera();
- }
- else
- {
- m_eCameraLocation = cameraLocation;
- }
- }
+ if(m_eCameraLocation != cameraLocation) {
+ if(m_bStarted) {
+ ToggleCamera();
+ }
+ else {
+ m_eCameraLocation = cameraLocation;
+ }
+ }
}
int VideoCapturePhone::UnPrepare()
{
- tsk_mutex_lock(m_hMutex);
-
- if(m_bStarted)
- {
- ResetEvent(m_hStopCompleted);
- Stop();
- DWORD waitResult = WaitForSingleObjectEx(m_hStopCompleted, 5000, FALSE);
- if(waitResult != WAIT_OBJECT_0)
- {
- TSK_DEBUG_ERROR("Failed to stop video producer");
- }
- }
-
- if (m_pVideoDevice)
- {
+ tsk_mutex_lock(m_hMutex);
+
+ if(m_bStarted) {
+ ResetEvent(m_hStopCompleted);
+ Stop();
+ DWORD waitResult = WaitForSingleObjectEx(m_hStopCompleted, 5000, FALSE);
+ if(waitResult != WAIT_OBJECT_0) {
+ TSK_DEBUG_ERROR("Failed to stop video producer");
+ }
+ }
+
+ if (m_pVideoDevice) {
m_pVideoDevice->Release();
m_pVideoDevice = NULL;
}
- if (m_pVideoSink)
- {
+ if (m_pVideoSink) {
m_pVideoSink->Release();
m_pVideoSink = NULL;
}
- m_pOpenOperation = nullptr;
+ m_pOpenOperation = nullptr;
- m_bPrepared = false;
+ m_bPrepared = false;
- tsk_mutex_unlock(m_hMutex);
+ tsk_mutex_unlock(m_hMutex);
- return 0;
+ return 0;
}
void VideoCapturePhone::ToggleCamera()
{
tsk_mutex_lock(m_hMutex);
- if(m_ToggleThread)
- {
+ if(m_ToggleThread) {
m_ToggleThread->Cancel();
m_ToggleThread->Close();
m_ToggleThread = nullptr;
@@ -619,7 +571,7 @@ void VideoCapturePhone::ToggleCamera()
m_ToggleThread = ThreadPool::RunAsync(ref new WorkItemHandler(this, &VideoCapturePhone::ToggleCameraThread), WorkItemPriority::High, WorkItemOptions::TimeSliced);
- tsk_mutex_unlock(m_hMutex);
+ tsk_mutex_unlock(m_hMutex);
}
@@ -630,35 +582,29 @@ void VideoCapturePhone::ToggleCameraThread(Windows::Foundation::IAsyncAction^ op
ResetEvent(m_hStopCompleted);
Stop();
DWORD waitResult = WaitForSingleObjectEx(m_hStopCompleted, INFINITE, FALSE);
- if(waitResult == WAIT_OBJECT_0)
- {
+ if(waitResult == WAIT_OBJECT_0) {
ResetEvent(m_hStartCompleted);
- if(m_eCameraLocation == Windows::Phone::Media::Capture::CameraSensorLocation::Back)
- {
+ if(m_eCameraLocation == Windows::Phone::Media::Capture::CameraSensorLocation::Back) {
m_eCameraLocation = Windows::Phone::Media::Capture::CameraSensorLocation::Front;
}
- else
- {
+ else {
m_eCameraLocation = Windows::Phone::Media::Capture::CameraSensorLocation::Back;
}
- Prepare(m_pWrappedPlugin);
- Start();
+ Prepare(m_pWrappedPlugin);
+ Start();
}
- else
- {
+ else {
throw ref new Platform::Exception(HRESULT_FROM_WIN32(waitResult), L"Error waiting for capture to stop when toggling cameras");
}
waitResult = WaitForSingleObjectEx(m_hStartCompleted, INFINITE, FALSE);
- if(waitResult == WAIT_OBJECT_0)
- {
+ if(waitResult == WAIT_OBJECT_0) {
// CameraLocationChanged(newCameraLocation);
}
- else
- {
+ else {
throw ref new Platform::Exception(HRESULT_FROM_WIN32(waitResult), L"Error waiting for capture to start when toggling cameras");
}
- TSK_DEBUG_INFO("-[VideoCapturePhone::ToggleCamera] => Toggling camera");
+ TSK_DEBUG_INFO("-[VideoCapturePhone::ToggleCamera] => Toggling camera");
}
#endif /* TDAV_UNDER_WINDOWS_PHONE */
@@ -670,67 +616,64 @@ void VideoCapturePhone::ToggleCameraThread(Windows::Foundation::IAsyncAction^ op
/* constructor */
static tsk_object_t* tdav_producer_winm_ctor(tsk_object_t * self, va_list * app)
{
- tdav_producer_winm_t *producer = (tdav_producer_winm_t *)self;
- if(producer){
- /* init base */
- tmedia_producer_init(TMEDIA_PRODUCER(producer));
- TMEDIA_PRODUCER(producer)->video.chroma = tmedia_chroma_yuv420p; // To avoid chroma conversion
- /* init self with default values*/
+ tdav_producer_winm_t *producer = (tdav_producer_winm_t *)self;
+ if(producer) {
+ /* init base */
+ tmedia_producer_init(TMEDIA_PRODUCER(producer));
+ TMEDIA_PRODUCER(producer)->video.chroma = tmedia_chroma_yuv420p; // To avoid chroma conversion
+ /* init self with default values*/
- TMEDIA_PRODUCER(producer)->video.fps = 15;
- TMEDIA_PRODUCER(producer)->video.width = 352;
- TMEDIA_PRODUCER(producer)->video.height = 288;
+ TMEDIA_PRODUCER(producer)->video.fps = 15;
+ TMEDIA_PRODUCER(producer)->video.width = 352;
+ TMEDIA_PRODUCER(producer)->video.height = 288;
#if TDAV_UNDER_WINDOWS_PHONE
- producer->videoCapturePhone = ref new VideoCapturePhone();
+ producer->videoCapturePhone = ref new VideoCapturePhone();
#endif
- }
- return self;
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_producer_winm_dtor(tsk_object_t * self)
-{
- tdav_producer_winm_t *producer = (tdav_producer_winm_t *)self;
- if(producer){
- /* stop */
- //if(producer->started){
- tdav_producer_winm_stop((tmedia_producer_t*)self);
- //}
-
- /* deinit base */
- tmedia_producer_deinit(TMEDIA_PRODUCER(producer));
- /* deinit self */
+{
+ tdav_producer_winm_t *producer = (tdav_producer_winm_t *)self;
+ if(producer) {
+ /* stop */
+ //if(producer->started){
+ tdav_producer_winm_stop((tmedia_producer_t*)self);
+ //}
+
+ /* deinit base */
+ tmedia_producer_deinit(TMEDIA_PRODUCER(producer));
+ /* deinit self */
#if TDAV_UNDER_WINDOWS_PHONE
- if(producer->videoCapturePhone)
- {
- delete producer->videoCapturePhone;
- }
+ if(producer->videoCapturePhone) {
+ delete producer->videoCapturePhone;
+ }
#endif
- }
+ }
- return self;
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_producer_winm_def_s =
-{
- sizeof(tdav_producer_winm_t),
- tdav_producer_winm_ctor,
- tdav_producer_winm_dtor,
- tsk_null,
+static const tsk_object_def_t tdav_producer_winm_def_s = {
+ sizeof(tdav_producer_winm_t),
+ tdav_producer_winm_ctor,
+ tdav_producer_winm_dtor,
+ tsk_null,
};
/* plugin definition*/
-static const tmedia_producer_plugin_def_t tdav_producer_winm_plugin_def_s =
-{
- &tdav_producer_winm_def_s,
+static const tmedia_producer_plugin_def_t tdav_producer_winm_plugin_def_s = {
+ &tdav_producer_winm_def_s,
- tmedia_video,
- "Microsoft Windows Media producer (Video)",
+ tmedia_video,
+ "Microsoft Windows Media producer (Video)",
- tdav_producer_winm_set,
- tdav_producer_winm_prepare,
- tdav_producer_winm_start,
- tdav_producer_winm_pause,
- tdav_producer_winm_stop
+ tdav_producer_winm_set,
+ tdav_producer_winm_prepare,
+ tdav_producer_winm_start,
+ tdav_producer_winm_pause,
+ tdav_producer_winm_stop
};
const tmedia_producer_plugin_def_t *tdav_producer_winm_plugin_def_t = &tdav_producer_winm_plugin_def_s;
OpenPOWER on IntegriCloud