Commit 14ba30c4 authored by atraczyk's avatar atraczyk Committed by Andreas Traczyk

video: add video

- adds incoming video
- adds webcam preview
- adds device enumeration
- adds daemon video signal handlers
- adds outgoing video

Tuleap: #1200
Change-Id: Ife5f6acc2ee400665e096e44e2111e03cab0299a
parent c551c365
......@@ -106,7 +106,6 @@ RingClientUWP::MainPage::showFrame(Windows::UI::Xaml::Controls::Frame^ frame)
_navGrid_->SetRow(_welcomeFrame_, 1);
} else if (frame == _videoFrame_) {
_navGrid_->SetRow(_videoFrame_, 1);
dynamic_cast<VideoPage^>(_videoFrame_->Content)->updatePageContent();
} else if (frame == _messageTextFrame_) {
_navGrid_->SetRow(_messageTextFrame_, 1);
}
......@@ -260,3 +259,37 @@ void RingClientUWP::MainPage::OnstateChange(Platform::String ^callId, RingClient
}
}
void
MainPage::Application_Suspending(Object^, Windows::ApplicationModel::SuspendingEventArgs^ e)
{
WriteLine("Application_Suspending");
if (Frame->CurrentSourcePageType.Name ==
Interop::TypeName(MainPage::typeid).Name)
{
if (Video::VideoManager::instance->captureManager()->captureTaskTokenSource)
Video::VideoManager::instance->captureManager()->captureTaskTokenSource->cancel();
//displayInformation->OrientationChanged -= displayInformationEventToken;
auto deferral = e->SuspendingOperation->GetDeferral();
Video::VideoManager::instance->captureManager()->CleanupCameraAsync()
.then([this, deferral]() {
deferral->Complete();
});
}
}
void
MainPage::Application_VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
{
if (e->Visible)
{
WriteLine("->Visible");
if (Video::VideoManager::instance->captureManager()->isInitialized) {
Video::VideoManager::instance->captureManager()->InitializeCameraAsync();
}
}
else
{
WriteLine("->Invisible");
}
}
......
......@@ -45,6 +45,10 @@ protected:
void OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e);
private:
// event handlers
void Application_Suspending(Object^, Windows::ApplicationModel::SuspendingEventArgs^ e);
void Application_VisibilityChanged(Object^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ e);
// Multi-monitor, DPI, scale factor change, and window resize detection
void DisplayProperties_DpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
Windows::Foundation::EventRegistrationToken dpiChangedtoken;
......@@ -58,4 +62,4 @@ private:
void OnpressHangUpCall();
void OnstateChange(Platform::String ^callId, RingClientUWP::CallStatus state, int code);
};
}
\ No newline at end of file
}
......@@ -23,6 +23,7 @@
#include "callmanager_interface.h"
#include "configurationmanager_interface.h"
#include "presencemanager_interface.h"
#include "videomanager_interface.h"
#include "fileutils.h"
#include "account_schema.h"
#include "account_const.h"
......@@ -32,6 +33,9 @@
using namespace Windows::ApplicationModel::Core;
using namespace Windows::Storage;
using namespace Windows::UI::Core;
using namespace Windows::Media;
using namespace Windows::Media::MediaProperties;
using namespace Windows::Media::Capture;
using namespace RingClientUWP;
using namespace RingClientUWP::Utils;
......@@ -311,14 +315,7 @@ RingClientUWP::RingD::startDaemon()
RingDebug::instance->print(toto);
}));
})
/* to remove from daemon API, this callback is never used */
//DRing::exportable_callback<DRing::CallSignal::NewCallCreated>([&](
// const std::string& accountId,
// const std::string& callId,
// const std::string& to)
//{ /*...*/ })
};
registerCallHandlers(callHandlers);
std::map<std::string, SharedCallback> getAppPathHandler =
......@@ -330,6 +327,91 @@ RingClientUWP::RingD::startDaemon()
};
registerCallHandlers(getAppPathHandler);
std::map<std::string, SharedCallback> incomingVideoHandlers =
{
DRing::exportable_callback<DRing::VideoSignal::DeviceEvent>
([this]() {
MSG_("<DeviceEvent>");
}),
DRing::exportable_callback<DRing::VideoSignal::DecodingStarted>
([this](const std::string &id, const std::string &shmPath, int width, int height, bool isMixer) {
MSG_("<DecodingStarted>");
Video::VideoManager::instance->rendererManager()->startedDecoding(
Utils::toPlatformString(id),
width,
height);
}),
DRing::exportable_callback<DRing::VideoSignal::DecodingStopped>
([this](const std::string &id, const std::string &shmPath, bool isMixer) {
MSG_("<DecodingStopped>");
MSG_("Removing renderer id:" + id);
/*auto Id = Utils::toPlatformString(id);
auto renderer = Video::VideoManager::instance->rendererManager()->renderer(Id);
if (renderer)
renderer->isRendering = false;*/
Video::VideoManager::instance->rendererManager()->removeRenderer(Utils::toPlatformString(id));
})
};
registerVideoHandlers(incomingVideoHandlers);
using namespace Video;
std::map<std::string, SharedCallback> outgoingVideoHandlers =
{
DRing::exportable_callback<DRing::VideoSignal::GetCameraInfo>
([this](const std::string& device,
std::vector<std::string> *formats,
std::vector<unsigned> *sizes,
std::vector<unsigned> *rates) {
MSG_("\n<GetCameraInfo>\n");
auto device_list = VideoManager::instance->captureManager()->deviceList;
for (unsigned int i = 0; i < device_list->Size; i++) {
auto dev = device_list->GetAt(i);
if (device == Utils::toString(dev->name())) {
auto channel = dev->channel();
Vector<Video::Resolution^>^ resolutions = channel->resolutionList();
for (auto res : resolutions) {
formats->emplace_back(Utils::toString(res->format()));
sizes->emplace_back(res->size()->width());
sizes->emplace_back(res->size()->height());
rates->emplace_back(res->activeRate()->value());
}
}
}
}),
DRing::exportable_callback<DRing::VideoSignal::SetParameters>
([this](const std::string& device,
std::string format,
const int width,
const int height,
const int rate) {
MSG_("\n<SetParameters>\n");
VideoManager::instance->captureManager()->activeDevice->SetDeviceProperties(
Utils::toPlatformString(format),width,height,rate);
}),
DRing::exportable_callback<DRing::VideoSignal::StartCapture>
([&](const std::string& device) {
MSG_("\n<StartCapture>\n");
dispatcher->RunAsync(CoreDispatcherPriority::Normal,
ref new DispatchedHandler([=]() {
VideoManager::instance->captureManager()->InitializeCameraAsync();
VideoManager::instance->captureManager()->videoFrameCopyInvoker->Start();
}));
}),
DRing::exportable_callback<DRing::VideoSignal::StopCapture>
([&]() {
MSG_("\n<StopCapture>\n");
dispatcher->RunAsync(CoreDispatcherPriority::Normal,
ref new DispatchedHandler([=]() {
VideoManager::instance->captureManager()->StopPreviewAsync();
if (VideoManager::instance->captureManager()->captureTaskTokenSource)
VideoManager::instance->captureManager()->captureTaskTokenSource->cancel();
VideoManager::instance->captureManager()->videoFrameCopyInvoker->Stop();
}));
})
};
registerVideoHandlers(outgoingVideoHandlers);
DRing::init(static_cast<DRing::InitFlag>(DRing::DRING_FLAG_CONSOLE_LOG |
DRing::DRING_FLAG_DEBUG));
......@@ -338,8 +420,7 @@ RingClientUWP::RingD::startDaemon()
return;
}
else {
if (!hasConfig)
{
if (!hasConfig) {
tasksList_.push(ref new RingD::Task(Request::AddRingAccount));
tasksList_.push(ref new RingD::Task(Request::AddSIPAccount));
}
......
......@@ -54,6 +54,20 @@ private:
RingDebug() {}; // singleton
};
void WriteLine(String^ str)
{
std::wstringstream wStringstream;
wStringstream << str->Data() << "\n";
OutputDebugString(wStringstream.str().c_str());
}
void WriteException(Exception^ ex)
{
std::wstringstream wStringstream;
wStringstream << "0x" << ex->HResult << ": " << ex->Message->Data();
OutputDebugString(wStringstream.str().c_str());
}
#define MSG_(cstr) CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Low, \
ref new DispatchedHandler([=]() { RingDebug::instance->print(cstr); }))
......
......@@ -20,8 +20,11 @@
#include <pch.h>
using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Storage;
typedef Windows::UI::Xaml::Visibility VIS;
namespace RingClientUWP
{
namespace Utils
......@@ -50,7 +53,8 @@ fileExists(StorageFolder^ folder, String^ fileName)
});
}
std::string makeString(const std::wstring& wstr)
inline std::string
makeString(const std::wstring& wstr)
{
auto wideData = wstr.c_str();
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, wideData, -1, nullptr, 0, NULL, NULL);
......@@ -65,7 +69,8 @@ std::string makeString(const std::wstring& wstr)
return std::string(utf8.get());
}
std::wstring makeWString(const std::string& str)
inline std::wstring
makeWString(const std::string& str)
{
auto utf8Data = str.c_str();
int bufferSize = MultiByteToWideChar(CP_UTF8, 0, utf8Data, -1, nullptr, 0);
......@@ -80,19 +85,22 @@ std::wstring makeWString(const std::string& str)
return std::wstring(wide.get());;
}
std::string toString(Platform::String ^str)
inline std::string
toString(Platform::String ^str)
{
std::wstring wsstr(str->Data());
return makeString(wsstr);
}
Platform::String^ toPlatformString(const std::string& str)
inline Platform::String^
toPlatformString(const std::string& str)
{
std::wstring wsstr = makeWString(str);
return ref new Platform::String(wsstr.c_str(), wsstr.length());
}
Platform::String^ Trim(Platform::String^ s)
Platform::String^
Trim(Platform::String^ s)
{
const WCHAR* first = s->Begin();
const WCHAR* last = s->End();
......@@ -107,7 +115,8 @@ Platform::String^ Trim(Platform::String^ s)
}
/* fix some issue in the daemon --> <...@...> */
Platform::String^ TrimRingId(Platform::String^ s)
Platform::String^
TrimRingId(Platform::String^ s)
{
const WCHAR* first = s->Begin();
const WCHAR* last = s->End();
......@@ -125,7 +134,8 @@ Platform::String^ TrimRingId(Platform::String^ s)
}
/* fix some issue in the daemon --> remove "@..." */
Platform::String^ TrimRingId2(Platform::String^ s)
Platform::String^
TrimRingId2(Platform::String^ s)
{
const WCHAR* first = s->Begin();
const WCHAR* last = s->End();
......@@ -138,7 +148,8 @@ Platform::String^ TrimRingId2(Platform::String^ s)
return ref new Platform::String(first, static_cast<unsigned int>(last - first));
}
Platform::String^ GetNewGUID()
Platform::String^
GetNewGUID()
{
GUID result;
HRESULT hr = CoCreateGuid(&result);
......@@ -159,5 +170,31 @@ getStringFromFile(const std::string& filename)
(std::istreambuf_iterator<char>()));
}
inline Map<String^,String^>^
convertMap(const std::map<std::string, std::string>& m)
{
auto temp = ref new Map<String^,String^>;
for (const auto& pair : m) {
temp->Insert(
Utils::toPlatformString(pair.first),
Utils::toPlatformString(pair.second)
);
}
return temp;
}
inline std::map<std::string, std::string>
convertMap(Map<String^,String^>^ m)
{
std::map<std::string, std::string> temp;
for (const auto& pair : m) {
temp.insert(
std::make_pair(
Utils::toString(pair->Key),
Utils::toString(pair->Value)));
}
return temp;
}
}
}
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux *
* Author: Jger Nicolas <nicolas.jager@savoirfairelinux.com> *
* Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com> *
* *
* This program 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. *
* *
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
#include "pch.h"
#include "Video.h"
using namespace RingClientUWP;
using namespace Video;
using namespace Platform;
/************************************************************
* *
* Size *
* *
***********************************************************/
unsigned int
Video::Size::width()
{
return m_Width;
}
unsigned int
Video::Size::height()
{
return m_Height;
}
void
Video::Size::setWidth(unsigned int width)
{
m_Width = width;
}
void
Video::Size::setHeight(unsigned int height)
{
m_Height = height;
}
/************************************************************
* *
* Rate *
* *
***********************************************************/
String^
Rate::name()
{
return m_name;
}
unsigned int
Rate::value()
{
return m_value;
}
void
Rate::setName(String^ name)
{
m_name = name;
}
void
Rate::setValue(unsigned int value)
{
m_value = value;
}
/************************************************************
* *
* Channel *
* *
***********************************************************/
Channel::Channel()
{
m_validResolutions = ref new Vector<Resolution^>();
}
String^
Channel::name()
{
return m_name;
}
Resolution^
Channel::currentResolution()
{
return m_currentResolution;
}
void
Channel::setName(String^ name)
{
m_name = name;
}
void
Channel::setCurrentResolution(Resolution^ currentResolution)
{
m_currentResolution = currentResolution;
}
Vector<Resolution^>^
Channel::resolutionList()
{
return m_validResolutions;
}
/************************************************************
* *
* Resolution *
* *
***********************************************************/
Resolution::Resolution()
{
m_size = ref new Size();
m_validRates = ref new Vector<Rate^>();
}
Resolution::Resolution(Video::Size^ size):
m_size(size)
{ }
String^
Resolution::name()
{
return size()->width().ToString() + "x" + size()->height().ToString();
}
Rate^
Resolution::activeRate()
{
return m_currentRate;
}
Vector<Rate^>^
Resolution::rateList()
{
return m_validRates;
}
Video::Size^
Resolution::size()
{
return m_size;
}
String^
Resolution::format()
{
return m_format;
}
void
Resolution::setWidth(int width)
{
m_size->setWidth(width);
}
void
Resolution::setHeight(int height)
{
m_size->setHeight(height);
}
void
Resolution::setFormat(String^ format)
{
m_format = format;
}
bool
Resolution::setActiveRate(Rate^ rate)
{
if (m_currentRate == rate)
return false;
m_currentRate = rate;
// set camera device rate here
return true;
}
/************************************************************
* *
* Device *
* *
***********************************************************/
Device::Device(String^ id)
{
m_deviceId = id;
m_channels = ref new Vector<Channel^>();
}
String^
Device::id()
{
return m_deviceId;
}
Vector<Channel^>^
Device::channelList()
{
return m_channels;
}
String^
Device::name()
{
return m_name;
}
Channel^
Device::channel()
{
return m_currentChannel;
}
bool
Device::setCurrentChannel(Channel^ channel)
{
if (m_currentChannel == channel)
return false;
m_currentChannel = channel;
return true;
}
void
Device::setName(String^ name)
{
m_name = name;
}
void
Device::save()
{
}
bool
Device::isActive()
{
return false;
//return Video::DeviceModel::instance().activeDevice() == this;
}
void
Device::SetDeviceProperties(String^ format, int width, int height, int rate)
{
auto rl = m_currentChannel->resolutionList();
for (auto res : rl) {
if (res->format() == format &&
res->size()->width() == width &&
res->size()->height() == height &&
res->activeRate()->value() == rate)
{
m_currentChannel->setCurrentResolution(res);
WriteLine("SetDeviceProperties");
return;
}
}
}
\ No newline at end of file
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux *
* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
* Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com> *
* *
* This program 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. *
* *
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
#pragma once
using namespace Platform;
namespace RingClientUWP
{
namespace Video
{
ref class Rate;
ref class Resolution;
ref class Device;
public ref class Size sealed
{
internal:
unsigned int width ();
unsigned int height ();
void setWidth ( unsigned int width );
void setHeight ( unsigned int height );
public:
Size() { };
Size(unsigned int w, unsigned int h):
m_Width(w),
m_Height(h) { };
Size(Size^ rhs):
m_Width(rhs->m_Width),
m_Height(rhs->m_Height) { };
private:
unsigned int m_Width;
unsigned int m_Height;
};
public ref class Rate sealed
{
internal:
String^ name ();
unsigned int value ();
void setName ( String^ name );
void setValue ( unsigned int value );
private:
String^ m_name;
unsigned int m_value;
};
public ref class Channel sealed
{
internal:
String^ name ();
Resolution^ currentResolution ();
Vector<Resolution^>^ resolutionList ();
void setName ( String^ name );
void setCurrentResolution ( Resolution^ currentResolution);
public:
Channel();
private:
String^ m_name;
Resolution^ m_currentResolution;
Vector<Resolution^>^ m_validResolutions;
};
public ref class Resolution sealed
{
internal:
String^ name ();
Rate^ activeRate ();
Vector<Rate^>^ rateList ();
Size^ size ();
String^ format ();
bool setActiveRate ( Rate^ rate );
void setWidth ( int width );
void setHeight ( int height );
void setFormat ( String^ format );
public:
Resolution();
Resolution(Size^ size);
private:
Rate^ m_currentRate;
Vector<Rate^>^ m_validRates;
Size^ m_size;
String^ m_format;
};
public ref class Device sealed
{
internal:
class PreferenceNames {
public:
constexpr static const char* RATE = "rate" ;
constexpr static const char* NAME = "name" ;
constexpr static const char* CHANNEL = "channel";
constexpr static const char* SIZE = "size" ;
};
Vector<Channel^>^ channelList ();
String^ id ();
String^ name ();
Channel^ channel ();
bool setCurrentChannel ( Channel^ channel );
void