Commit e079e94e authored by Ghislain MARY's avatar Ghislain MARY

Define 2 display filters: one to be used in a background process to display to...

Define 2 display filters: one to be used in a background process to display to a SwapChainPanel, and an other to be used in the foreground process to display to a MediaElement.
parent 4f77b48a
......@@ -67,6 +67,8 @@ set(SOURCE_FILES
"MediaEngineNotify.h"
"MediaStreamSource.cpp"
"MediaStreamSource.h"
"mswinrtbackgrounddis.cpp"
"mswinrtbackgrounddis.h"
"mswinrtcap.cpp"
"mswinrtcap.h"
"mswinrtdis.cpp"
......
/*
mswinrtbackgrounddis.cpp
mediastreamer2 library - modular sound and video processing and streaming
Windows Audio Session API sound card plugin for mediastreamer2
Copyright (C) 2010-2015 Belledonne Communications, Grenoble, France
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <wrl.h>
#include "mswinrtbackgrounddis.h"
#include "VideoBuffer.h"
using namespace libmswinrtvid;
MSWinRTBackgroundDis::MSWinRTBackgroundDis()
: mIsActivated(false), mIsStarted(false)
{
mRenderer = ref new MSWinRTRenderer();
}
MSWinRTBackgroundDis::~MSWinRTBackgroundDis()
{
stop();
mRenderer = nullptr;
}
int MSWinRTBackgroundDis::activate()
{
mIsActivated = true;
return 0;
}
int MSWinRTBackgroundDis::deactivate()
{
mIsActivated = false;
return 0;
}
void MSWinRTBackgroundDis::start()
{
if (!mIsStarted && mIsActivated) {
mIsStarted = mRenderer->Start();
}
}
void MSWinRTBackgroundDis::stop()
{
if (mIsStarted) {
mRenderer->Stop();
mIsStarted = false;
}
}
int MSWinRTBackgroundDis::feed(MSFilter *f)
{
if (mIsStarted) {
mblk_t *im;
if ((f->inputs[0] != NULL) && ((im = ms_queue_peek_last(f->inputs[0])) != NULL)) {
MSPicture buf;
if (ms_yuv_buf_init_from_mblk(&buf, im) == 0) {
ms_queue_remove(f->inputs[0], im);
Microsoft::WRL::ComPtr<VideoBuffer> spVideoBuffer = NULL;
Microsoft::WRL::MakeAndInitialize<VideoBuffer>(&spVideoBuffer, buf.planes[0], (int)msgdsize(im), im);
mRenderer->Feed(VideoBuffer::GetIBuffer(spVideoBuffer), buf.w, buf.h);
}
}
}
if (f->inputs[0] != NULL) {
ms_queue_flush(f->inputs[0]);
}
if (f->inputs[1] != NULL) {
ms_queue_flush(f->inputs[1]);
}
return 0;
}
MSVideoSize MSWinRTBackgroundDis::getVideoSize()
{
MSVideoSize vs;
vs.width = mRenderer->FrameWidth;
vs.height = mRenderer->FrameHeight;
return vs;
}
void MSWinRTBackgroundDis::setSwapChainPanel(Platform::String ^swapChainPanelName)
{
mRenderer->SwapChainPanelName = swapChainPanelName;
}
/*
mswinrtbackgrounddis.h
mediastreamer2 library - modular sound and video processing and streaming
Windows Audio Session API sound card plugin for mediastreamer2
Copyright (C) 2010-2015 Belledonne Communications, Grenoble, France
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include <string>
#include "mswinrtvid.h"
#include "Renderer.h"
namespace libmswinrtvid
{
class MSWinRTBackgroundDis {
public:
MSWinRTBackgroundDis();
virtual ~MSWinRTBackgroundDis();
int activate();
int deactivate();
bool isStarted() { return mIsStarted; }
void start();
void stop();
int feed(MSFilter *f);
MSVideoSize getVideoSize();
void setSwapChainPanel(Platform::String ^swapChainPanelName);
private:
bool mIsActivated;
bool mIsStarted;
MSWinRTRenderer^ mRenderer;
};
}
......@@ -3,7 +3,7 @@ mswinrtdis.cpp
mediastreamer2 library - modular sound and video processing and streaming
Windows Audio Session API sound card plugin for mediastreamer2
Copyright (C) 2010-2015 Belledonne Communications, Grenoble, France
Copyright (C) 2010-2013 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
......@@ -17,32 +17,186 @@ 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <wrl.h>
#include "mswinrtdis.h"
#include "VideoBuffer.h"
using namespace libmswinrtvid;
using namespace Microsoft::WRL;
using namespace Windows::Foundation;
using namespace Windows::Media::Core;
using namespace Windows::Media::MediaProperties;
//#define MSWINRTDIS_DEBUG
static void _startMediaElement(Windows::UI::Xaml::Controls::MediaElement^ mediaElement, Windows::Media::Core::MediaStreamSource^ mediaStreamSource)
{
ms_message("[MSWinRTDis] Play MediaElement");
mediaElement->RealTimePlayback = true;
mediaElement->SetMediaStreamSource(mediaStreamSource);
mediaElement->Play();
}
static void _stopMediaElement(Windows::UI::Xaml::Controls::MediaElement^ mediaElement, MSWinRTDisSampleHandler^ sampleHandler)
{
ms_message("[MSWinRTDis] Stop MediaElement");
mediaElement->Stop();
}
MSWinRTDisSampleHandler::MSWinRTDisSampleHandler() :
mSample(nullptr), mReferenceTime(0), mPixFmt(MS_YUV420P), mWidth(MS_VIDEO_SIZE_CIF_W), mHeight(MS_VIDEO_SIZE_CIF_H), mStarted(false)
{
mDeferralQueue = ref new Platform::Collections::Vector<MSWinRTDisDeferral^>();
}
MSWinRTDisSampleHandler::~MSWinRTDisSampleHandler()
{
}
void MSWinRTDisSampleHandler::StartMediaElement()
{
if (mMediaElement != nullptr) {
VideoEncodingProperties^ videoEncodingProperties;
videoEncodingProperties = VideoEncodingProperties::CreateUncompressed(MediaEncodingSubtypes::Nv12, this->Width, this->Height);
VideoStreamDescriptor^ videoStreamDescriptor = ref new VideoStreamDescriptor(videoEncodingProperties);
MediaStreamSource^ mediaStreamSource = ref new MediaStreamSource(videoStreamDescriptor);
mediaStreamSource->SampleRequested += ref new Windows::Foundation::TypedEventHandler<Windows::Media::Core::MediaStreamSource ^, Windows::Media::Core::MediaStreamSourceSampleRequestedEventArgs ^>(this, &MSWinRTDisSampleHandler::OnSampleRequested);
Windows::UI::Xaml::Controls::MediaElement^ mediaElement = mMediaElement;
bool inUIThread = mediaElement->Dispatcher->HasThreadAccess;
mReferenceTime = 0;
if (inUIThread) {
// We are in the UI thread
_startMediaElement(mediaElement, mediaStreamSource);
mStarted = true;
}
else {
// Ask the dispatcher to run this code in the UI thread
mediaElement->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([mediaElement, mediaStreamSource, this]() {
_startMediaElement(mediaElement, mediaStreamSource);
mStarted = true;
}));
}
}
}
void MSWinRTDisSampleHandler::StopMediaElement()
{
if (mMediaElement != nullptr) {
Windows::UI::Xaml::Controls::MediaElement^ mediaElement = mMediaElement;
if (mediaElement->Dispatcher->HasThreadAccess) {
// We are in the UI thread
_stopMediaElement(mediaElement, this);
mDeferralQueue->Clear();
mStarted = false;
}
else {
// Ask the dispatcher to run this code in the UI thread
mediaElement->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([mediaElement, this]() {
_stopMediaElement(mediaElement, this);
mDeferralQueue->Clear();
mStarted = false;
}));
}
}
else {
mDeferralQueue->Clear();
mStarted = false;
}
}
void MSWinRTDisSampleHandler::Feed(Windows::Storage::Streams::IBuffer^ pBuffer)
{
mMutex.lock();
if (!mStarted) {
StartMediaElement();
}
mSample = pBuffer;
if (mDeferralQueue->Size > 0) {
#ifdef MSWINRTDIS_DEBUG
ms_message("[MSWinRTDis] Feed answer deferral");
#endif
MSWinRTDisDeferral^ deferral = mDeferralQueue->GetAt(0);
mDeferralQueue->RemoveAt(0);
AnswerSampleRequest(deferral->Request);
deferral->Deferral->Complete();
}
#ifdef MSWINRTDIS_DEBUG
else {
ms_message("[MSWinRTDis] Feed");
}
#endif
mMutex.unlock();
}
void MSWinRTDisSampleHandler::OnSampleRequested(Windows::Media::Core::MediaStreamSource^ sender, Windows::Media::Core::MediaStreamSourceSampleRequestedEventArgs^ args)
{
MediaStreamSourceSampleRequest^ request = args->Request;
VideoStreamDescriptor^ videoStreamDescriptor = dynamic_cast<VideoStreamDescriptor^>(request->StreamDescriptor);
if (videoStreamDescriptor == nullptr) {
ms_warning("[MSWinRTDis] OnSampleRequested not for a video stream!");
return;
}
mMutex.lock();
if (mSample == nullptr) {
#ifdef MSWINRTDIS_DEBUG
ms_message("[MSWinRTDis] OnSampleRequested defer");
#endif
mDeferralQueue->Append(ref new MSWinRTDisDeferral(request, request->GetDeferral()));
} else {
#ifdef MSWINRTDIS_DEBUG
ms_message("[MSWinRTDis] OnSampleRequested answer");
#endif
AnswerSampleRequest(request);
}
mMutex.unlock();
}
void MSWinRTDisSampleHandler::AnswerSampleRequest(Windows::Media::Core::MediaStreamSourceSampleRequest^ sampleRequest)
{
TimeSpan ts;
UINT64 CurrentTime = GetTickCount64() * 10000LL;
if (mReferenceTime == 0) {
mReferenceTime = CurrentTime;
}
ts.Duration = CurrentTime - mReferenceTime;
sampleRequest->Sample = MediaStreamSample::CreateFromBuffer(mSample, ts);
mSample = nullptr;
}
void MSWinRTDisSampleHandler::RequestMediaElementRestart()
{
mMutex.lock();
ms_message("[MSWinRTDis] RequestMediaElementRestart");
if (mReferenceTime != 0) {
StopMediaElement();
mReferenceTime = 0;
}
mMutex.unlock();
}
MSWinRTDis::MSWinRTDis()
: mIsActivated(false), mIsStarted(false)
: mIsInitialized(false), mIsActivated(false), mIsStarted(false), mSampleHandler(nullptr)
{
mRenderer = ref new MSWinRTRenderer();
mSampleHandler = ref new MSWinRTDisSampleHandler();
mIsInitialized = true;
}
MSWinRTDis::~MSWinRTDis()
{
stop();
mRenderer = nullptr;
}
int MSWinRTDis::activate()
{
if (!mIsInitialized) return -1;
mIsActivated = true;
return 0;
}
......@@ -56,15 +210,15 @@ int MSWinRTDis::deactivate()
void MSWinRTDis::start()
{
if (!mIsStarted && mIsActivated) {
mIsStarted = mRenderer->Start();
mIsStarted = true;
}
}
void MSWinRTDis::stop()
{
if (mIsStarted) {
mRenderer->Stop();
mIsStarted = false;
mSampleHandler->StopMediaElement();
}
}
......@@ -72,14 +226,30 @@ int MSWinRTDis::feed(MSFilter *f)
{
if (mIsStarted) {
mblk_t *im;
mblk_t *om;
if ((f->inputs[0] != NULL) && ((im = ms_queue_peek_last(f->inputs[0])) != NULL)) {
MSPicture buf;
if (ms_yuv_buf_init_from_mblk(&buf, im) == 0) {
ms_queue_remove(f->inputs[0], im);
int size = 0;
MSPicture inbuf;
MSPicture outbuf;
if (ms_yuv_buf_init_from_mblk(&inbuf, im) == 0) {
if ((inbuf.w != mSampleHandler->Width) || (inbuf.h != mSampleHandler->Height)) {
mSampleHandler->Width = inbuf.w;
mSampleHandler->Height = inbuf.h;
mSampleHandler->RequestMediaElementRestart();
}
om = ms_yuv_buf_alloc(&outbuf, inbuf.w, inbuf.h);
int ysize = inbuf.w * inbuf.h;
int usize = ysize / 4;
uint8_t *buffer = outbuf.planes[0];
memcpy(buffer, inbuf.planes[0], ysize);
for (int i = 0; i < usize; i++) {
buffer[ysize + (i * 2)] = inbuf.planes[1][i];
buffer[ysize + (i * 2) + 1] = inbuf.planes[2][i];
}
Microsoft::WRL::ComPtr<VideoBuffer> spVideoBuffer = NULL;
Microsoft::WRL::MakeAndInitialize<VideoBuffer>(&spVideoBuffer, buf.planes[0], (int)msgdsize(im), im);
mRenderer->Feed(VideoBuffer::GetIBuffer(spVideoBuffer), buf.w, buf.h);
Microsoft::WRL::MakeAndInitialize<VideoBuffer>(&spVideoBuffer, buffer, (int)msgdsize(om), om);
mSampleHandler->Feed(VideoBuffer::GetIBuffer(spVideoBuffer));
}
}
}
......@@ -97,12 +267,13 @@ int MSWinRTDis::feed(MSFilter *f)
MSVideoSize MSWinRTDis::getVideoSize()
{
MSVideoSize vs;
vs.width = mRenderer->FrameWidth;
vs.height = mRenderer->FrameHeight;
vs.width = mSampleHandler->Width;
vs.height = mSampleHandler->Height;
return vs;
}
void MSWinRTDis::setSwapChainPanel(Platform::String ^swapChainPanelName)
void MSWinRTDis::setVideoSize(MSVideoSize vs)
{
mRenderer->SwapChainPanelName = swapChainPanelName;
mSampleHandler->Width = vs.width;
mSampleHandler->Height = vs.height;
}
......@@ -3,7 +3,7 @@ mswinrtdis.h
mediastreamer2 library - modular sound and video processing and streaming
Windows Audio Session API sound card plugin for mediastreamer2
Copyright (C) 2010-2015 Belledonne Communications, Grenoble, France
Copyright (C) 2010-2013 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
......@@ -17,20 +17,106 @@ 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#pragma once
#include <string>
#include "mswinrtvid.h"
#include "Renderer.h"
#include <mediastreamer2/rfc3984.h>
#include <collection.h>
#include <ppltasks.h>
#include <mutex>
#include <robuffer.h>
#include <windows.storage.streams.h>
namespace libmswinrtvid
{
class MSWinRTDis;
private ref class MSWinRTDisDeferral sealed
{
public:
MSWinRTDisDeferral(Windows::Media::Core::MediaStreamSourceSampleRequest^ request, Windows::Media::Core::MediaStreamSourceSampleRequestDeferral^ deferral)
{
this->Request = request;
this->Deferral = deferral;
}
property Windows::Media::Core::MediaStreamSourceSampleRequest^ Request
{
Windows::Media::Core::MediaStreamSourceSampleRequest^ get() { return mRequest; }
void set(Windows::Media::Core::MediaStreamSourceSampleRequest^ value) { mRequest = value; }
}
property Windows::Media::Core::MediaStreamSourceSampleRequestDeferral^ Deferral
{
Windows::Media::Core::MediaStreamSourceSampleRequestDeferral^ get() { return mDeferral; }
void set(Windows::Media::Core::MediaStreamSourceSampleRequestDeferral^ value) { mDeferral = value; }
}
private:
~MSWinRTDisDeferral() {};
Windows::Media::Core::MediaStreamSourceSampleRequest^ mRequest;
Windows::Media::Core::MediaStreamSourceSampleRequestDeferral^ mDeferral;
};
private ref class MSWinRTDisSampleHandler sealed
{
public:
MSWinRTDisSampleHandler();
virtual ~MSWinRTDisSampleHandler();
void StartMediaElement();
void StopMediaElement();
void Feed(Windows::Storage::Streams::IBuffer^ pBuffer);
void OnSampleRequested(Windows::Media::Core::MediaStreamSource ^sender, Windows::Media::Core::MediaStreamSourceSampleRequestedEventArgs ^args);
void RequestMediaElementRestart();
property unsigned int PixFmt
{
unsigned int get() { return mPixFmt; }
void set(unsigned int value) { mPixFmt = (MSPixFmt)value; }
}
property Windows::UI::Xaml::Controls::MediaElement^ MediaElement
{
Windows::UI::Xaml::Controls::MediaElement^ get() { return mMediaElement; }
void set(Windows::UI::Xaml::Controls::MediaElement^ value) { mMediaElement = value; }
}
property int Width
{
int get() { return mWidth; }
void set(int value) { mWidth = value; }
}
property int Height
{
int get() { return mHeight; }
void set(int value) { mHeight = value; }
}
private:
void AnswerSampleRequest(Windows::Media::Core::MediaStreamSourceSampleRequest^ sampleRequest);
Windows::Storage::Streams::IBuffer^ mSample;
Platform::Collections::Vector<MSWinRTDisDeferral^>^ mDeferralQueue;
Windows::UI::Xaml::Controls::MediaElement^ mMediaElement;
UINT64 mReferenceTime;
std::mutex mMutex;
MSPixFmt mPixFmt;
int mWidth;
int mHeight;
bool mStarted;
};
class MSWinRTDis {
public:
MSWinRTDis();
......@@ -43,11 +129,14 @@ namespace libmswinrtvid
void stop();
int feed(MSFilter *f);
MSVideoSize getVideoSize();
void setSwapChainPanel(Platform::String ^swapChainPanelName);
void setVideoSize(MSVideoSize vs);
void setMediaElement(Windows::UI::Xaml::Controls::MediaElement^ mediaElement) { mSampleHandler->MediaElement = mediaElement; }
private:
bool mIsInitialized;
bool mIsActivated;
bool mIsStarted;
MSWinRTRenderer^ mRenderer;
MSWinRTDisSampleHandler^ mSampleHandler;
Windows::Media::Core::MediaStreamSource^ mMediaStreamSource;
};
}
......@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/mswebcam.h"
#include "mswinrtcap.h"
#include "mswinrtbackgrounddis.h"
#include "mswinrtdis.h"
#ifdef MS2_WINDOWS_PHONE
#include "IVideoRenderer.h"
......@@ -244,9 +245,9 @@ static int ms_winrtdis_get_vsize(MSFilter *f, void *arg) {
static int ms_winrtdis_set_native_window_id(MSFilter *f, void *arg) {
MSWinRTDis *w = static_cast<MSWinRTDis *>(f->data);
RefToPtrProxy<Platform::String^> *proxy = static_cast<RefToPtrProxy<Platform::String^>*>((void *)(*((PULONG_PTR)arg)));
Platform::String ^swapChainPanelName = proxy->Ref();
w->setSwapChainPanel(swapChainPanelName);
RefToPtrProxy<Platform::Object^> *proxy = static_cast<RefToPtrProxy<Platform::Object^>*>((void *)(*((PULONG_PTR)arg)));
Windows::UI::Xaml::Controls::MediaElement^ mediaElement = dynamic_cast<Windows::UI::Xaml::Controls::MediaElement^>(proxy->Ref());
w->setMediaElement(mediaElement);
return 0;
}
......@@ -291,11 +292,104 @@ MS_FILTER_DESC_EXPORT(ms_winrtdis_desc)
/******************************************************************************
* Methods to (de)initialize and run the WinRT background video display filter *
******************************************************************************/
static void ms_winrtbackgrounddis_init(MSFilter *f) {
MSWinRTBackgroundDis *w = new MSWinRTBackgroundDis();
f->data = w;
}
static void ms_winrtbackgrounddis_preprocess(MSFilter *f) {
MSWinRTBackgroundDis *w = static_cast<MSWinRTBackgroundDis *>(f->data);
w->activate();
w->start();
}
static void ms_winrtbackgrounddis_process(MSFilter *f) {
MSWinRTBackgroundDis *w = static_cast<MSWinRTBackgroundDis *>(f->data);
if (w->isStarted()) {
w->feed(f);
}
}
static void ms_winrtbackgrounddis_postprocess(MSFilter *f) {
MSWinRTBackgroundDis *w = static_cast<MSWinRTBackgroundDis *>(f->data);
w->stop();
w->deactivate();
}
static void ms_winrtbackgrounddis_uninit(MSFilter *f) {
MSWinRTBackgroundDis *w = static_cast<MSWinRTBackgroundDis *>(f->data);
delete w;
}
/******************************************************************************
* Methods to configure the WinRT background video display filter *
******************************************************************************/
static int ms_winrtbackgrounddis_get_vsize(MSFilter *f, void *arg) {
MSWinRTBackgroundDis *w = static_cast<MSWinRTBackgroundDis *>(f->data);
*((MSVideoSize *)arg) = w->getVideoSize();
return 0;
}
static int ms_winrtbackgrounddis_set_native_window_id(MSFilter *f, void *arg) {
MSWinRTBackgroundDis *w = static_cast<MSWinRTBackgroundDis *>(f->data);
RefToPtrProxy<Platform::Object^> *proxy = static_cast<RefToPtrProxy<Platform::Object^>*>((void *)(*((PULONG_PTR)arg)));
Platform::String^ swapChainPanelName = dynamic_cast<Platform::String^>(proxy->Ref());
w->setSwapChainPanel(swapChainPanelName);
return 0;
}
static MSFilterMethod ms_winrtbackgrounddis_methods[] = {
{ MS_FILTER_GET_VIDEO_SIZE, ms_winrtbackgrounddis_get_vsize },
{ MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID, ms_winrtbackgrounddis_set_native_window_id },
{ 0, NULL }
};
/******************************************************************************
* Definition of the WinRT background video display filter *
******************************************************************************/
#define MS_WINRTBACKGROUNDDIS_ID MS_FILTER_PLUGIN_ID
#define MS_WINRTBACKGROUNDDIS_NAME "MSWinRTBackgroundDis"
#define MS_WINRTBACKGROUNDDIS_DESCRIPTION "WinRT background video display"
#define MS_WINRTBACKGROUNDDIS_CATEGORY MS_FILTER_OTHER
#define MS_WINRTBACKGROUNDDIS_ENC_FMT NULL
#define MS_WINRTBACKGROUNDDIS_NINPUTS 2
#define MS_WINRTBACKGROUNDDIS_NOUTPUTS 0
#define MS_WINRTBACKGROUNDDIS_FLAGS 0
MSFilterDesc ms_winrtbackgrounddis_desc = {
MS_WINRTBACKGROUNDDIS_ID,
MS_WINRTBACKGROUNDDIS_NAME,
MS_WINRTBACKGROUNDDIS_DESCRIPTION,
MS_WINRTBACKGROUNDDIS_CATEGORY,
MS_WINRTBACKGROUNDDIS_ENC_FMT,
MS_WINRTBACKGROUNDDIS_NINPUTS,
MS_WINRTBACKGROUNDDIS_NOUTPUTS,
ms_winrtbackgrounddis_init,
ms_winrtbackgrounddis_preprocess,
ms_winrtbackgrounddis_process,
ms_winrtbackgrounddis_postprocess,
ms_winrtbackgrounddis_uninit,
ms_winrtbackgrounddis_methods,
MS_WINRTBACKGROUNDDIS_FLAGS
};
MS_FILTER_DESC_EXPORT(ms_winrtbackgrounddis_desc)
extern "C" __declspec(dllexport) void libmswinrtvid_init(MSFactory *factory) {
MSWebCamManager *manager = ms_factory_get_web_cam_manager(factory);
ms_web_cam_manager_register_desc(manager, &ms_winrtcap_desc);
ms_factory_register_filter(factory, &ms_winrtcap_read_desc);
ms_factory_register_filter(factory, &ms_winrtdis_desc);
ms_factory_register_filter(factory, &ms_winrtbackgrounddis_desc);
ms_message("libmswinrtvid plugin loaded");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment