Commit 2da506c1 authored by Ghislain MARY's avatar Ghislain MARY

Configuration of video capture with custom media sink.

parent dca30e2c
//-----------------------------------------------------------------------------
// File: Linklist.h
// Desc: Linked list class.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#pragma once
// Notes:
//
// The List class template implements a simple double-linked list.
// It uses STL's copy semantics.
// There are two versions of the Clear() method:
// Clear(void) clears the list w/out cleaning up the object.
// Clear(FN fn) takes a functor object that releases the objects, if they need cleanup.
// The List class supports enumeration. Example of usage:
//
// List<T>::POSIITON pos = list.GetFrontPosition();
// while (pos != list.GetEndPosition())
// {
// T item;
// hr = list.GetItemPos(&item);
// pos = list.Next(pos);
// }
// The ComPtrList class template derives from List<> and implements a list of COM pointers.
template <class T>
struct NoOp
{
void operator()(T& t)
{
}
};
template <class T>
class List
{
protected:
// Nodes in the linked list
struct Node
{
Node *prev;
Node *next;
T item;
Node() : prev(nullptr), next(nullptr)
{
}
Node(T item) : prev(nullptr), next(nullptr)
{
this->item = item;
}
T Item() const { return item; }
};
public:
// Object for enumerating the list.
class POSITION
{
friend class List<T>;
public:
POSITION() : pNode(nullptr)
{
}
bool operator==(const POSITION &p) const
{
return pNode == p.pNode;
}
bool operator!=(const POSITION &p) const
{
return pNode != p.pNode;
}
private:
const Node *pNode;
POSITION(Node *p) : pNode(p)
{
}
};
protected:
Node m_anchor; // Anchor node for the linked list.
DWORD m_count; // Number of items in the list.
Node* Front() const
{
return m_anchor.next;
}
Node* Back() const
{
return m_anchor.prev;
}
virtual HRESULT InsertAfter(T item, Node *pBefore)
{
if (pBefore == nullptr)
{
return E_POINTER;
}
Node *pNode = new Node(item);
if (pNode == nullptr)
{
return E_OUTOFMEMORY;
}
Node *pAfter = pBefore->next;
pBefore->next = pNode;
pAfter->prev = pNode;
pNode->prev = pBefore;
pNode->next = pAfter;
m_count++;
return S_OK;
}
virtual HRESULT GetItem(const Node *pNode, T* ppItem)
{
if (pNode == nullptr || ppItem == nullptr)
{
return E_POINTER;
}
*ppItem = pNode->item;
return S_OK;
}
// RemoveItem:
// Removes a node and optionally returns the item.
// ppItem can be nullptr.
virtual HRESULT RemoveItem(Node *pNode, T *ppItem)
{
if (pNode == nullptr)
{
return E_POINTER;
}
if (pNode == &m_anchor)
{
return E_INVALIDARG;
}
T item;
// The next node's previous is this node's previous.
pNode->next->prev = pNode->prev;
// The previous node's next is this node's next.
pNode->prev->next = pNode->next;
item = pNode->item;
delete pNode;
m_count--;
if (ppItem)
{
*ppItem = item;
}
return S_OK;
}
public:
List()
{
m_anchor.next = &m_anchor;
m_anchor.prev = &m_anchor;
m_count = 0;
}
virtual ~List()
{
Clear();
}
// Insertion functions
HRESULT InsertBack(T item)
{
return InsertAfter(item, m_anchor.prev);
}
HRESULT InsertFront(T item)
{
return InsertAfter(item, &m_anchor);
}
HRESULT InsertPos(POSITION pos, T item)
{
if (pos.pNode == nullptr)
{
return InsertBack(item);
}
return InsertAfter(item, pos.pNode->prev);
}
// RemoveBack: Removes the tail of the list and returns the value.
// ppItem can be nullptr if you don't want the item back. (But the method does not release the item.)
HRESULT RemoveBack(T *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return RemoveItem(Back(), ppItem);
}
}
// RemoveFront: Removes the head of the list and returns the value.
// ppItem can be nullptr if you don't want the item back. (But the method does not release the item.)
HRESULT RemoveFront(T *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return RemoveItem(Front(), ppItem);
}
}
// GetBack: Gets the tail item.
HRESULT GetBack(T *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return GetItem(Back(), ppItem);
}
}
// GetFront: Gets the front item.
HRESULT GetFront(T *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return GetItem(Front(), ppItem);
}
}
// GetCount: Returns the number of items in the list.
DWORD GetCount() const { return m_count; }
bool IsEmpty() const
{
return (GetCount() == 0);
}
// Clear: Takes a functor object whose operator()
// frees the object on the list.
template <class FN>
void Clear(FN& clear_fn)
{
Node *n = m_anchor.next;
// Delete the nodes
while (n != &m_anchor)
{
clear_fn(n->item);
Node *tmp = n->next;
delete n;
n = tmp;
}
// Reset the anchor to point at itself
m_anchor.next = &m_anchor;
m_anchor.prev = &m_anchor;
m_count = 0;
}
// Clear: Clears the list. (Does not delete or release the list items.)
virtual void Clear()
{
NoOp<T> clearOp;
Clear<>(clearOp);
}
// Enumerator functions
POSITION FrontPosition()
{
if (IsEmpty())
{
return POSITION(nullptr);
}
else
{
return POSITION(Front());
}
}
POSITION EndPosition() const
{
return POSITION();
}
HRESULT GetItemPos(POSITION pos, T *ppItem)
{
if (pos.pNode)
{
return GetItem(pos.pNode, ppItem);
}
else
{
return E_FAIL;
}
}
POSITION Next(const POSITION pos)
{
if (pos.pNode && (pos.pNode->next != &m_anchor))
{
return POSITION(pos.pNode->next);
}
else
{
return POSITION(nullptr);
}
}
// Remove an item at a position.
// The item is returns in ppItem, unless ppItem is nullptr.
// NOTE: This method invalidates the POSITION object.
HRESULT Remove(POSITION& pos, T *ppItem)
{
if (pos.pNode)
{
// Remove const-ness temporarily...
Node *pNode = const_cast<Node*>(pos.pNode);
pos = POSITION();
return RemoveItem(pNode, ppItem);
}
else
{
return E_INVALIDARG;
}
}
};
// Typical functors for Clear method.
// ComAutoRelease: Releases COM pointers.
// MemDelete: Deletes pointers to new'd memory.
class ComAutoRelease
{
public:
void operator()(IUnknown *p)
{
if (p)
{
p->Release();
}
}
};
class MemDelete
{
public:
void operator()(void *p)
{
if (p)
{
delete p;
}
}
};
// ComPtrList class
// Derived class that makes it safer to store COM pointers in the List<> class.
// It automatically AddRef's the pointers that are inserted onto the list
// (unless the insertion method fails).
//
// T must be a COM interface type.
// example: ComPtrList<IUnknown>
//
// NULLABLE: If true, client can insert nullptr pointers. This means GetItem can
// succeed but return a nullptr pointer. By default, the list does not allow nullptr
// pointers.
template <class T, bool NULLABLE = FALSE>
class ComPtrList : public List<T*>
{
public:
typedef T* Ptr;
void Clear()
{
ComAutoRelease car;
List<Ptr>::Clear(car);
}
~ComPtrList()
{
Clear();
}
protected:
HRESULT InsertAfter(Ptr item, Node *pBefore)
{
// Do not allow nullptr item pointers unless NULLABLE is true.
if (item == nullptr && !NULLABLE)
{
return E_POINTER;
}
if (item)
{
item->AddRef();
}
HRESULT hr = List<Ptr>::InsertAfter(item, pBefore);
if (FAILED(hr) && item != nullptr)
{
item->Release();
}
return hr;
}
HRESULT GetItem(const Node *pNode, Ptr* ppItem)
{
Ptr pItem = nullptr;
// The base class gives us the pointer without AddRef'ing it.
// If we return the pointer to the caller, we must AddRef().
HRESULT hr = List<Ptr>::GetItem(pNode, &pItem);
if (SUCCEEDED(hr))
{
if (pItem)
{
*ppItem = pItem;
(*ppItem)->AddRef();
}
}
return hr;
}
HRESULT RemoveItem(Node *pNode, Ptr *ppItem)
{
// ppItem can be nullptr, but we need to get the
// item so that we can release it.
// If ppItem is not nullptr, we will AddRef it on the way out.
Ptr pItem = nullptr;
HRESULT hr = List<Ptr>::RemoveItem(pNode, &pItem);
if (SUCCEEDED(hr))
{
if (ppItem && pItem)
{
*ppItem = pItem;
(*ppItem)->AddRef();
}
if (pItem)
{
pItem->Release();
pItem = nullptr;
}
}
return hr;
}
};
This diff is collapsed.
......@@ -29,135 +29,85 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <mediastreamer2/videostarter.h>
#include "mswinrtvid.h"
#include "mswinrtmediasink.h"
#ifdef MS2_WINDOWS_UNIVERSAL
#include <wrl\implements.h>
#include <ppltasks.h>
using namespace Windows::Media::Capture;
using namespace Windows::Media::Devices;
using namespace Windows::Media::MediaProperties;
#endif
#ifdef MS2_WINDOWS_PHONE
#include "implements.h"
#include <Windows.Phone.Media.Capture.h>
#include <Windows.Phone.Media.Capture.Native.h>
#endif
#ifdef MS2_WINDOWS_PHONE
class SampleSink;
#endif
class MSWinRTCap {
public:
MSWinRTCap();
virtual ~MSWinRTCap();
int activate();
int deactivate();
bool isStarted() { return mIsStarted; }
void start();
void stop();
int feed(MSFilter *f);
void OnSampleAvailable(ULONGLONG hnsPresentationTime, ULONGLONG hnsSampleDuration, DWORD cbSample, BYTE* pSample);
#ifdef MS2_WINDOWS_UNIVERSAL
void setCaptureElement(Windows::UI::Xaml::Controls::CaptureElement^ captureElement) { mCaptureElement = captureElement; };
void setDeviceId(Platform::String^ id) { mDeviceId = id; };
#endif
#ifdef MS2_WINDOWS_PHONE
void setCameraLocation(uint32 location);
#endif
MSPixFmt getPixFmt() { return mPixFmt; }
void setPixFmt(MSPixFmt pixFmt) { mPixFmt = pixFmt; }
float getFps() { return mVConf.fps; }
void setFps(float fps);
int getBitrate() { return mBitrate; }
void setBitrate(int bitrate);
MSVideoSize getVideoSize();
void setVideoSize(MSVideoSize vs);
const MSVideoConfiguration * getConfigurationList();
void setConfiguration(const MSVideoConfiguration *vconf);
int getCameraSensorRotation() { return mCameraSensorRotation; }
void setDeviceOrientation(int degrees);
void requestIdrFrame();
static void detectCameras(MSWebCamManager *manager, MSWebCamDesc *desc);
private:
void applyFps();
void applyVideoSize();
void bitstreamToMsgb(uint8_t *encoded_buf, size_t size, MSQueue *nalus);
bool selectBestVideoSize();
void configure();
void printProperties();
#ifdef MS2_WINDOWS_UNIVERSAL
static void addCamera(MSWebCamManager *manager, MSWebCamDesc *desc, Platform::String^ DeviceId, Platform::String^ DeviceName);
#endif
static bool smInstantiated;
bool mIsInitialized;
bool mIsActivated;
bool mIsStarted;
MSQueue mSampleToSendQueue;
MSQueue mSampleToFreeQueue;
ms_mutex_t mMutex;
Rfc3984Context *mRfc3984Packer;
MSYuvBufAllocator *mAllocator;
int mPackerMode;
uint64_t mStartTime;
int mSamplesCount;
int mBitrate;
int mCameraSensorRotation;
int mDeviceOrientation;
MSVideoStarter mStarter;
MSVideoConfiguration mVConf;
MSPixFmt mPixFmt;
HANDLE mActivationCompleted;
HANDLE mStartCompleted;
HANDLE mStopCompleted;
#ifdef MS2_WINDOWS_UNIVERSAL
HANDLE mPreviewStartCompleted;
Windows::UI::Xaml::Controls::CaptureElement^ mCaptureElement;
Platform::String^ mDeviceId;
Platform::Agile<MediaCapture^> mCapture;
MediaEncodingProfile^ mEncodingProfile;
Windows::Storage::Streams::InMemoryRandomAccessStream^ mStream;
#endif
#ifdef MS2_WINDOWS_PHONE
Windows::Phone::Media::Capture::CameraSensorLocation mCameraLocation;
Windows::Phone::Media::Capture::AudioVideoCaptureDevice^ mVideoDevice;
SampleSink *mVideoSink;
IAudioVideoCaptureDeviceNative* mNativeVideoDevice;
#endif
};
#ifdef MS2_WINDOWS_PHONE
class SampleSink
: public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ICameraCaptureSampleSink>
namespace libmswinrtvid
{
public:
STDMETHODIMP RuntimeClassInitialize(MSWinRTCap *reader) {
m_dwSampleCount = 0;
m_reader = reader;
return S_OK;
}
DWORD GetSampleCount() {
return m_dwSampleCount;
}
IFACEMETHODIMP_(void) OnSampleAvailable(ULONGLONG hnsPresentationTime, ULONGLONG hnsSampleDuration, DWORD cbSample, BYTE* pSample) {
m_dwSampleCount++;
if (m_reader) {
m_reader->OnSampleAvailable(hnsPresentationTime, hnsSampleDuration, cbSample, pSample);
}
}
private:
DWORD m_dwSampleCount;
MSWinRTCap *m_reader;
};
#endif
class MSWinRTCap {
public:
MSWinRTCap();
virtual ~MSWinRTCap();
int activate();
int deactivate();
bool isStarted() { return mIsStarted; }
void start();
void stop();
int feed(MSFilter *f);
void OnSampleAvailable(ULONGLONG hnsPresentationTime, ULONGLONG hnsSampleDuration, DWORD cbSample, BYTE* pSample);
void setCaptureElement(Windows::UI::Xaml::Controls::CaptureElement^ captureElement) { mCaptureElement = captureElement; };
void setDeviceId(Platform::String^ id) { mDeviceId = id; };
MSPixFmt getPixFmt() { return mPixFmt; }
void setPixFmt(MSPixFmt pixFmt) { mPixFmt = pixFmt; }
float getFps() { return mVConf.fps; }
void setFps(float fps);
int getBitrate() { return mBitrate; }
void setBitrate(int bitrate);
MSVideoSize getVideoSize();
void setVideoSize(MSVideoSize vs);
const MSVideoConfiguration * getConfigurationList();
void setConfiguration(const MSVideoConfiguration *vconf);
int getCameraSensorRotation() { return mCameraSensorRotation; }
void setDeviceOrientation(int degrees);
void requestIdrFrame();
static void detectCameras(MSWebCamManager *manager, MSWebCamDesc *desc);
private:
void applyFps();
void applyVideoSize();
void bitstreamToMsgb(uint8_t *encoded_buf, size_t size, MSQueue *nalus);
bool selectBestVideoSize();
void configure();
void printProperties();
static void addCamera(MSWebCamManager *manager, MSWebCamDesc *desc, Platform::String^ DeviceId, Platform::String^ DeviceName);
static bool smInstantiated;
bool mIsInitialized;
bool mIsActivated;
bool mIsStarted;
MSQueue mSampleToSendQueue;
MSQueue mSampleToFreeQueue;
ms_mutex_t mMutex;
Rfc3984Context *mRfc3984Packer;
MSYuvBufAllocator *mAllocator;
int mPackerMode;
uint64_t mStartTime;
int mSamplesCount;
int mBitrate;
int mCameraSensorRotation;
int mDeviceOrientation;
MSVideoStarter mStarter;
MSVideoConfiguration mVConf;
MSPixFmt mPixFmt;
HANDLE mActivationCompleted;
HANDLE mStartCompleted;
HANDLE mStopCompleted;
HANDLE mPreviewStartCompleted;
Windows::UI::Xaml::Controls::CaptureElement^ mCaptureElement;
Platform::String^ mDeviceId;
Platform::Agile<MediaCapture^> mCapture;
MediaEncodingProfile^ mEncodingProfile;
MSWinRTMediaSinkProxy^ mMediaSink;
};
}
This diff is collapsed.
This diff is collapsed.
......@@ -37,11 +37,14 @@
<ItemGroup>
<ClCompile Include="..\..\mswinrtcap.cpp" />
<ClCompile Include="..\..\mswinrtdis.cpp" />
<ClCompile Include="..\..\mswinrtmediasink.cpp" />
<ClCompile Include="..\..\mswinrtvid.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\LinkList.h" />
<ClInclude Include="..\..\mswinrtcap.h" />
<ClInclude Include="..\..\mswinrtdis.h" />
<ClInclude Include="..\..\mswinrtmediasink.h" />
<ClInclude Include="..\..\mswinrtvid.h" />
<ClInclude Include="..\..\VideoBuffer.h" />
</ItemGroup>
......@@ -92,6 +95,7 @@
<Link>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<AdditionalDependencies>WindowsApp.lib;mfplat.lib;mfuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
......@@ -106,6 +110,7 @@
<Link>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<AdditionalDependencies>WindowsApp.lib;mfplat.lib;mfuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
......
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