Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
b0b2d8de
Commit
b0b2d8de
authored
Apr 13, 2018
by
Vitaly Tuzov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove unused code
parent
44848d32
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
550 additions
and
4256 deletions
+550
-4256
cap_msmf.cpp
modules/videoio/src/cap_msmf.cpp
+550
-1752
cap_msmf.hpp
modules/videoio/src/cap_msmf.hpp
+0
-2504
No files found.
modules/videoio/src/cap_msmf.cpp
View file @
b0b2d8de
...
...
@@ -52,9 +52,6 @@
#undef WINVER
#define WINVER _WIN32_WINNT_WIN8
#endif
#if defined _MSC_VER && _MSC_VER >= 1600
#define HAVE_CONCURRENCY
#endif
#include <windows.h>
#include <guiddef.h>
#include <mfidl.h>
...
...
@@ -97,15 +94,6 @@ struct IMFAttributes;
namespace
{
template
<
class
T
>
void
SafeRelease
(
T
**
ppT
)
{
if
(
*
ppT
)
{
(
*
ppT
)
->
Release
();
*
ppT
=
NULL
;
}
}
#ifdef _DEBUG
void
DPOprintOut
(
const
wchar_t
*
format
,
...)
{
...
...
@@ -138,166 +126,154 @@ void DPOprintOut(const wchar_t *format, ...)
#define DebugPrintOut(...) void()
#endif
#include "cap_msmf.hpp"
template
<
class
T
>
class
ComPtr
{
public
:
ComPtr
()
throw
()
{
}
ComPtr
(
T
*
lp
)
throw
()
{
p
=
lp
;
}
ComPtr
(
_In_
const
ComPtr
<
T
>&
lp
)
throw
()
{
p
=
lp
.
p
;
}
virtual
~
ComPtr
()
{
}
T
**
operator
&
()
throw
()
{
assert
(
p
==
NULL
);
return
p
.
operator
&
();
}
T
*
operator
->
()
const
throw
()
{
assert
(
p
!=
NULL
);
return
p
.
operator
->
();
}
bool
operator
!
()
const
throw
()
{
return
p
.
operator
==
(
NULL
);
}
bool
operator
==
(
_In_opt_
T
*
pT
)
const
throw
()
{
return
p
.
operator
==
(
pT
);
}
bool
operator
!=
(
_In_opt_
T
*
pT
)
const
throw
()
{
return
p
.
operator
!=
(
pT
);
}
operator
bool
()
{
return
p
.
operator
!=
(
NULL
);
}
T
*
const
*
GetAddressOf
()
const
throw
()
{
return
&
p
;
}
T
**
GetAddressOf
()
throw
()
{
return
&
p
;
}
T
**
ReleaseAndGetAddressOf
()
throw
()
{
p
.
Release
();
return
&
p
;
}
T
*
Get
()
const
throw
()
{
return
p
;
}
// Attach to an existing interface (does not AddRef)
void
Attach
(
_In_opt_
T
*
p2
)
throw
()
{
p
.
Attach
(
p2
);
}
// Detach the interface (does not Release)
T
*
Detach
()
throw
()
{
return
p
.
Detach
();
}
_Check_return_
HRESULT
CopyTo
(
_Deref_out_opt_
T
**
ppT
)
throw
()
{
assert
(
ppT
!=
NULL
);
if
(
ppT
==
NULL
)
return
E_POINTER
;
*
ppT
=
p
;
if
(
p
!=
NULL
)
p
->
AddRef
();
return
S_OK
;
}
void
Reset
()
{
p
.
Release
();
}
// query for U interface
template
<
typename
U
>
HRESULT
As
(
_Inout_
U
**
lp
)
const
throw
()
{
return
p
->
QueryInterface
(
__uuidof
(
U
),
reinterpret_cast
<
void
**>
(
lp
));
}
// query for U interface
template
<
typename
U
>
HRESULT
As
(
_Out_
ComPtr
<
U
>*
lp
)
const
throw
()
{
return
p
->
QueryInterface
(
__uuidof
(
U
),
reinterpret_cast
<
void
**>
(
lp
->
ReleaseAndGetAddressOf
()));
}
private
:
_COM_SMARTPTR_TYPEDEF
(
T
,
__uuidof
(
T
));
TPtr
p
;
};
#define _ComPtr ComPtr
// Structure for collecting info about types of video, which are supported by current video device
struct
MediaType
{
unsigned
int
MF_MT_FRAME_SIZE
;
unsigned
int
height
;
unsigned
int
width
;
UINT32
height
;
UINT32
width
;
unsigned
int
MF_MT_YUV_MATRIX
;
unsigned
int
MF_MT_VIDEO_LIGHTING
;
int
MF_MT_DEFAULT_STRIDE
;
// stride is negative if image is bottom-up
unsigned
int
MF_MT_VIDEO_CHROMA_SITING
;
GUID
MF_MT_AM_FORMAT_TYPE
;
wchar_t
*
pMF_MT_AM_FORMAT_TYPEName
;
LPCWSTR
pMF_MT_AM_FORMAT_TYPEName
;
unsigned
int
MF_MT_FIXED_SIZE_SAMPLES
;
unsigned
int
MF_MT_VIDEO_NOMINAL_RANGE
;
unsigned
int
MF_MT_FRAME_RATE_NUMERATOR
;
unsigned
int
MF_MT_FRAME_RATE_DENOMINATOR
;
unsigned
int
MF_MT_PIXEL_ASPECT_RATIO
;
unsigned
int
MF_MT_PIXEL_ASPECT_RATIO_low
;
UINT32
MF_MT_FRAME_RATE_NUMERATOR
;
UINT32
MF_MT_FRAME_RATE_DENOMINATOR
;
UINT32
MF_MT_PIXEL_ASPECT_RATIO
;
UINT32
MF_MT_PIXEL_ASPECT_RATIO_low
;
unsigned
int
MF_MT_ALL_SAMPLES_INDEPENDENT
;
unsigned
int
MF_MT_FRAME_RATE_RANGE_MIN
;
unsigned
int
MF_MT_FRAME_RATE_RANGE_MIN_low
;
UINT32
MF_MT_FRAME_RATE_RANGE_MIN
;
UINT32
MF_MT_FRAME_RATE_RANGE_MIN_low
;
unsigned
int
MF_MT_SAMPLE_SIZE
;
unsigned
int
MF_MT_VIDEO_PRIMARIES
;
unsigned
int
MF_MT_INTERLACE_MODE
;
unsigned
int
MF_MT_FRAME_RATE_RANGE_MAX
;
unsigned
int
MF_MT_FRAME_RATE_RANGE_MAX_low
;
UINT32
MF_MT_FRAME_RATE_RANGE_MAX
;
UINT32
MF_MT_FRAME_RATE_RANGE_MAX_low
;
GUID
MF_MT_MAJOR_TYPE
;
GUID
MF_MT_SUBTYPE
;
wchar_t
*
pMF_MT_MAJOR_TYPEName
;
wchar_t
*
pMF_MT_SUBTYPEName
;
LPCWSTR
pMF_MT_MAJOR_TYPEName
;
LPCWSTR
pMF_MT_SUBTYPEName
;
MediaType
();
MediaType
(
IMFMediaType
*
pType
);
~
MediaType
();
void
Clear
();
};
/// Class for parsing info from IMFMediaType into the local MediaType
class
FormatReader
{
public
:
static
MediaType
Read
(
IMFMediaType
*
pType
);
~
FormatReader
(
void
);
private
:
FormatReader
(
void
);
};
DWORD
WINAPI
MainThreadFunction
(
LPVOID
lpParam
);
typedef
void
(
*
emergensyStopEventCallback
)(
int
,
void
*
);
class
RawImage
{
public
:
~
RawImage
(
void
);
// Function of creation of the instance of the class
static
long
CreateInstance
(
RawImage
**
ppRImage
,
unsigned
int
size
);
void
setCopy
(
const
BYTE
*
pSampleBuffer
);
void
fastCopy
(
const
BYTE
*
pSampleBuffer
);
unsigned
char
*
getpPixels
();
bool
isNew
();
unsigned
int
getSize
();
private
:
bool
ri_new
;
unsigned
int
ri_size
;
unsigned
char
*
ri_pixels
;
RawImage
(
unsigned
int
size
);
};
class
ImageGrabberCallback
:
public
IMFSampleGrabberSinkCallback
{
public
:
void
pauseGrabbing
();
void
resumeGrabbing
();
RawImage
*
getRawImage
();
// IMFClockStateSink methods
STDMETHODIMP
OnClockStart
(
MFTIME
hnsSystemTime
,
LONGLONG
llClockStartOffset
);
STDMETHODIMP
OnClockStop
(
MFTIME
hnsSystemTime
);
STDMETHODIMP
OnClockPause
(
MFTIME
hnsSystemTime
);
STDMETHODIMP
OnClockRestart
(
MFTIME
hnsSystemTime
);
STDMETHODIMP
OnClockSetRate
(
MFTIME
hnsSystemTime
,
float
flRate
);
// IMFSampleGrabberSinkCallback methods
STDMETHODIMP
OnSetPresentationClock
(
IMFPresentationClock
*
pClock
);
STDMETHODIMP
OnProcessSample
(
REFGUID
guidMajorMediaType
,
DWORD
dwSampleFlags
,
LONGLONG
llSampleTime
,
LONGLONG
llSampleDuration
,
const
BYTE
*
pSampleBuffer
,
DWORD
dwSampleSize
);
STDMETHODIMP
OnShutdown
();
const
HANDLE
ig_hFrameReady
;
const
HANDLE
ig_hFrameGrabbed
;
const
HANDLE
ig_hFinish
;
protected
:
ImageGrabberCallback
(
bool
synchronous
);
bool
ig_RIE
;
bool
ig_Close
;
bool
ig_Synchronous
;
long
m_cRef
;
RawImage
*
ig_RIFirst
;
RawImage
*
ig_RISecond
;
RawImage
*
ig_RIOut
;
private
:
ImageGrabberCallback
&
operator
=
(
const
ImageGrabberCallback
&
);
// Declared to fix compilation warning.
};
// Class for grabbing image from video stream
class
ImageGrabber
:
public
ImageGrabberCallback
{
public
:
~
ImageGrabber
(
void
);
HRESULT
initImageGrabber
(
IMFMediaSource
*
pSource
);
HRESULT
startGrabbing
(
void
);
void
stopGrabbing
();
// IUnknown methods
STDMETHODIMP
QueryInterface
(
REFIID
iid
,
void
**
ppv
);
STDMETHODIMP_
(
ULONG
)
AddRef
();
STDMETHODIMP_
(
ULONG
)
Release
();
// Function of creation of the instance of the class
static
HRESULT
CreateInstance
(
ImageGrabber
**
ppIG
,
unsigned
int
deviceID
,
bool
synchronous
=
false
);
const
MediaType
*
getCaptureFormat
()
{
return
&
captureFormat
;
}
private
:
unsigned
int
ig_DeviceID
;
IMFMediaSource
*
ig_pSource
;
MediaType
captureFormat
;
IMFMediaSession
*
ig_pSession
;
IMFTopology
*
ig_pTopology
;
ImageGrabber
(
unsigned
int
deviceID
,
bool
synchronous
);
HRESULT
CreateTopology
(
IMFMediaSource
*
pSource
,
IMFActivate
*
pSinkActivate
,
IMFTopology
**
ppTopo
);
HRESULT
AddSourceNode
(
IMFTopology
*
pTopology
,
IMFMediaSource
*
pSource
,
IMFPresentationDescriptor
*
pPD
,
IMFStreamDescriptor
*
pSD
,
IMFTopologyNode
**
ppNode
);
HRESULT
AddOutputNode
(
IMFTopology
*
pTopology
,
IMFActivate
*
pActivate
,
DWORD
dwId
,
IMFTopologyNode
**
ppNode
);
ImageGrabber
&
operator
=
(
const
ImageGrabber
&
);
// Declared to fix comiplation error.
};
/// Class for controlling of thread of the grabbing raw data from video device
class
ImageGrabberThread
{
friend
DWORD
WINAPI
MainThreadFunction
(
LPVOID
lpParam
);
public
:
~
ImageGrabberThread
(
void
);
static
HRESULT
CreateInstance
(
ImageGrabberThread
**
ppIGT
,
IMFMediaSource
*
pSource
,
unsigned
int
deviceID
,
bool
synchronious
=
false
);
void
start
();
void
stop
();
void
setEmergencyStopEvent
(
void
*
userData
,
void
(
*
func
)(
int
,
void
*
));
ImageGrabber
*
getImageGrabber
();
protected
:
virtual
void
run
();
private
:
ImageGrabberThread
(
IMFMediaSource
*
pSource
,
unsigned
int
deviceID
,
bool
synchronious
);
HANDLE
igt_Handle
;
DWORD
igt_ThreadIdArray
;
ImageGrabber
*
igt_pImageGrabber
;
emergensyStopEventCallback
igt_func
;
void
*
igt_userData
;
bool
igt_stop
;
unsigned
int
igt_DeviceID
;
};
// Structure for collecting info about one parametr of current video device
struct
Parametr
{
...
...
@@ -307,1652 +283,473 @@ struct Parametr
long
Step
;
long
Default
;
long
Flag
;
Parametr
();
Parametr
()
{
CurrentValue
=
0
;
Min
=
0
;
Max
=
0
;
Step
=
0
;
Default
=
0
;
Flag
=
0
;
}
};
// Structure for collecting info about 17 parametrs of current video device
struct
CamParametrs
{
Parametr
Brightness
;
Parametr
Contrast
;
Parametr
Hue
;
Parametr
Saturation
;
Parametr
Sharpness
;
Parametr
Gamma
;
Parametr
ColorEnable
;
Parametr
WhiteBalance
;
Parametr
BacklightCompensation
;
Parametr
Gain
;
Parametr
Pan
;
Parametr
Tilt
;
Parametr
Roll
;
Parametr
Zoom
;
Parametr
Exposure
;
Parametr
Iris
;
Parametr
Focus
;
};
typedef
std
::
wstring
String
;
typedef
std
::
vector
<
int
>
vectorNum
;
typedef
std
::
map
<
String
,
vectorNum
>
SUBTYPEMap
;
typedef
std
::
map
<
UINT64
,
SUBTYPEMap
>
FrameRateMap
;
typedef
void
(
*
emergensyStopEventCallback
)(
int
,
void
*
);
/// Class for controlling of video device
class
videoDevice
{
public
:
videoDevice
(
void
);
~
videoDevice
(
void
);
void
closeDevice
();
CamParametrs
getParametrs
();
void
setParametrs
(
CamParametrs
parametrs
);
void
setEmergencyStopEvent
(
void
*
userData
,
void
(
*
func
)(
int
,
void
*
));
long
readInfoOfDevice
(
IMFActivate
*
pActivate
,
unsigned
int
Num
);
int
getCountFormats
();
unsigned
int
getWidth
();
unsigned
int
getHeight
();
unsigned
int
getFrameRate
()
const
;
MediaType
getFormat
(
unsigned
int
id
);
bool
setupDevice
(
unsigned
int
w
,
unsigned
int
h
,
unsigned
int
idealFramerate
=
0
);
bool
setupDevice
(
unsigned
int
id
);
bool
isDeviceSetup
();
bool
isDeviceMediaSource
();
bool
isDeviceRawDataSource
();
bool
isFrameNew
();
IMFMediaSource
*
getMediaSource
();
RawImage
*
getRawImageOut
();
private
:
enum
typeLock
{
MediaSourceLock
,
RawDataLock
,
OpenLock
}
vd_LockOut
;
wchar_t
*
vd_pFriendlyName
;
ImageGrabberThread
*
vd_pImGrTh
;
unsigned
int
vd_Width
;
unsigned
int
vd_Height
;
unsigned
int
vd_FrameRate
;
unsigned
int
vd_CurrentNumber
;
bool
vd_IsSetuped
;
std
::
map
<
UINT64
,
FrameRateMap
>
vd_CaptureFormats
;
std
::
vector
<
MediaType
>
vd_CurrentFormats
;
IMFMediaSource
*
vd_pSource
;
emergensyStopEventCallback
vd_func
;
void
*
vd_userData
;
HRESULT
enumerateCaptureFormats
(
IMFMediaSource
*
pSource
);
long
setDeviceFormat
(
IMFMediaSource
*
pSource
,
unsigned
long
dwFormatIndex
);
void
buildLibraryofTypes
();
int
findType
(
unsigned
int
size
,
unsigned
int
frameRate
=
0
);
long
checkDevice
(
IMFActivate
**
pDevice
);
long
initDevice
();
};
/// Class for managing of list of video devices
class
videoDevices
{
public
:
~
videoDevices
(
void
);
static
cv
::
Ptr
<
videoDevice
>
getDevice
(
unsigned
int
i
,
bool
fallback
=
false
);
private
:
videoDevices
(
void
);
};
// Class for creating of Media Foundation context
class
Media_Foundation
{
public
:
~
Media_Foundation
(
void
)
{
/*CV_Assert(SUCCEEDED(MFShutdown()));*/
}
static
Media_Foundation
&
getInstance
()
{
static
Media_Foundation
instance
;
return
instance
;
}
private
:
Media_Foundation
(
void
)
{
CV_Assert
(
SUCCEEDED
(
MFStartup
(
MF_VERSION
)));
}
Parametr
Brightness
;
Parametr
Contrast
;
Parametr
Hue
;
Parametr
Saturation
;
Parametr
Sharpness
;
Parametr
Gamma
;
Parametr
ColorEnable
;
Parametr
WhiteBalance
;
Parametr
BacklightCompensation
;
Parametr
Gain
;
Parametr
Pan
;
Parametr
Tilt
;
Parametr
Roll
;
Parametr
Zoom
;
Parametr
Exposure
;
Parametr
Iris
;
Parametr
Focus
;
};
LPCWSTR
GetGUIDNameConstNew
(
const
GUID
&
guid
);
HRESULT
GetGUIDNameNew
(
const
GUID
&
guid
,
WCHAR
**
ppwsz
);
HRESULT
LogAttributeValueByIndexNew
(
IMFAttributes
*
pAttr
,
DWORD
index
);
HRESULT
SpecialCaseAttributeValueNew
(
GUID
guid
,
const
PROPVARIANT
&
var
,
MediaType
&
out
);
unsigned
int
*
GetParametr
(
GUID
guid
,
MediaType
&
out
)
{
if
(
guid
==
MF_MT_YUV_MATRIX
)
return
&
(
out
.
MF_MT_YUV_MATRIX
);
if
(
guid
==
MF_MT_VIDEO_LIGHTING
)
return
&
(
out
.
MF_MT_VIDEO_LIGHTING
);
if
(
guid
==
MF_MT_DEFAULT_STRIDE
)
return
(
unsigned
int
*
)
&
(
out
.
MF_MT_DEFAULT_STRIDE
);
if
(
guid
==
MF_MT_VIDEO_CHROMA_SITING
)
return
&
(
out
.
MF_MT_VIDEO_CHROMA_SITING
);
if
(
guid
==
MF_MT_VIDEO_NOMINAL_RANGE
)
return
&
(
out
.
MF_MT_VIDEO_NOMINAL_RANGE
);
if
(
guid
==
MF_MT_ALL_SAMPLES_INDEPENDENT
)
return
&
(
out
.
MF_MT_ALL_SAMPLES_INDEPENDENT
);
if
(
guid
==
MF_MT_FIXED_SIZE_SAMPLES
)
return
&
(
out
.
MF_MT_FIXED_SIZE_SAMPLES
);
if
(
guid
==
MF_MT_SAMPLE_SIZE
)
return
&
(
out
.
MF_MT_SAMPLE_SIZE
);
if
(
guid
==
MF_MT_VIDEO_PRIMARIES
)
return
&
(
out
.
MF_MT_VIDEO_PRIMARIES
);
if
(
guid
==
MF_MT_INTERLACE_MODE
)
return
&
(
out
.
MF_MT_INTERLACE_MODE
);
return
NULL
;
}
HRESULT
LogAttributeValueByIndexNew
(
IMFAttributes
*
pAttr
,
DWORD
index
,
MediaType
&
out
)
CamParametrs
videoDevice__getParametrs
(
IMFMediaSource
*
vd_pSource
)
{
WCHAR
*
pGuidName
=
NULL
;
WCHAR
*
pGuidValName
=
NULL
;
GUID
guid
=
{
0
};
PROPVARIANT
var
;
PropVariantInit
(
&
var
);
HRESULT
hr
=
pAttr
->
GetItemByIndex
(
index
,
&
guid
,
&
var
);
if
(
FAILED
(
hr
))
{
goto
done
;
}
hr
=
GetGUIDNameNew
(
guid
,
&
pGuidName
);
if
(
FAILED
(
hr
))
{
goto
done
;
}
hr
=
SpecialCaseAttributeValueNew
(
guid
,
var
,
out
);
unsigned
int
*
p
;
if
(
FAILED
(
hr
))
{
goto
done
;
}
if
(
hr
==
S_FALSE
)
CamParametrs
out
;
if
(
vd_pSource
)
{
switch
(
var
.
vt
)
Parametr
*
pParametr
=
(
Parametr
*
)(
&
out
);
IAMVideoProcAmp
*
pProcAmp
=
NULL
;
HRESULT
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcAmp
));
if
(
SUCCEEDED
(
hr
))
{
case
VT_UI4
:
p
=
GetParametr
(
guid
,
out
);
if
(
p
)
{
*
p
=
var
.
ulVal
;
}
break
;
case
VT_UI8
:
break
;
case
VT_R8
:
break
;
case
VT_CLSID
:
if
(
guid
==
MF_MT_AM_FORMAT_TYPE
)
{
hr
=
GetGUIDNameNew
(
*
var
.
puuid
,
&
pGuidValName
);
if
(
SUCCEEDED
(
hr
))
{
out
.
MF_MT_AM_FORMAT_TYPE
=
*
var
.
puuid
;
out
.
pMF_MT_AM_FORMAT_TYPEName
=
pGuidValName
;
pGuidValName
=
NULL
;
}
}
if
(
guid
==
MF_MT_MAJOR_TYPE
)
for
(
unsigned
int
i
=
0
;
i
<
10
;
i
++
)
{
hr
=
GetGUIDNameNew
(
*
var
.
puuid
,
&
pGuidValName
);
Parametr
temp
;
hr
=
pProcAmp
->
GetRange
(
VideoProcAmp_Brightness
+
i
,
&
temp
.
Min
,
&
temp
.
Max
,
&
temp
.
Step
,
&
temp
.
Default
,
&
temp
.
Flag
);
if
(
SUCCEEDED
(
hr
))
{
out
.
MF_MT_MAJOR_TYPE
=
*
var
.
puuid
;
out
.
pMF_MT_MAJOR_TYPEName
=
pGuidValName
;
pGuidValName
=
NULL
;
temp
.
CurrentValue
=
temp
.
Default
;
pParametr
[
i
]
=
temp
;
}
}
if
(
guid
==
MF_MT_SUBTYPE
)
pProcAmp
->
Release
();
}
IAMCameraControl
*
pProcControl
=
NULL
;
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcControl
));
if
(
SUCCEEDED
(
hr
))
{
for
(
unsigned
int
i
=
0
;
i
<
7
;
i
++
)
{
hr
=
GetGUIDNameNew
(
*
var
.
puuid
,
&
pGuidValName
);
Parametr
temp
;
hr
=
pProcControl
->
GetRange
(
CameraControl_Pan
+
i
,
&
temp
.
Min
,
&
temp
.
Max
,
&
temp
.
Step
,
&
temp
.
Default
,
&
temp
.
Flag
);
if
(
SUCCEEDED
(
hr
))
{
out
.
MF_MT_SUBTYPE
=
*
var
.
puuid
;
out
.
pMF_MT_SUBTYPEName
=
pGuidValName
;
pGuidValName
=
NULL
;
temp
.
CurrentValue
=
temp
.
Default
;
pParametr
[
10
+
i
]
=
temp
;
}
}
break
;
case
VT_LPWSTR
:
break
;
case
VT_VECTOR
|
VT_UI1
:
break
;
case
VT_UNKNOWN
:
break
;
default:
break
;
pProcControl
->
Release
();
}
}
done:
CoTaskMemFree
(
pGuidName
);
CoTaskMemFree
(
pGuidValName
);
PropVariantClear
(
&
var
);
return
hr
;
return
out
;
}
HRESULT
GetGUIDNameNew
(
const
GUID
&
guid
,
WCHAR
**
ppwsz
)
void
videoDevice__setParametrs
(
IMFMediaSource
*
vd_pSource
,
CamParametrs
parametrs
)
{
HRESULT
hr
=
S_OK
;
WCHAR
*
pName
=
NULL
;
LPCWSTR
pcwsz
=
GetGUIDNameConstNew
(
guid
);
if
(
pcwsz
)
if
(
vd_pSource
)
{
size_t
cchLength
=
0
;
hr
=
StringCchLengthW
(
pcwsz
,
STRSAFE_MAX_CCH
,
&
cchLength
);
if
(
FAILED
(
hr
))
{
goto
done
;
}
pName
=
(
WCHAR
*
)
CoTaskMemAlloc
((
cchLength
+
1
)
*
sizeof
(
WCHAR
));
if
(
pName
==
NULL
)
CamParametrs
vd_PrevParametrs
=
videoDevice__getParametrs
(
vd_pSource
);
Parametr
*
pParametr
=
(
Parametr
*
)(
&
parametrs
);
Parametr
*
pPrevParametr
=
(
Parametr
*
)(
&
vd_PrevParametrs
);
IAMVideoProcAmp
*
pProcAmp
=
NULL
;
HRESULT
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcAmp
));
if
(
SUCCEEDED
(
hr
))
{
hr
=
E_OUTOFMEMORY
;
goto
done
;
for
(
unsigned
int
i
=
0
;
i
<
10
;
i
++
)
{
if
(
pPrevParametr
[
i
].
CurrentValue
!=
pParametr
[
i
].
CurrentValue
||
pPrevParametr
[
i
].
Flag
!=
pParametr
[
i
].
Flag
)
hr
=
pProcAmp
->
Set
(
VideoProcAmp_Brightness
+
i
,
pParametr
[
i
].
CurrentValue
,
pParametr
[
i
].
Flag
);
}
pProcAmp
->
Release
();
}
hr
=
StringCchCopyW
(
pName
,
cchLength
+
1
,
pcwsz
);
if
(
FAILED
(
hr
))
IAMCameraControl
*
pProcControl
=
NULL
;
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcControl
));
if
(
SUCCEEDED
(
hr
))
{
goto
done
;
for
(
unsigned
int
i
=
0
;
i
<
7
;
i
++
)
{
if
(
pPrevParametr
[
10
+
i
].
CurrentValue
!=
pParametr
[
10
+
i
].
CurrentValue
||
pPrevParametr
[
10
+
i
].
Flag
!=
pParametr
[
10
+
i
].
Flag
)
hr
=
pProcControl
->
Set
(
CameraControl_Pan
+
i
,
pParametr
[
10
+
i
].
CurrentValue
,
pParametr
[
10
+
i
].
Flag
);
}
pProcControl
->
Release
();
}
}
else
{
hr
=
StringFromCLSID
(
guid
,
&
pName
);
}
done:
if
(
FAILED
(
hr
))
{
*
ppwsz
=
NULL
;
CoTaskMemFree
(
pName
);
}
else
}
// Class for creating of Media Foundation context
class
Media_Foundation
{
public
:
~
Media_Foundation
(
void
)
{
/*CV_Assert(SUCCEEDED(MFShutdown()));*/
}
static
Media_Foundation
&
getInstance
()
{
*
ppwsz
=
pName
;
static
Media_Foundation
instance
;
return
instance
;
}
return
hr
;
}
private
:
Media_Foundation
(
void
)
{
CV_Assert
(
SUCCEEDED
(
MFStartup
(
MF_VERSION
)));
}
};
void
LogUINT32AsUINT64New
(
const
PROPVARIANT
&
var
,
UINT32
&
uHigh
,
UINT32
&
uLow
)
#ifndef IF_GUID_EQUAL_RETURN
#define IF_GUID_EQUAL_RETURN(val) if(val == guid) return L#val
#endif
LPCWSTR
GetGUIDNameConstNew
(
const
GUID
&
guid
)
{
Unpack2UINT32AsUINT64
(
var
.
uhVal
.
QuadPart
,
&
uHigh
,
&
uLow
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MAJOR_TYPE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_SUBTYPE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_ALL_SAMPLES_INDEPENDENT
);
IF_GUID_EQUAL_RETURN
(
MF_MT_FIXED_SIZE_SAMPLES
);
IF_GUID_EQUAL_RETURN
(
MF_MT_COMPRESSED
);
IF_GUID_EQUAL_RETURN
(
MF_MT_SAMPLE_SIZE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_WRAPPED_TYPE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_NUM_CHANNELS
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_SAMPLES_PER_SECOND
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_AVG_BYTES_PER_SECOND
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_BLOCK_ALIGNMENT
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_BITS_PER_SAMPLE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_VALID_BITS_PER_SAMPLE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_SAMPLES_PER_BLOCK
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_CHANNEL_MASK
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_FOLDDOWN_MATRIX
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_WMADRC_PEAKREF
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_WMADRC_PEAKTARGET
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_WMADRC_AVGREF
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_WMADRC_AVGTARGET
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AUDIO_PREFER_WAVEFORMATEX
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AAC_PAYLOAD_TYPE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION
);
IF_GUID_EQUAL_RETURN
(
MF_MT_FRAME_SIZE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_FRAME_RATE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_FRAME_RATE_RANGE_MAX
);
IF_GUID_EQUAL_RETURN
(
MF_MT_FRAME_RATE_RANGE_MIN
);
IF_GUID_EQUAL_RETURN
(
MF_MT_PIXEL_ASPECT_RATIO
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DRM_FLAGS
);
IF_GUID_EQUAL_RETURN
(
MF_MT_PAD_CONTROL_FLAGS
);
IF_GUID_EQUAL_RETURN
(
MF_MT_SOURCE_CONTENT_HINT
);
IF_GUID_EQUAL_RETURN
(
MF_MT_VIDEO_CHROMA_SITING
);
IF_GUID_EQUAL_RETURN
(
MF_MT_INTERLACE_MODE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_TRANSFER_FUNCTION
);
IF_GUID_EQUAL_RETURN
(
MF_MT_VIDEO_PRIMARIES
);
IF_GUID_EQUAL_RETURN
(
MF_MT_CUSTOM_VIDEO_PRIMARIES
);
IF_GUID_EQUAL_RETURN
(
MF_MT_YUV_MATRIX
);
IF_GUID_EQUAL_RETURN
(
MF_MT_VIDEO_LIGHTING
);
IF_GUID_EQUAL_RETURN
(
MF_MT_VIDEO_NOMINAL_RANGE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_GEOMETRIC_APERTURE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MINIMUM_DISPLAY_APERTURE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_PAN_SCAN_APERTURE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_PAN_SCAN_ENABLED
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AVG_BITRATE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AVG_BIT_ERROR_RATE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MAX_KEYFRAME_SPACING
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DEFAULT_STRIDE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_PALETTE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_USER_DATA
);
IF_GUID_EQUAL_RETURN
(
MF_MT_AM_FORMAT_TYPE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MPEG_START_TIME_CODE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MPEG2_PROFILE
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MPEG2_LEVEL
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MPEG2_FLAGS
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MPEG_SEQUENCE_HEADER
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DV_AAUX_SRC_PACK_0
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DV_AAUX_CTRL_PACK_0
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DV_AAUX_SRC_PACK_1
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DV_AAUX_CTRL_PACK_1
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DV_VAUX_SRC_PACK
);
IF_GUID_EQUAL_RETURN
(
MF_MT_DV_VAUX_CTRL_PACK
);
IF_GUID_EQUAL_RETURN
(
MF_MT_ARBITRARY_HEADER
);
IF_GUID_EQUAL_RETURN
(
MF_MT_ARBITRARY_FORMAT
);
IF_GUID_EQUAL_RETURN
(
MF_MT_IMAGE_LOSS_TOLERANT
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MPEG4_SAMPLE_DESCRIPTION
);
IF_GUID_EQUAL_RETURN
(
MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY
);
IF_GUID_EQUAL_RETURN
(
MF_MT_ORIGINAL_4CC
);
IF_GUID_EQUAL_RETURN
(
MF_MT_ORIGINAL_WAVE_FORMAT_TAG
);
// Media types
IF_GUID_EQUAL_RETURN
(
MFMediaType_Audio
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_Video
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_Protected
);
#ifdef MFMediaType_Perception
IF_GUID_EQUAL_RETURN
(
MFMediaType_Perception
);
#endif
IF_GUID_EQUAL_RETURN
(
MFMediaType_Stream
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_SAMI
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_Script
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_Image
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_HTML
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_Binary
);
IF_GUID_EQUAL_RETURN
(
MFMediaType_FileTransfer
);
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_AI44
);
// FCC('AI44')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_ARGB32
);
// D3DFMT_A8R8G8B8
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_AYUV
);
// FCC('AYUV')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_DV25
);
// FCC('dv25')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_DV50
);
// FCC('dv50')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_DVH1
);
// FCC('dvh1')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_DVC
);
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_DVHD
);
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_DVSD
);
// FCC('dvsd')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_DVSL
);
// FCC('dvsl')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_H264
);
// FCC('H264')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_I420
);
// FCC('I420')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_IYUV
);
// FCC('IYUV')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_M4S2
);
// FCC('M4S2')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MJPG
);
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MP43
);
// FCC('MP43')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MP4S
);
// FCC('MP4S')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MP4V
);
// FCC('MP4V')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MPG1
);
// FCC('MPG1')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MSS1
);
// FCC('MSS1')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MSS2
);
// FCC('MSS2')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_NV11
);
// FCC('NV11')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_NV12
);
// FCC('NV12')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_P010
);
// FCC('P010')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_P016
);
// FCC('P016')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_P210
);
// FCC('P210')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_P216
);
// FCC('P216')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_RGB24
);
// D3DFMT_R8G8B8
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_RGB32
);
// D3DFMT_X8R8G8B8
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_RGB555
);
// D3DFMT_X1R5G5B5
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_RGB565
);
// D3DFMT_R5G6B5
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_RGB8
);
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_UYVY
);
// FCC('UYVY')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_v210
);
// FCC('v210')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_v410
);
// FCC('v410')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_WMV1
);
// FCC('WMV1')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_WMV2
);
// FCC('WMV2')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_WMV3
);
// FCC('WMV3')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_WVC1
);
// FCC('WVC1')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_Y210
);
// FCC('Y210')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_Y216
);
// FCC('Y216')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_Y410
);
// FCC('Y410')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_Y416
);
// FCC('Y416')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_Y41P
);
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_Y41T
);
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_YUY2
);
// FCC('YUY2')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_YV12
);
// FCC('YV12')
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_YVYU
);
#ifdef MFVideoFormat_H263
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_H263
);
#endif
#ifdef MFVideoFormat_H265
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_H265
);
#endif
#ifdef MFVideoFormat_H264_ES
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_H264_ES
);
#endif
#ifdef MFVideoFormat_HEVC
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_HEVC
);
#endif
#ifdef MFVideoFormat_HEVC_ES
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_HEVC_ES
);
#endif
#ifdef MFVideoFormat_MPEG2
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_MPEG2
);
#endif
#ifdef MFVideoFormat_VP80
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_VP80
);
#endif
#ifdef MFVideoFormat_VP90
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_VP90
);
#endif
#ifdef MFVideoFormat_420O
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_420O
);
#endif
#ifdef MFVideoFormat_Y42T
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_Y42T
);
#endif
#ifdef MFVideoFormat_YVU9
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_YVU9
);
#endif
#ifdef MFVideoFormat_v216
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_v216
);
#endif
#ifdef MFVideoFormat_L8
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_L8
);
#endif
#ifdef MFVideoFormat_L16
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_L16
);
#endif
#ifdef MFVideoFormat_D16
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_D16
);
#endif
#ifdef D3DFMT_X8R8G8B8
IF_GUID_EQUAL_RETURN
(
D3DFMT_X8R8G8B8
);
#endif
#ifdef D3DFMT_A8R8G8B8
IF_GUID_EQUAL_RETURN
(
D3DFMT_A8R8G8B8
);
#endif
#ifdef D3DFMT_R8G8B8
IF_GUID_EQUAL_RETURN
(
D3DFMT_R8G8B8
);
#endif
#ifdef D3DFMT_X1R5G5B5
IF_GUID_EQUAL_RETURN
(
D3DFMT_X1R5G5B5
);
#endif
#ifdef D3DFMT_A4R4G4B4
IF_GUID_EQUAL_RETURN
(
D3DFMT_A4R4G4B4
);
#endif
#ifdef D3DFMT_R5G6B5
IF_GUID_EQUAL_RETURN
(
D3DFMT_R5G6B5
);
#endif
#ifdef D3DFMT_P8
IF_GUID_EQUAL_RETURN
(
D3DFMT_P8
);
#endif
#ifdef D3DFMT_A2R10G10B10
IF_GUID_EQUAL_RETURN
(
D3DFMT_A2R10G10B10
);
#endif
#ifdef D3DFMT_A2B10G10R10
IF_GUID_EQUAL_RETURN
(
D3DFMT_A2B10G10R10
);
#endif
#ifdef D3DFMT_L8
IF_GUID_EQUAL_RETURN
(
D3DFMT_L8
);
#endif
#ifdef D3DFMT_L16
IF_GUID_EQUAL_RETURN
(
D3DFMT_L16
);
#endif
#ifdef D3DFMT_D16
IF_GUID_EQUAL_RETURN
(
D3DFMT_D16
);
#endif
#ifdef MFVideoFormat_A2R10G10B10
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_A2R10G10B10
);
#endif
#ifdef MFVideoFormat_A16B16G16R16F
IF_GUID_EQUAL_RETURN
(
MFVideoFormat_A16B16G16R16F
);
#endif
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_PCM
);
// WAVE_FORMAT_PCM
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_Float
);
// WAVE_FORMAT_IEEE_FLOAT
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_DTS
);
// WAVE_FORMAT_DTS
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_Dolby_AC3_SPDIF
);
// WAVE_FORMAT_DOLBY_AC3_SPDIF
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_DRM
);
// WAVE_FORMAT_DRM
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_WMAudioV8
);
// WAVE_FORMAT_WMAUDIO2
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_WMAudioV9
);
// WAVE_FORMAT_WMAUDIO3
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_WMAudio_Lossless
);
// WAVE_FORMAT_WMAUDIO_LOSSLESS
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_WMASPDIF
);
// WAVE_FORMAT_WMASPDIF
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_MSP1
);
// WAVE_FORMAT_WMAVOICE9
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_MP3
);
// WAVE_FORMAT_MPEGLAYER3
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_MPEG
);
// WAVE_FORMAT_MPEG
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_AAC
);
// WAVE_FORMAT_MPEG_HEAAC
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_ADTS
);
// WAVE_FORMAT_MPEG_ADTS_AAC
#ifdef MFAudioFormat_ALAC
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_ALAC
);
#endif
#ifdef MFAudioFormat_AMR_NB
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_AMR_NB
);
#endif
#ifdef MFAudioFormat_AMR_WB
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_AMR_WB
);
#endif
#ifdef MFAudioFormat_AMR_WP
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_AMR_WP
);
#endif
#ifdef MFAudioFormat_Dolby_AC3
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_Dolby_AC3
);
#endif
#ifdef MFAudioFormat_Dolby_DDPlus
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_Dolby_DDPlus
);
#endif
#ifdef MFAudioFormat_FLAC
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_FLAC
);
#endif
#ifdef MFAudioFormat_Opus
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_Opus
);
#endif
#ifdef MEDIASUBTYPE_RAW_AAC1
IF_GUID_EQUAL_RETURN
(
MEDIASUBTYPE_RAW_AAC1
);
#endif
#ifdef MFAudioFormat_Float_SpatialObjects
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_Float_SpatialObjects
);
#endif
#ifdef MFAudioFormat_QCELP
IF_GUID_EQUAL_RETURN
(
MFAudioFormat_QCELP
);
#endif
return
NULL
;
}
float
OffsetToFloatNew
(
const
MFOffset
&
offse
t
)
bool
LogAttributeValueByIndexNew
(
IMFAttributes
*
pAttr
,
DWORD
index
,
MediaType
&
ou
t
)
{
return
offset
.
value
+
(
static_cast
<
float
>
(
offset
.
fract
)
/
65536.0
f
);
PROPVARIANT
var
;
PropVariantInit
(
&
var
);
GUID
guid
=
{
0
};
if
(
SUCCEEDED
(
pAttr
->
GetItemByIndex
(
index
,
&
guid
,
&
var
)))
{
if
(
guid
==
MF_MT_DEFAULT_STRIDE
&&
var
.
vt
==
VT_INT
)
out
.
MF_MT_DEFAULT_STRIDE
=
var
.
intVal
;
else
if
(
guid
==
MF_MT_FRAME_RATE
&&
var
.
vt
==
VT_UI8
)
Unpack2UINT32AsUINT64
(
var
.
uhVal
.
QuadPart
,
&
out
.
MF_MT_FRAME_RATE_NUMERATOR
,
&
out
.
MF_MT_FRAME_RATE_DENOMINATOR
);
else
if
(
guid
==
MF_MT_FRAME_RATE_RANGE_MAX
&&
var
.
vt
==
VT_UI8
)
Unpack2UINT32AsUINT64
(
var
.
uhVal
.
QuadPart
,
&
out
.
MF_MT_FRAME_RATE_RANGE_MAX
,
&
out
.
MF_MT_FRAME_RATE_RANGE_MAX_low
);
else
if
(
guid
==
MF_MT_FRAME_RATE_RANGE_MIN
&&
var
.
vt
==
VT_UI8
)
Unpack2UINT32AsUINT64
(
var
.
uhVal
.
QuadPart
,
&
out
.
MF_MT_FRAME_RATE_RANGE_MIN
,
&
out
.
MF_MT_FRAME_RATE_RANGE_MIN_low
);
else
if
(
guid
==
MF_MT_PIXEL_ASPECT_RATIO
&&
var
.
vt
==
VT_UI8
)
Unpack2UINT32AsUINT64
(
var
.
uhVal
.
QuadPart
,
&
out
.
MF_MT_PIXEL_ASPECT_RATIO
,
&
out
.
MF_MT_PIXEL_ASPECT_RATIO_low
);
else
if
(
guid
==
MF_MT_YUV_MATRIX
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_YUV_MATRIX
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_VIDEO_LIGHTING
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_VIDEO_LIGHTING
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_DEFAULT_STRIDE
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_DEFAULT_STRIDE
=
(
int
)
var
.
ulVal
;
else
if
(
guid
==
MF_MT_VIDEO_CHROMA_SITING
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_VIDEO_CHROMA_SITING
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_VIDEO_NOMINAL_RANGE
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_VIDEO_NOMINAL_RANGE
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_ALL_SAMPLES_INDEPENDENT
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_ALL_SAMPLES_INDEPENDENT
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_FIXED_SIZE_SAMPLES
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_FIXED_SIZE_SAMPLES
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_SAMPLE_SIZE
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_SAMPLE_SIZE
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_VIDEO_PRIMARIES
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_VIDEO_PRIMARIES
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_INTERLACE_MODE
&&
var
.
vt
==
VT_UI4
)
out
.
MF_MT_INTERLACE_MODE
=
var
.
ulVal
;
else
if
(
guid
==
MF_MT_AM_FORMAT_TYPE
&&
var
.
vt
==
VT_CLSID
)
out
.
MF_MT_AM_FORMAT_TYPE
=
*
var
.
puuid
;
else
if
(
guid
==
MF_MT_MAJOR_TYPE
&&
var
.
vt
==
VT_CLSID
)
out
.
pMF_MT_MAJOR_TYPEName
=
GetGUIDNameConstNew
(
out
.
MF_MT_MAJOR_TYPE
=
*
var
.
puuid
);
else
if
(
guid
==
MF_MT_SUBTYPE
&&
var
.
vt
==
VT_CLSID
)
out
.
pMF_MT_SUBTYPEName
=
GetGUIDNameConstNew
(
out
.
MF_MT_SUBTYPE
=
*
var
.
puuid
);
else
if
(
guid
==
MF_MT_FRAME_SIZE
&&
var
.
vt
==
VT_UI8
)
{
Unpack2UINT32AsUINT64
(
var
.
uhVal
.
QuadPart
,
&
out
.
width
,
&
out
.
height
);
out
.
MF_MT_FRAME_SIZE
=
out
.
width
*
out
.
height
;
}
PropVariantClear
(
&
var
);
return
true
;
}
return
false
;
}
HRESULT
LogVideoAreaNew
(
const
PROPVARIANT
&
var
)
MediaType
::
MediaType
(
)
{
if
(
var
.
caub
.
cElems
<
sizeof
(
MFVideoArea
))
{
return
S_OK
;
}
return
S_OK
;
pMF_MT_MAJOR_TYPEName
=
NULL
;
pMF_MT_SUBTYPEName
=
NULL
;
Clear
();
}
HRESULT
SpecialCaseAttributeValueNew
(
GUID
guid
,
const
PROPVARIANT
&
var
,
MediaType
&
out
)
MediaType
::
MediaType
(
IMFMediaType
*
pType
)
{
if
(
guid
==
MF_MT_DEFAULT_STRIDE
)
{
out
.
MF_MT_DEFAULT_STRIDE
=
var
.
intVal
;
}
else
if
(
guid
==
MF_MT_FRAME_SIZE
)
{
UINT32
uHigh
=
0
,
uLow
=
0
;
LogUINT32AsUINT64New
(
var
,
uHigh
,
uLow
);
out
.
width
=
uHigh
;
out
.
height
=
uLow
;
out
.
MF_MT_FRAME_SIZE
=
out
.
width
*
out
.
height
;
}
else
if
(
guid
==
MF_MT_FRAME_RATE
)
{
UINT32
uHigh
=
0
,
uLow
=
0
;
LogUINT32AsUINT64New
(
var
,
uHigh
,
uLow
);
out
.
MF_MT_FRAME_RATE_NUMERATOR
=
uHigh
;
out
.
MF_MT_FRAME_RATE_DENOMINATOR
=
uLow
;
}
else
if
(
guid
==
MF_MT_FRAME_RATE_RANGE_MAX
)
UINT32
count
=
0
;
if
(
SUCCEEDED
(
pType
->
GetCount
(
&
count
))
&&
SUCCEEDED
(
pType
->
LockStore
()))
{
UINT32
uHigh
=
0
,
uLow
=
0
;
LogUINT32AsUINT64New
(
var
,
uHigh
,
uLow
);
out
.
MF_MT_FRAME_RATE_RANGE_MAX
=
uHigh
;
out
.
MF_MT_FRAME_RATE_RANGE_MAX_low
=
uLow
;
for
(
UINT32
i
=
0
;
i
<
count
;
i
++
)
if
(
!
LogAttributeValueByIndexNew
(
pType
,
i
,
*
this
))
break
;
pType
->
UnlockStore
()
;
}
else
if
(
guid
==
MF_MT_FRAME_RATE_RANGE_MIN
)
{
UINT32
uHigh
=
0
,
uLow
=
0
;
LogUINT32AsUINT64New
(
var
,
uHigh
,
uLow
);
out
.
MF_MT_FRAME_RATE_RANGE_MIN
=
uHigh
;
out
.
MF_MT_FRAME_RATE_RANGE_MIN_low
=
uLow
;
}
else
if
(
guid
==
MF_MT_PIXEL_ASPECT_RATIO
)
{
UINT32
uHigh
=
0
,
uLow
=
0
;
LogUINT32AsUINT64New
(
var
,
uHigh
,
uLow
);
out
.
MF_MT_PIXEL_ASPECT_RATIO
=
uHigh
;
out
.
MF_MT_PIXEL_ASPECT_RATIO_low
=
uLow
;
}
else
{
return
S_FALSE
;
}
return
S_OK
;
}
#ifndef IF_EQUAL_RETURN
#define IF_EQUAL_RETURN(param, val) if(val == param) return L#val
#endif
LPCWSTR
GetGUIDNameConstNew
(
const
GUID
&
guid
)
{
IF_EQUAL_RETURN
(
guid
,
MF_MT_MAJOR_TYPE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MAJOR_TYPE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_SUBTYPE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_ALL_SAMPLES_INDEPENDENT
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_FIXED_SIZE_SAMPLES
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_COMPRESSED
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_SAMPLE_SIZE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_WRAPPED_TYPE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_NUM_CHANNELS
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_SAMPLES_PER_SECOND
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_AVG_BYTES_PER_SECOND
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_BLOCK_ALIGNMENT
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_BITS_PER_SAMPLE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_VALID_BITS_PER_SAMPLE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_SAMPLES_PER_BLOCK
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_CHANNEL_MASK
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_FOLDDOWN_MATRIX
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_WMADRC_PEAKREF
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_WMADRC_PEAKTARGET
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_WMADRC_AVGREF
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_WMADRC_AVGTARGET
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AUDIO_PREFER_WAVEFORMATEX
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AAC_PAYLOAD_TYPE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_FRAME_SIZE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_FRAME_RATE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_FRAME_RATE_RANGE_MAX
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_FRAME_RATE_RANGE_MIN
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_PIXEL_ASPECT_RATIO
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DRM_FLAGS
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_PAD_CONTROL_FLAGS
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_SOURCE_CONTENT_HINT
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_VIDEO_CHROMA_SITING
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_INTERLACE_MODE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_TRANSFER_FUNCTION
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_VIDEO_PRIMARIES
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_CUSTOM_VIDEO_PRIMARIES
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_YUV_MATRIX
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_VIDEO_LIGHTING
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_VIDEO_NOMINAL_RANGE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_GEOMETRIC_APERTURE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MINIMUM_DISPLAY_APERTURE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_PAN_SCAN_APERTURE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_PAN_SCAN_ENABLED
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AVG_BITRATE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AVG_BIT_ERROR_RATE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MAX_KEYFRAME_SPACING
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DEFAULT_STRIDE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_PALETTE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_USER_DATA
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_AM_FORMAT_TYPE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MPEG_START_TIME_CODE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MPEG2_PROFILE
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MPEG2_LEVEL
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MPEG2_FLAGS
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MPEG_SEQUENCE_HEADER
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DV_AAUX_SRC_PACK_0
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DV_AAUX_CTRL_PACK_0
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DV_AAUX_SRC_PACK_1
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DV_AAUX_CTRL_PACK_1
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DV_VAUX_SRC_PACK
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_DV_VAUX_CTRL_PACK
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_ARBITRARY_HEADER
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_ARBITRARY_FORMAT
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_IMAGE_LOSS_TOLERANT
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MPEG4_SAMPLE_DESCRIPTION
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_ORIGINAL_4CC
);
IF_EQUAL_RETURN
(
guid
,
MF_MT_ORIGINAL_WAVE_FORMAT_TAG
);
// Media types
IF_EQUAL_RETURN
(
guid
,
MFMediaType_Audio
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_Video
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_Protected
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_SAMI
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_Script
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_Image
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_HTML
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_Binary
);
IF_EQUAL_RETURN
(
guid
,
MFMediaType_FileTransfer
);
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_AI44
);
// FCC('AI44')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_ARGB32
);
// D3DFMT_A8R8G8B8
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_AYUV
);
// FCC('AYUV')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_DV25
);
// FCC('dv25')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_DV50
);
// FCC('dv50')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_DVH1
);
// FCC('dvh1')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_DVSD
);
// FCC('dvsd')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_DVSL
);
// FCC('dvsl')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_H264
);
// FCC('H264')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_I420
);
// FCC('I420')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_IYUV
);
// FCC('IYUV')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_M4S2
);
// FCC('M4S2')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_MJPG
);
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_MP43
);
// FCC('MP43')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_MP4S
);
// FCC('MP4S')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_MP4V
);
// FCC('MP4V')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_MPG1
);
// FCC('MPG1')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_MSS1
);
// FCC('MSS1')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_MSS2
);
// FCC('MSS2')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_NV11
);
// FCC('NV11')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_NV12
);
// FCC('NV12')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_P010
);
// FCC('P010')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_P016
);
// FCC('P016')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_P210
);
// FCC('P210')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_P216
);
// FCC('P216')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_RGB24
);
// D3DFMT_R8G8B8
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_RGB32
);
// D3DFMT_X8R8G8B8
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_RGB555
);
// D3DFMT_X1R5G5B5
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_RGB565
);
// D3DFMT_R5G6B5
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_RGB8
);
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_UYVY
);
// FCC('UYVY')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_v210
);
// FCC('v210')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_v410
);
// FCC('v410')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_WMV1
);
// FCC('WMV1')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_WMV2
);
// FCC('WMV2')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_WMV3
);
// FCC('WMV3')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_WVC1
);
// FCC('WVC1')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_Y210
);
// FCC('Y210')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_Y216
);
// FCC('Y216')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_Y410
);
// FCC('Y410')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_Y416
);
// FCC('Y416')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_Y41P
);
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_Y41T
);
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_YUY2
);
// FCC('YUY2')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_YV12
);
// FCC('YV12')
IF_EQUAL_RETURN
(
guid
,
MFVideoFormat_YVYU
);
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_PCM
);
// WAVE_FORMAT_PCM
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_Float
);
// WAVE_FORMAT_IEEE_FLOAT
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_DTS
);
// WAVE_FORMAT_DTS
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_Dolby_AC3_SPDIF
);
// WAVE_FORMAT_DOLBY_AC3_SPDIF
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_DRM
);
// WAVE_FORMAT_DRM
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_WMAudioV8
);
// WAVE_FORMAT_WMAUDIO2
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_WMAudioV9
);
// WAVE_FORMAT_WMAUDIO3
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_WMAudio_Lossless
);
// WAVE_FORMAT_WMAUDIO_LOSSLESS
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_WMASPDIF
);
// WAVE_FORMAT_WMASPDIF
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_MSP1
);
// WAVE_FORMAT_WMAVOICE9
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_MP3
);
// WAVE_FORMAT_MPEGLAYER3
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_MPEG
);
// WAVE_FORMAT_MPEG
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_AAC
);
// WAVE_FORMAT_MPEG_HEAAC
IF_EQUAL_RETURN
(
guid
,
MFAudioFormat_ADTS
);
// WAVE_FORMAT_MPEG_ADTS_AAC
return
NULL
;
}
FormatReader
::
FormatReader
(
void
)
{
}
MediaType
FormatReader
::
Read
(
IMFMediaType
*
pType
)
{
UINT32
count
=
0
;
MediaType
out
;
HRESULT
hr
=
pType
->
LockStore
();
if
(
FAILED
(
hr
))
{
return
out
;
}
hr
=
pType
->
GetCount
(
&
count
);
if
(
FAILED
(
hr
))
{
return
out
;
}
for
(
UINT32
i
=
0
;
i
<
count
;
i
++
)
{
hr
=
LogAttributeValueByIndexNew
(
pType
,
i
,
out
);
if
(
FAILED
(
hr
))
{
break
;
}
}
hr
=
pType
->
UnlockStore
();
if
(
FAILED
(
hr
))
{
return
out
;
}
return
out
;
}
FormatReader
::~
FormatReader
(
void
)
{
}
#define CHECK_HR(x) if (FAILED(x)) { goto done; }
ImageGrabberCallback
::
ImageGrabberCallback
(
bool
synchronous
)
:
m_cRef
(
1
),
ig_RIE
(
true
),
ig_Close
(
false
),
ig_Synchronous
(
synchronous
),
ig_hFrameReady
(
synchronous
?
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
)
:
0
),
ig_hFrameGrabbed
(
synchronous
?
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
)
:
0
),
ig_hFinish
(
CreateEvent
(
NULL
,
TRUE
,
FALSE
,
NULL
))
{}
ImageGrabber
::
ImageGrabber
(
unsigned
int
deviceID
,
bool
synchronous
)
:
ImageGrabberCallback
(
synchronous
),
ig_DeviceID
(
deviceID
),
ig_pSource
(
NULL
),
ig_pSession
(
NULL
),
ig_pTopology
(
NULL
)
{}
ImageGrabber
::~
ImageGrabber
(
void
)
{
if
(
ig_pSession
)
{
ig_pSession
->
Shutdown
();
}
CloseHandle
(
ig_hFinish
);
if
(
ig_Synchronous
)
{
CloseHandle
(
ig_hFrameReady
);
CloseHandle
(
ig_hFrameGrabbed
);
}
SafeRelease
(
&
ig_pSession
);
SafeRelease
(
&
ig_pTopology
);
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: Destroying instance of the ImageGrabber class
\n
"
,
ig_DeviceID
);
}
HRESULT
ImageGrabber
::
initImageGrabber
(
IMFMediaSource
*
pSource
)
{
// Clean up.
if
(
ig_pSession
)
{
ig_pSession
->
Shutdown
();
}
SafeRelease
(
&
ig_pSession
);
SafeRelease
(
&
ig_pTopology
);
HRESULT
hr
;
ig_pSource
=
pSource
;
// Configure the media type that the Sample Grabber will receive.
// Setting the major and subtype is usually enough for the topology loader
// to resolve the topology.
_ComPtr
<
IMFMediaType
>
pType
=
NULL
;
_ComPtr
<
IMFActivate
>
pSinkActivate
=
NULL
;
CHECK_HR
(
hr
=
MFCreateMediaType
(
pType
.
GetAddressOf
()));
CHECK_HR
(
hr
=
pType
->
SetGUID
(
MF_MT_MAJOR_TYPE
,
MFMediaType_Video
));
CHECK_HR
(
hr
=
pType
->
SetGUID
(
MF_MT_SUBTYPE
,
MFVideoFormat_RGB24
));
// Create the sample grabber sink.
CHECK_HR
(
hr
=
MFCreateSampleGrabberSinkActivate
(
pType
.
Get
(),
this
,
pSinkActivate
.
GetAddressOf
()));
// To run as fast as possible, set this attribute (requires Windows 7):
CHECK_HR
(
hr
=
pSinkActivate
->
SetUINT32
(
MF_SAMPLEGRABBERSINK_IGNORE_CLOCK
,
TRUE
));
// Create the Media Session.
CHECK_HR
(
hr
=
MFCreateMediaSession
(
NULL
,
&
ig_pSession
));
// Create the topology.
CHECK_HR
(
hr
=
CreateTopology
(
pSource
,
pSinkActivate
.
Get
(),
&
ig_pTopology
));
CHECK_HR
(
hr
=
RawImage
::
CreateInstance
(
&
ig_RIFirst
,
captureFormat
.
MF_MT_FRAME_SIZE
*
3
));
// Expect that output image will be RGB24 thus occupy 3 byte per point
CHECK_HR
(
hr
=
RawImage
::
CreateInstance
(
&
ig_RISecond
,
captureFormat
.
MF_MT_FRAME_SIZE
*
3
));
ig_RIOut
=
ig_RISecond
;
done
:
// Clean up.
if
(
FAILED
(
hr
))
{
if
(
ig_pSession
)
{
ig_pSession
->
Shutdown
();
}
SafeRelease
(
&
ig_pSession
);
SafeRelease
(
&
ig_pTopology
);
}
return
hr
;
}
void
ImageGrabber
::
stopGrabbing
()
{
if
(
ig_pSession
)
ig_pSession
->
Stop
();
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: Stopping of of grabbing of images
\n
"
,
ig_DeviceID
);
}
HRESULT
ImageGrabber
::
startGrabbing
(
void
)
{
PROPVARIANT
var
;
PropVariantInit
(
&
var
);
HRESULT
hr
=
ig_pSession
->
SetTopology
(
0
,
ig_pTopology
);
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: Start Grabbing of the images
\n
"
,
ig_DeviceID
);
hr
=
ig_pSession
->
Start
(
&
GUID_NULL
,
&
var
);
for
(;;)
{
_ComPtr
<
IMFMediaEvent
>
pEvent
=
NULL
;
HRESULT
hrStatus
=
S_OK
;
MediaEventType
met
;
if
(
!
ig_pSession
)
break
;
hr
=
ig_pSession
->
GetEvent
(
0
,
&
pEvent
);
if
(
!
SUCCEEDED
(
hr
))
{
hr
=
S_OK
;
goto
done
;
}
hr
=
pEvent
->
GetStatus
(
&
hrStatus
);
if
(
!
SUCCEEDED
(
hr
))
{
hr
=
S_OK
;
goto
done
;
}
hr
=
pEvent
->
GetType
(
&
met
);
if
(
!
SUCCEEDED
(
hr
))
{
hr
=
S_OK
;
goto
done
;
}
if
(
!
SUCCEEDED
(
hrStatus
))
{
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: Event Status Error: %u
\n
"
,
ig_DeviceID
,
hrStatus
);
goto
done
;
}
if
(
met
==
MESessionEnded
)
{
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: MESessionEnded
\n
"
,
ig_DeviceID
);
ig_pSession
->
Stop
();
break
;
}
if
(
met
==
MESessionStopped
)
{
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: MESessionStopped
\n
"
,
ig_DeviceID
);
break
;
}
#if (WINVER >= 0x0602) // Available since Win 8
if
(
met
==
MEVideoCaptureDeviceRemoved
)
{
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved
\n
"
,
ig_DeviceID
);
break
;
}
#endif
if
((
met
==
MEError
)
||
(
met
==
MENonFatalError
))
{
pEvent
->
GetStatus
(
&
hrStatus
);
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: MEError | MENonFatalError: %u
\n
"
,
ig_DeviceID
,
hrStatus
);
break
;
}
}
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: Finish startGrabbing
\n
"
,
ig_DeviceID
);
done
:
SetEvent
(
ig_hFinish
);
return
hr
;
}
void
ImageGrabberCallback
::
pauseGrabbing
()
{
}
void
ImageGrabberCallback
::
resumeGrabbing
()
{
}
HRESULT
ImageGrabber
::
CreateTopology
(
IMFMediaSource
*
pSource
,
IMFActivate
*
pSinkActivate
,
IMFTopology
**
ppTopo
)
{
HRESULT
hr
=
S_OK
;
{
// "done:" scope
_ComPtr
<
IMFPresentationDescriptor
>
pPD
=
NULL
;
hr
=
!
pSource
?
E_POINTER
:
S_OK
;
CHECK_HR
(
hr
);
CHECK_HR
(
hr
=
pSource
->
CreatePresentationDescriptor
(
pPD
.
GetAddressOf
()));
DWORD
cStreams
=
0
;
CHECK_HR
(
hr
=
pPD
->
GetStreamDescriptorCount
(
&
cStreams
));
DWORD
vStream
=
cStreams
;
BOOL
vStreamSelected
=
FALSE
;
for
(
DWORD
i
=
0
;
i
<
cStreams
;
i
++
)
{
BOOL
fSelected
=
FALSE
;
_ComPtr
<
IMFStreamDescriptor
>
pSD
=
NULL
;
CHECK_HR
(
hr
=
pPD
->
GetStreamDescriptorByIndex
(
i
,
&
fSelected
,
pSD
.
GetAddressOf
()));
_ComPtr
<
IMFMediaTypeHandler
>
pHandler
=
NULL
;
CHECK_HR
(
hr
=
pSD
->
GetMediaTypeHandler
(
pHandler
.
GetAddressOf
()));
GUID
majorType
;
CHECK_HR
(
hr
=
pHandler
->
GetMajorType
(
&
majorType
));
if
(
majorType
==
MFMediaType_Video
&&
!
vStreamSelected
)
{
if
(
fSelected
)
{
vStream
=
i
;
vStreamSelected
=
TRUE
;
}
else
vStream
=
i
<
vStream
?
i
:
vStream
;
}
else
{
CHECK_HR
(
hr
=
pPD
->
DeselectStream
(
i
));
}
}
if
(
vStream
<
cStreams
)
{
if
(
!
vStreamSelected
)
CHECK_HR
(
hr
=
pPD
->
SelectStream
(
vStream
));
BOOL
fSelected
;
_ComPtr
<
IMFStreamDescriptor
>
pSD
=
NULL
;
CHECK_HR
(
hr
=
pPD
->
GetStreamDescriptorByIndex
(
vStream
,
&
fSelected
,
pSD
.
GetAddressOf
()));
_ComPtr
<
IMFMediaTypeHandler
>
pHandler
=
NULL
;
CHECK_HR
(
hr
=
pSD
->
GetMediaTypeHandler
(
pHandler
.
GetAddressOf
()));
DWORD
cTypes
=
0
;
CHECK_HR
(
hr
=
pHandler
->
GetMediaTypeCount
(
&
cTypes
));
DWORD
j
=
0
;
for
(;
j
<
cTypes
;
j
++
)
// Iterate throug available video subtypes to find supported and fill MediaType structure
{
_ComPtr
<
IMFMediaType
>
pType
=
NULL
;
CHECK_HR
(
hr
=
pHandler
->
GetMediaTypeByIndex
(
j
,
pType
.
GetAddressOf
()));
MediaType
MT
=
FormatReader
::
Read
(
pType
.
Get
());
if
(
MT
.
MF_MT_MAJOR_TYPE
==
MFMediaType_Video
/*&& MT.MF_MT_SUBTYPE == MFVideoFormat_RGB24*/
)
{
captureFormat
=
MT
;
break
;
}
}
if
(
j
<
cTypes
)
// If there is supported video subtype create topology
{
IMFTopology
*
pTopology
=
NULL
;
_ComPtr
<
IMFTopologyNode
>
pNode1
=
NULL
;
_ComPtr
<
IMFTopologyNode
>
pNode2
=
NULL
;
_ComPtr
<
IMFTopologyNode
>
pNode1c1
=
NULL
;
_ComPtr
<
IMFTopologyNode
>
pNode1c2
=
NULL
;
CHECK_HR
(
hr
=
MFCreateTopology
(
&
pTopology
));
CHECK_HR
(
hr
=
AddSourceNode
(
pTopology
,
pSource
,
pPD
.
Get
(),
pSD
.
Get
(),
pNode1
.
GetAddressOf
()));
CHECK_HR
(
hr
=
AddOutputNode
(
pTopology
,
pSinkActivate
,
0
,
pNode2
.
GetAddressOf
()));
CHECK_HR
(
hr
=
pNode1
->
ConnectOutput
(
0
,
pNode2
.
Get
(),
0
));
*
ppTopo
=
pTopology
;
(
*
ppTopo
)
->
AddRef
();
}
else
hr
=
E_INVALIDARG
;
}
else
hr
=
E_INVALIDARG
;
}
// "done:" scope
done
:
return
hr
;
}
HRESULT
ImageGrabber
::
AddSourceNode
(
IMFTopology
*
pTopology
,
// Topology.
IMFMediaSource
*
pSource
,
// Media source.
IMFPresentationDescriptor
*
pPD
,
// Presentation descriptor.
IMFStreamDescriptor
*
pSD
,
// Stream descriptor.
IMFTopologyNode
**
ppNode
)
// Receives the node pointer.
{
_ComPtr
<
IMFTopologyNode
>
pNode
=
NULL
;
HRESULT
hr
=
S_OK
;
CHECK_HR
(
hr
=
MFCreateTopologyNode
(
MF_TOPOLOGY_SOURCESTREAM_NODE
,
pNode
.
GetAddressOf
()));
CHECK_HR
(
hr
=
pNode
->
SetUnknown
(
MF_TOPONODE_SOURCE
,
pSource
));
CHECK_HR
(
hr
=
pNode
->
SetUnknown
(
MF_TOPONODE_PRESENTATION_DESCRIPTOR
,
pPD
));
CHECK_HR
(
hr
=
pNode
->
SetUnknown
(
MF_TOPONODE_STREAM_DESCRIPTOR
,
pSD
));
CHECK_HR
(
hr
=
pTopology
->
AddNode
(
pNode
.
Get
()));
// Return the pointer to the caller.
*
ppNode
=
pNode
.
Get
();
(
*
ppNode
)
->
AddRef
();
done
:
return
hr
;
}
HRESULT
ImageGrabber
::
AddOutputNode
(
IMFTopology
*
pTopology
,
// Topology.
IMFActivate
*
pActivate
,
// Media sink activation object.
DWORD
dwId
,
// Identifier of the stream sink.
IMFTopologyNode
**
ppNode
)
// Receives the node pointer.
{
_ComPtr
<
IMFTopologyNode
>
pNode
=
NULL
;
HRESULT
hr
=
S_OK
;
CHECK_HR
(
hr
=
MFCreateTopologyNode
(
MF_TOPOLOGY_OUTPUT_NODE
,
pNode
.
GetAddressOf
()));
CHECK_HR
(
hr
=
pNode
->
SetObject
(
pActivate
));
CHECK_HR
(
hr
=
pNode
->
SetUINT32
(
MF_TOPONODE_STREAMID
,
dwId
));
CHECK_HR
(
hr
=
pNode
->
SetUINT32
(
MF_TOPONODE_NOSHUTDOWN_ON_REMOVE
,
FALSE
));
CHECK_HR
(
hr
=
pTopology
->
AddNode
(
pNode
.
Get
()));
// Return the pointer to the caller.
*
ppNode
=
pNode
.
Get
();
(
*
ppNode
)
->
AddRef
();
done
:
return
hr
;
}
HRESULT
ImageGrabber
::
CreateInstance
(
ImageGrabber
**
ppIG
,
unsigned
int
deviceID
,
bool
synchronious
)
{
*
ppIG
=
new
(
std
::
nothrow
)
ImageGrabber
(
deviceID
,
synchronious
);
if
(
ppIG
==
NULL
)
{
return
E_OUTOFMEMORY
;
}
DebugPrintOut
(
L"IMAGEGRABBER VIDEODEVICE %i: Creating instance of ImageGrabber
\n
"
,
deviceID
);
return
S_OK
;
}
STDMETHODIMP
ImageGrabber
::
QueryInterface
(
REFIID
riid
,
void
**
ppv
)
{
HRESULT
hr
=
E_NOINTERFACE
;
*
ppv
=
NULL
;
if
(
riid
==
IID_IUnknown
||
riid
==
IID_IMFSampleGrabberSinkCallback
)
{
*
ppv
=
static_cast
<
IMFSampleGrabberSinkCallback
*>
(
this
);
hr
=
S_OK
;
}
if
(
riid
==
IID_IMFClockStateSink
)
{
*
ppv
=
static_cast
<
IMFClockStateSink
*>
(
this
);
hr
=
S_OK
;
}
if
(
SUCCEEDED
(
hr
))
{
reinterpret_cast
<
IUnknown
*>
(
*
ppv
)
->
AddRef
();
}
return
hr
;
}
STDMETHODIMP_
(
ULONG
)
ImageGrabber
::
AddRef
()
{
return
InterlockedIncrement
(
&
m_cRef
);
}
STDMETHODIMP_
(
ULONG
)
ImageGrabber
::
Release
()
{
ULONG
cRef
=
InterlockedDecrement
(
&
m_cRef
);
if
(
cRef
==
0
)
{
delete
this
;
}
return
cRef
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnClockStart
(
MFTIME
hnsSystemTime
,
LONGLONG
llClockStartOffset
)
{
(
void
)
hnsSystemTime
;
(
void
)
llClockStartOffset
;
return
S_OK
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnClockStop
(
MFTIME
hnsSystemTime
)
{
(
void
)
hnsSystemTime
;
return
S_OK
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnClockPause
(
MFTIME
hnsSystemTime
)
{
(
void
)
hnsSystemTime
;
return
S_OK
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnClockRestart
(
MFTIME
hnsSystemTime
)
{
(
void
)
hnsSystemTime
;
return
S_OK
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnClockSetRate
(
MFTIME
hnsSystemTime
,
float
flRate
)
{
(
void
)
flRate
;
(
void
)
hnsSystemTime
;
return
S_OK
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnSetPresentationClock
(
IMFPresentationClock
*
pClock
)
{
(
void
)
pClock
;
return
S_OK
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnProcessSample
(
REFGUID
guidMajorMediaType
,
DWORD
dwSampleFlags
,
LONGLONG
llSampleTime
,
LONGLONG
llSampleDuration
,
const
BYTE
*
pSampleBuffer
,
DWORD
dwSampleSize
)
{
(
void
)
guidMajorMediaType
;
(
void
)
llSampleTime
;
(
void
)
dwSampleFlags
;
(
void
)
llSampleDuration
;
(
void
)
dwSampleSize
;
HANDLE
tmp
[]
=
{
ig_hFinish
,
ig_hFrameGrabbed
,
NULL
};
DWORD
status
=
WaitForMultipleObjects
(
2
,
tmp
,
FALSE
,
INFINITE
);
if
(
status
==
WAIT_OBJECT_0
)
{
DebugPrintOut
(
L"OnProcessFrame called after ig_hFinish event
\n
"
);
return
S_OK
;
}
if
(
ig_RIE
)
{
ig_RIFirst
->
fastCopy
(
pSampleBuffer
);
ig_RIOut
=
ig_RIFirst
;
}
else
{
ig_RISecond
->
fastCopy
(
pSampleBuffer
);
ig_RIOut
=
ig_RISecond
;
}
if
(
ig_Synchronous
)
{
SetEvent
(
ig_hFrameReady
);
}
else
{
ig_RIE
=
!
ig_RIE
;
}
return
S_OK
;
}
STDMETHODIMP
ImageGrabberCallback
::
OnShutdown
()
{
SetEvent
(
ig_hFinish
);
return
S_OK
;
}
RawImage
*
ImageGrabberCallback
::
getRawImage
()
{
return
ig_RIOut
;
}
DWORD
WINAPI
MainThreadFunction
(
LPVOID
lpParam
)
{
ImageGrabberThread
*
pIGT
=
(
ImageGrabberThread
*
)
lpParam
;
pIGT
->
run
();
return
0
;
}
HRESULT
ImageGrabberThread
::
CreateInstance
(
ImageGrabberThread
**
ppIGT
,
IMFMediaSource
*
pSource
,
unsigned
int
deviceID
,
bool
synchronious
)
{
*
ppIGT
=
new
(
std
::
nothrow
)
ImageGrabberThread
(
pSource
,
deviceID
,
synchronious
);
if
(
ppIGT
==
NULL
)
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Memory cannot be allocated
\n
"
,
deviceID
);
return
E_OUTOFMEMORY
;
}
else
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Creating of the instance of ImageGrabberThread
\n
"
,
deviceID
);
return
S_OK
;
}
ImageGrabberThread
::
ImageGrabberThread
(
IMFMediaSource
*
pSource
,
unsigned
int
deviceID
,
bool
synchronious
)
:
igt_func
(
NULL
),
igt_Handle
(
NULL
),
igt_stop
(
false
)
{
HRESULT
hr
=
ImageGrabber
::
CreateInstance
(
&
igt_pImageGrabber
,
deviceID
,
synchronious
);
igt_DeviceID
=
deviceID
;
if
(
SUCCEEDED
(
hr
))
{
hr
=
igt_pImageGrabber
->
initImageGrabber
(
pSource
);
if
(
!
SUCCEEDED
(
hr
))
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with initialization of the instance of the ImageGrabber class
\n
"
,
deviceID
);
}
else
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Initialization of instance of the ImageGrabber class
\n
"
,
deviceID
);
}
}
else
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with creation of the instance of the ImageGrabber class
\n
"
,
deviceID
);
}
}
void
ImageGrabberThread
::
setEmergencyStopEvent
(
void
*
userData
,
void
(
*
func
)(
int
,
void
*
))
{
if
(
func
)
{
igt_func
=
func
;
igt_userData
=
userData
;
}
}
ImageGrabberThread
::~
ImageGrabberThread
(
void
)
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Destroying ImageGrabberThread
\n
"
,
igt_DeviceID
);
if
(
igt_Handle
)
WaitForSingleObject
(
igt_Handle
,
INFINITE
);
delete
igt_pImageGrabber
;
}
void
ImageGrabberThread
::
stop
()
{
igt_stop
=
true
;
if
(
igt_pImageGrabber
)
{
igt_pImageGrabber
->
stopGrabbing
();
}
}
void
ImageGrabberThread
::
start
()
{
igt_Handle
=
CreateThread
(
NULL
,
// default security attributes
0
,
// use default stack size
MainThreadFunction
,
// thread function name
this
,
// argument to thread function
0
,
// use default creation flags
&
igt_ThreadIdArray
);
// returns the thread identifier
}
void
ImageGrabberThread
::
run
()
{
if
(
igt_pImageGrabber
)
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Thread for grabbing images is started
\n
"
,
igt_DeviceID
);
HRESULT
hr
=
igt_pImageGrabber
->
startGrabbing
();
if
(
!
SUCCEEDED
(
hr
))
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with starting the process of grabbing
\n
"
,
igt_DeviceID
);
}
}
else
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i The thread is finished without execution of grabbing
\n
"
,
igt_DeviceID
);
}
if
(
!
igt_stop
)
{
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Emergency Stop thread
\n
"
,
igt_DeviceID
);
if
(
igt_func
)
{
igt_func
(
igt_DeviceID
,
igt_userData
);
}
}
else
DebugPrintOut
(
L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Finish thread
\n
"
,
igt_DeviceID
);
}
ImageGrabber
*
ImageGrabberThread
::
getImageGrabber
()
{
return
igt_pImageGrabber
;
}
RawImage
::
RawImage
(
unsigned
int
size
)
:
ri_new
(
false
),
ri_pixels
(
NULL
)
{
ri_size
=
size
;
ri_pixels
=
new
unsigned
char
[
size
];
memset
((
void
*
)
ri_pixels
,
0
,
ri_size
);
}
bool
RawImage
::
isNew
()
{
return
ri_new
;
}
unsigned
int
RawImage
::
getSize
()
{
return
ri_size
;
}
RawImage
::~
RawImage
(
void
)
{
delete
[]
ri_pixels
;
ri_pixels
=
NULL
;
}
long
RawImage
::
CreateInstance
(
RawImage
**
ppRImage
,
unsigned
int
size
)
{
*
ppRImage
=
new
(
std
::
nothrow
)
RawImage
(
size
);
if
(
ppRImage
==
NULL
)
{
return
E_OUTOFMEMORY
;
}
return
S_OK
;
}
void
RawImage
::
setCopy
(
const
BYTE
*
pSampleBuffer
)
{
memcpy
(
ri_pixels
,
pSampleBuffer
,
ri_size
);
ri_new
=
true
;
}
void
RawImage
::
fastCopy
(
const
BYTE
*
pSampleBuffer
)
{
memcpy
(
ri_pixels
,
pSampleBuffer
,
ri_size
);
ri_new
=
true
;
}
unsigned
char
*
RawImage
::
getpPixels
()
{
ri_new
=
false
;
return
ri_pixels
;
}
videoDevice
::
videoDevice
(
void
)
:
vd_IsSetuped
(
false
),
vd_LockOut
(
OpenLock
),
vd_pFriendlyName
(
NULL
),
vd_Width
(
0
),
vd_Height
(
0
),
vd_FrameRate
(
0
),
vd_pSource
(
NULL
),
vd_pImGrTh
(
NULL
),
vd_func
(
NULL
),
vd_userData
(
NULL
)
{
}
void
videoDevice
::
setParametrs
(
CamParametrs
parametrs
)
{
if
(
vd_IsSetuped
)
{
if
(
vd_pSource
)
{
CamParametrs
vd_PrevParametrs
=
getParametrs
();
Parametr
*
pParametr
=
(
Parametr
*
)(
&
parametrs
);
Parametr
*
pPrevParametr
=
(
Parametr
*
)(
&
vd_PrevParametrs
);
IAMVideoProcAmp
*
pProcAmp
=
NULL
;
HRESULT
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcAmp
));
if
(
SUCCEEDED
(
hr
))
{
for
(
unsigned
int
i
=
0
;
i
<
10
;
i
++
)
{
if
(
pPrevParametr
[
i
].
CurrentValue
!=
pParametr
[
i
].
CurrentValue
||
pPrevParametr
[
i
].
Flag
!=
pParametr
[
i
].
Flag
)
hr
=
pProcAmp
->
Set
(
VideoProcAmp_Brightness
+
i
,
pParametr
[
i
].
CurrentValue
,
pParametr
[
i
].
Flag
);
}
pProcAmp
->
Release
();
}
IAMCameraControl
*
pProcControl
=
NULL
;
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcControl
));
if
(
SUCCEEDED
(
hr
))
{
for
(
unsigned
int
i
=
0
;
i
<
7
;
i
++
)
{
if
(
pPrevParametr
[
10
+
i
].
CurrentValue
!=
pParametr
[
10
+
i
].
CurrentValue
||
pPrevParametr
[
10
+
i
].
Flag
!=
pParametr
[
10
+
i
].
Flag
)
hr
=
pProcControl
->
Set
(
CameraControl_Pan
+
i
,
pParametr
[
10
+
i
].
CurrentValue
,
pParametr
[
10
+
i
].
Flag
);
}
pProcControl
->
Release
();
}
vd_PrevParametrs
=
parametrs
;
}
}
}
CamParametrs
videoDevice
::
getParametrs
()
{
CamParametrs
out
;
if
(
vd_IsSetuped
)
{
if
(
vd_pSource
)
{
Parametr
*
pParametr
=
(
Parametr
*
)(
&
out
);
IAMVideoProcAmp
*
pProcAmp
=
NULL
;
HRESULT
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcAmp
));
if
(
SUCCEEDED
(
hr
))
{
for
(
unsigned
int
i
=
0
;
i
<
10
;
i
++
)
{
Parametr
temp
;
hr
=
pProcAmp
->
GetRange
(
VideoProcAmp_Brightness
+
i
,
&
temp
.
Min
,
&
temp
.
Max
,
&
temp
.
Step
,
&
temp
.
Default
,
&
temp
.
Flag
);
if
(
SUCCEEDED
(
hr
))
{
temp
.
CurrentValue
=
temp
.
Default
;
pParametr
[
i
]
=
temp
;
}
}
pProcAmp
->
Release
();
}
IAMCameraControl
*
pProcControl
=
NULL
;
hr
=
vd_pSource
->
QueryInterface
(
IID_PPV_ARGS
(
&
pProcControl
));
if
(
SUCCEEDED
(
hr
))
{
for
(
unsigned
int
i
=
0
;
i
<
7
;
i
++
)
{
Parametr
temp
;
hr
=
pProcControl
->
GetRange
(
CameraControl_Pan
+
i
,
&
temp
.
Min
,
&
temp
.
Max
,
&
temp
.
Step
,
&
temp
.
Default
,
&
temp
.
Flag
);
if
(
SUCCEEDED
(
hr
))
{
temp
.
CurrentValue
=
temp
.
Default
;
pParametr
[
10
+
i
]
=
temp
;
}
}
pProcControl
->
Release
();
}
}
}
return
out
;
}
long
videoDevice
::
readInfoOfDevice
(
IMFActivate
*
pActivate
,
unsigned
int
Num
)
{
vd_CurrentNumber
=
Num
;
HRESULT
hr
=
E_FAIL
;
vd_CurrentFormats
.
clear
();
if
(
pActivate
)
{
SafeRelease
(
&
vd_pSource
);
hr
=
pActivate
->
ActivateObject
(
__uuidof
(
IMFMediaSource
),
(
void
**
)
&
vd_pSource
);
if
(
SUCCEEDED
(
hr
)
&&
vd_pSource
)
{
enumerateCaptureFormats
(
vd_pSource
);
buildLibraryofTypes
();
}
//end if (SUCCEEDED(hr) && pSource)
else
DebugPrintOut
(
L"VIDEODEVICE %i: IMFMediaSource interface cannot be created
\n
"
,
vd_CurrentNumber
);
}
return
hr
;
}
MediaType
videoDevice
::
getFormat
(
unsigned
int
id
)
{
if
(
id
<
vd_CurrentFormats
.
size
())
{
return
vd_CurrentFormats
[
id
];
}
else
return
MediaType
();
}
int
videoDevice
::
getCountFormats
()
{
return
(
int
)
vd_CurrentFormats
.
size
();
}
void
videoDevice
::
setEmergencyStopEvent
(
void
*
userData
,
void
(
*
func
)(
int
,
void
*
))
{
vd_func
=
func
;
vd_userData
=
userData
;
}
void
videoDevice
::
closeDevice
()
{
if
(
vd_IsSetuped
)
{
vd_IsSetuped
=
false
;
vd_pSource
->
Shutdown
();
SafeRelease
(
&
vd_pSource
);
if
(
vd_LockOut
==
RawDataLock
)
{
vd_pImGrTh
->
stop
();
Sleep
(
500
);
delete
vd_pImGrTh
;
}
vd_pImGrTh
=
NULL
;
vd_LockOut
=
OpenLock
;
DebugPrintOut
(
L"VIDEODEVICE %i: Device is stopped
\n
"
,
vd_CurrentNumber
);
}
}
unsigned
int
videoDevice
::
getWidth
()
{
if
(
vd_IsSetuped
)
return
vd_Width
;
else
return
0
;
}
unsigned
int
videoDevice
::
getHeight
()
{
if
(
vd_IsSetuped
)
return
vd_Height
;
else
return
0
;
}
unsigned
int
videoDevice
::
getFrameRate
()
const
{
if
(
vd_IsSetuped
)
return
vd_FrameRate
;
else
return
0
;
}
IMFMediaSource
*
videoDevice
::
getMediaSource
()
{
IMFMediaSource
*
out
=
NULL
;
if
(
vd_LockOut
==
OpenLock
)
{
vd_LockOut
=
MediaSourceLock
;
out
=
vd_pSource
;
}
return
out
;
}
int
videoDevice
::
findType
(
unsigned
int
size
,
unsigned
int
frameRate
)
{
// For required frame size look for the suitable video format.
// If not found, get the format for the largest available frame size.
FrameRateMap
FRM
;
std
::
map
<
UINT64
,
FrameRateMap
>::
const_iterator
fmt
;
fmt
=
vd_CaptureFormats
.
find
(
size
);
if
(
fmt
!=
vd_CaptureFormats
.
end
()
)
FRM
=
fmt
->
second
;
else
if
(
!
vd_CaptureFormats
.
empty
()
)
FRM
=
vd_CaptureFormats
.
rbegin
()
->
second
;
if
(
FRM
.
empty
()
)
return
-
1
;
UINT64
frameRateMax
=
0
;
SUBTYPEMap
STMMax
;
if
(
frameRate
==
0
)
{
std
::
map
<
UINT64
,
SUBTYPEMap
>::
iterator
f
=
FRM
.
begin
();
for
(;
f
!=
FRM
.
end
();
f
++
)
{
// Looking for highest possible frame rate.
if
((
*
f
).
first
>=
frameRateMax
)
{
frameRateMax
=
(
*
f
).
first
;
STMMax
=
(
*
f
).
second
;
}
}
}
else
{
std
::
map
<
UINT64
,
SUBTYPEMap
>::
iterator
f
=
FRM
.
begin
();
for
(;
f
!=
FRM
.
end
();
f
++
)
{
// Looking for frame rate higher that recently found but not higher then demanded.
if
(
(
*
f
).
first
>=
frameRateMax
&&
(
*
f
).
first
<=
frameRate
)
{
frameRateMax
=
(
*
f
).
first
;
STMMax
=
(
*
f
).
second
;
}
}
}
// Get first (default) item from the list if no suitable frame rate found.
if
(
STMMax
.
empty
()
)
STMMax
=
FRM
.
begin
()
->
second
;
// Check if there are any format types on the list.
if
(
STMMax
.
empty
()
)
return
-
1
;
vectorNum
VN
=
STMMax
.
begin
()
->
second
;
if
(
VN
.
empty
()
)
return
-
1
;
return
VN
[
0
];
}
void
videoDevice
::
buildLibraryofTypes
()
{
unsigned
int
size
;
unsigned
int
framerate
;
std
::
vector
<
MediaType
>::
iterator
i
=
vd_CurrentFormats
.
begin
();
int
count
=
0
;
for
(;
i
!=
vd_CurrentFormats
.
end
();
i
++
)
{
// Count only supported video formats.
if
(
(
*
i
).
MF_MT_SUBTYPE
==
MFVideoFormat_RGB24
||
(
*
i
).
MF_MT_SUBTYPE
==
MFVideoFormat_NV12
)
{
size
=
(
*
i
).
MF_MT_FRAME_SIZE
;
framerate
=
(
*
i
).
MF_MT_FRAME_RATE_NUMERATOR
/
(
*
i
).
MF_MT_FRAME_RATE_DENOMINATOR
;
FrameRateMap
FRM
=
vd_CaptureFormats
[
size
];
SUBTYPEMap
STM
=
FRM
[
framerate
];
String
subType
((
*
i
).
pMF_MT_SUBTYPEName
);
vectorNum
VN
=
STM
[
subType
];
VN
.
push_back
(
count
);
STM
[
subType
]
=
VN
;
FRM
[
framerate
]
=
STM
;
vd_CaptureFormats
[
size
]
=
FRM
;
}
count
++
;
}
}
long
videoDevice
::
setDeviceFormat
(
IMFMediaSource
*
pSource
,
unsigned
long
dwFormatIndex
)
{
_ComPtr
<
IMFPresentationDescriptor
>
pPD
=
NULL
;
_ComPtr
<
IMFStreamDescriptor
>
pSD
=
NULL
;
_ComPtr
<
IMFMediaTypeHandler
>
pHandler
=
NULL
;
_ComPtr
<
IMFMediaType
>
pType
=
NULL
;
HRESULT
hr
=
pSource
->
CreatePresentationDescriptor
(
pPD
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
BOOL
fSelected
;
hr
=
pPD
->
GetStreamDescriptorByIndex
(
0
,
&
fSelected
,
pSD
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
hr
=
pSD
->
GetMediaTypeHandler
(
pHandler
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
hr
=
pHandler
->
GetMediaTypeByIndex
((
DWORD
)
dwFormatIndex
,
pType
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
hr
=
pHandler
->
SetCurrentMediaType
(
pType
.
Get
());
done
:
return
hr
;
}
bool
videoDevice
::
isDeviceSetup
()
{
return
vd_IsSetuped
;
}
RawImage
*
videoDevice
::
getRawImageOut
()
{
if
(
!
vd_IsSetuped
)
return
NULL
;
if
(
vd_pImGrTh
)
return
vd_pImGrTh
->
getImageGrabber
()
->
getRawImage
();
else
{
DebugPrintOut
(
L"VIDEODEVICE %i: The instance of ImageGrabberThread class does not exist
\n
"
,
vd_CurrentNumber
);
}
return
NULL
;
}
bool
videoDevice
::
isFrameNew
()
{
if
(
!
vd_IsSetuped
)
return
false
;
if
(
vd_LockOut
==
RawDataLock
||
vd_LockOut
==
OpenLock
)
{
if
(
vd_LockOut
==
OpenLock
)
{
vd_LockOut
=
RawDataLock
;
//must already be closed
HRESULT
hr
=
ImageGrabberThread
::
CreateInstance
(
&
vd_pImGrTh
,
vd_pSource
,
vd_CurrentNumber
);
if
(
FAILED
(
hr
))
{
DebugPrintOut
(
L"VIDEODEVICE %i: The instance of ImageGrabberThread class cannot be created.
\n
"
,
vd_CurrentNumber
);
return
false
;
}
vd_pImGrTh
->
setEmergencyStopEvent
(
vd_userData
,
vd_func
);
vd_pImGrTh
->
start
();
return
true
;
}
if
(
vd_pImGrTh
)
return
vd_pImGrTh
->
getImageGrabber
()
->
getRawImage
()
->
isNew
();
}
return
false
;
}
bool
videoDevice
::
isDeviceMediaSource
()
{
if
(
vd_LockOut
==
MediaSourceLock
)
return
true
;
return
false
;
}
bool
videoDevice
::
isDeviceRawDataSource
()
{
if
(
vd_LockOut
==
RawDataLock
)
return
true
;
return
false
;
}
bool
videoDevice
::
setupDevice
(
unsigned
int
id
)
{
if
(
!
vd_IsSetuped
)
{
HRESULT
hr
;
vd_Width
=
vd_CurrentFormats
[
id
].
width
;
vd_Height
=
vd_CurrentFormats
[
id
].
height
;
vd_FrameRate
=
vd_CurrentFormats
[
id
].
MF_MT_FRAME_RATE_NUMERATOR
/
vd_CurrentFormats
[
id
].
MF_MT_FRAME_RATE_DENOMINATOR
;
hr
=
setDeviceFormat
(
vd_pSource
,
(
DWORD
)
id
);
vd_IsSetuped
=
(
SUCCEEDED
(
hr
));
if
(
vd_IsSetuped
)
DebugPrintOut
(
L"
\n\n
VIDEODEVICE %i: Device is setuped
\n
"
,
vd_CurrentNumber
);
return
vd_IsSetuped
;
}
else
{
DebugPrintOut
(
L"VIDEODEVICE %i: Device is setuped already
\n
"
,
vd_CurrentNumber
);
return
false
;
}
}
bool
videoDevice
::
setupDevice
(
unsigned
int
w
,
unsigned
int
h
,
unsigned
int
idealFramerate
)
{
int
id
=
findType
(
w
*
h
,
idealFramerate
);
if
(
id
<
0
)
return
false
;
return
setupDevice
(
id
);
}
videoDevice
::~
videoDevice
(
void
)
{
closeDevice
();
SafeRelease
(
&
vd_pSource
);
if
(
vd_pFriendlyName
)
CoTaskMemFree
(
vd_pFriendlyName
);
}
HRESULT
videoDevice
::
enumerateCaptureFormats
(
IMFMediaSource
*
pSource
)
{
HRESULT
hr
=
S_OK
;
{
// "done:" scope
_ComPtr
<
IMFPresentationDescriptor
>
pPD
=
NULL
;
_ComPtr
<
IMFStreamDescriptor
>
pSD
=
NULL
;
_ComPtr
<
IMFMediaTypeHandler
>
pHandler
=
NULL
;
_ComPtr
<
IMFMediaType
>
pType
=
NULL
;
hr
=
!
pSource
?
E_POINTER
:
S_OK
;
if
(
FAILED
(
hr
))
{
goto
done
;
}
hr
=
pSource
->
CreatePresentationDescriptor
(
pPD
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
BOOL
fSelected
;
hr
=
pPD
->
GetStreamDescriptorByIndex
(
0
,
&
fSelected
,
pSD
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
hr
=
pSD
->
GetMediaTypeHandler
(
pHandler
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
DWORD
cTypes
=
0
;
hr
=
pHandler
->
GetMediaTypeCount
(
&
cTypes
);
if
(
FAILED
(
hr
))
{
goto
done
;
}
for
(
DWORD
i
=
0
;
i
<
cTypes
;
i
++
)
{
hr
=
pHandler
->
GetMediaTypeByIndex
(
i
,
pType
.
GetAddressOf
());
if
(
FAILED
(
hr
))
{
goto
done
;
}
MediaType
MT
=
FormatReader
::
Read
(
pType
.
Get
());
vd_CurrentFormats
.
push_back
(
MT
);
}
}
// "done:" scope
done
:
return
hr
;
}
videoDevices
::
videoDevices
(
void
)
{
DebugPrintOut
(
L"
\n
***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****
\n\n
"
);
}
videoDevices
::~
videoDevices
(
void
)
{
DebugPrintOut
(
L"
\n
***** CLOSE VIDEOINPUT LIBRARY - 2013 *****
\n\n
"
);
}
cv
::
Ptr
<
videoDevice
>
videoDevices
::
getDevice
(
unsigned
int
i
,
bool
fallback
)
{
static
videoDevices
instance
;
cv
::
Ptr
<
videoDevice
>
res
;
_ComPtr
<
IMFAttributes
>
pAttributes
=
NULL
;
if
(
SUCCEEDED
(
MFCreateAttributes
(
pAttributes
.
GetAddressOf
(),
1
))
&&
SUCCEEDED
(
pAttributes
->
SetGUID
(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE
,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
)))
{
IMFActivate
**
ppDevices
=
NULL
;
UINT32
count
;
if
(
SUCCEEDED
(
MFEnumDeviceSources
(
pAttributes
.
Get
(),
&
ppDevices
,
&
count
)))
{
if
(
count
>
0
)
{
if
(
fallback
)
i
=
std
::
min
(
std
::
max
(
0U
,
i
),
count
-
1
);
for
(
UINT32
ind
=
0
;
ind
<
count
;
ind
++
)
{
if
(
ind
==
i
)
{
res
=
cv
::
Ptr
<
videoDevice
>
(
new
videoDevice
);
res
->
readInfoOfDevice
(
ppDevices
[
ind
],
ind
);
res
->
setupDevice
(
0
,
0
,
0
);
if
(
!
res
->
isDeviceSetup
()
||
!
res
->
isFrameNew
())
res
.
release
();
}
SafeRelease
(
&
ppDevices
[
ind
]);
}
}
}
else
DebugPrintOut
(
L"VIDEODEVICES: The instances of the videoDevice class cannot be created
\n
"
);
CoTaskMemFree
(
ppDevices
);
}
if
(
res
.
empty
())
DebugPrintOut
(
L"VIDEODEVICE %i: Invalid device ID
\n
"
,
i
);
return
res
;
}
Parametr
::
Parametr
()
{
CurrentValue
=
0
;
Min
=
0
;
Max
=
0
;
Step
=
0
;
Default
=
0
;
Flag
=
0
;
}
MediaType
::
MediaType
()
{
pMF_MT_AM_FORMAT_TYPEName
=
NULL
;
pMF_MT_MAJOR_TYPEName
=
NULL
;
pMF_MT_SUBTYPEName
=
NULL
;
Clear
();
}
MediaType
::~
MediaType
()
...
...
@@ -2067,7 +864,7 @@ bool CvCaptureCAM_MSMF::configureOutput(unsigned int width, unsigned int height,
}
else
if
(
SUCCEEDED
(
hr
))
{
MediaType
MT
=
FormatReader
::
Read
(
pType
.
Get
());
MediaType
MT
(
pType
.
Get
());
if
(
MT
.
MF_MT_MAJOR_TYPE
==
MFMediaType_Video
)
{
if
(
dwStreamFallback
<
0
||
...
...
@@ -2160,7 +957,8 @@ bool CvCaptureCAM_MSMF::open(int _index)
configureOutput
(
0
,
0
,
0
);
}
}
SafeRelease
(
&
ppDevices
[
ind
]);
if
(
ppDevices
[
ind
])
ppDevices
[
ind
]
->
Release
();
}
}
}
...
...
@@ -2407,7 +1205,7 @@ bool CvCaptureFile_MSMF::open(const char* filename)
}
else
if
(
SUCCEEDED
(
hr
))
{
MediaType
MT
=
FormatReader
::
Read
(
pType
.
Get
());
MediaType
MT
(
pType
.
Get
());
if
(
MT
.
MF_MT_MAJOR_TYPE
==
MFMediaType_Video
)
{
captureFormat
=
MT
;
...
...
modules/videoio/src/cap_msmf.hpp
View file @
b0b2d8de
EXTERN_C
const
IID
IID_ICustomStreamSink
;
class
DECLSPEC_UUID
(
"4F8A1939-2FD3-46DB-AE70-DB7E0DD79B73"
)
DECLSPEC_NOVTABLE
ICustomStreamSink
:
public
IUnknown
{
public
:
virtual
HRESULT
Initialize
()
=
0
;
virtual
HRESULT
Shutdown
()
=
0
;
virtual
HRESULT
Start
(
MFTIME
start
)
=
0
;
virtual
HRESULT
Pause
()
=
0
;
virtual
HRESULT
Restart
()
=
0
;
virtual
HRESULT
Stop
()
=
0
;
};
#define MF_PROP_SAMPLEGRABBERCALLBACK L"samplegrabbercallback"
#define MF_PROP_VIDTYPE L"vidtype"
#define MF_PROP_VIDENCPROPS L"videncprops"
#include <initguid.h>
// MF_MEDIASINK_SAMPLEGRABBERCALLBACK: {26957AA7-AFF4-464c-BB8B-07BA65CE11DF}
// Type: IUnknown*
DEFINE_GUID
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
0x26957aa7
,
0xaff4
,
0x464c
,
0xbb
,
0x8b
,
0x7
,
0xba
,
0x65
,
0xce
,
0x11
,
0xdf
);
// {4BD133CC-EB9B-496E-8865-0813BFBC6FAA}
DEFINE_GUID
(
MF_STREAMSINK_ID
,
0x4bd133cc
,
0xeb9b
,
0x496e
,
0x88
,
0x65
,
0x8
,
0x13
,
0xbf
,
0xbc
,
0x6f
,
0xaa
);
// {C9E22A8C-6A50-4D78-9183-0834A02A3780}
DEFINE_GUID
(
MF_STREAMSINK_MEDIASINKINTERFACE
,
0xc9e22a8c
,
0x6a50
,
0x4d78
,
0x91
,
0x83
,
0x8
,
0x34
,
0xa0
,
0x2a
,
0x37
,
0x80
);
// {DABD13AB-26B7-47C2-97C1-4B04C187B838}
DEFINE_GUID
(
MF_MEDIASINK_PREFERREDTYPE
,
0xdabd13ab
,
0x26b7
,
0x47c2
,
0x97
,
0xc1
,
0x4b
,
0x4
,
0xc1
,
0x87
,
0xb8
,
0x38
);
#include <utility>
#ifdef _UNICODE
#define MAKE_MAP(e) std::map<e, std::wstring>
#define MAKE_ENUM(e) std::pair<e, std::wstring>
#define MAKE_ENUM_PAIR(e, str) std::pair<e, std::wstring>(str, L#str)
#else
#define MAKE_MAP(e) std::map<e, std::string>
#define MAKE_ENUM(e) std::pair<e, std::string>
#define MAKE_ENUM_PAIR(e, str) std::pair<e, std::string>(str, #str)
#endif
MAKE_ENUM
(
MediaEventType
)
MediaEventTypePairs
[]
=
{
MAKE_ENUM_PAIR
(
MediaEventType
,
MEUnknown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEError
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEExtendedType
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MENonFatalError
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEGenericV1Anchor
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionUnknown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionTopologySet
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionTopologiesCleared
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionStarted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionPaused
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionStopped
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionClosed
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionEnded
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionRateChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionScrubSampleComplete
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionCapabilitiesChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionTopologyStatus
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionNotifyPresentationTime
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MENewPresentation
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MELicenseAcquisitionStart
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MELicenseAcquisitionCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEIndividualizationStart
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEIndividualizationCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEEnablerProgress
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEEnablerCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEPolicyError
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEPolicyReport
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEBufferingStarted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEBufferingStopped
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEConnectStart
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEConnectEnd
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEReconnectStart
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEReconnectEnd
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MERendererEvent
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionStreamSinkFormatChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESessionV1Anchor
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceUnknown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceStarted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamStarted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceSeeked
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSeeked
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MENewStream
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEUpdatedStream
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceStopped
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamStopped
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourcePaused
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamPaused
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEEndOfPresentation
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEEndOfStream
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEMediaSample
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamTick
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamThinMode
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamFormatChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceRateChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEEndOfPresentationSegment
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceCharacteristicsChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceRateChangeRequested
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceMetadataChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESequencerSourceTopologyUpdated
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESourceV1Anchor
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESinkUnknown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkStarted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkStopped
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkPaused
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkRateChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkRequestSample
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkMarker
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkPrerolled
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkScrubSampleComplete
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkFormatChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEStreamSinkDeviceChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEQualityNotify
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESinkInvalidated
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionNameChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionVolumeChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionDeviceRemoved
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionServerShutdown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionGroupingParamChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionIconChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionFormatChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionDisconnected
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEAudioSessionExclusiveModeOverride
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESinkV1Anchor
),
#if (WINVER >= 0x0602) // Available since Win 8
MAKE_ENUM_PAIR
(
MediaEventType
,
MECaptureAudioSessionVolumeChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MECaptureAudioSessionDeviceRemoved
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MECaptureAudioSessionFormatChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MECaptureAudioSessionDisconnected
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MECaptureAudioSessionExclusiveModeOverride
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MECaptureAudioSessionServerShutdown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MESinkV2Anchor
),
#endif
MAKE_ENUM_PAIR
(
MediaEventType
,
METrustUnknown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEPolicyChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEContentProtectionMessage
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEPolicySet
),
MAKE_ENUM_PAIR
(
MediaEventType
,
METrustV1Anchor
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMLicenseBackupCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMLicenseBackupProgress
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMLicenseRestoreCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMLicenseRestoreProgress
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMLicenseAcquisitionCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMIndividualizationCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMIndividualizationProgress
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMProximityCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMLicenseStoreCleaned
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMRevocationDownloadCompleted
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEWMDRMV1Anchor
),
MAKE_ENUM_PAIR
(
MediaEventType
,
METransformUnknown
),
MAKE_ENUM_PAIR
(
MediaEventType
,
METransformNeedInput
),
MAKE_ENUM_PAIR
(
MediaEventType
,
METransformHaveOutput
),
MAKE_ENUM_PAIR
(
MediaEventType
,
METransformDrainComplete
),
MAKE_ENUM_PAIR
(
MediaEventType
,
METransformMarker
),
#if (WINVER >= 0x0602) // Available since Win 8
MAKE_ENUM_PAIR
(
MediaEventType
,
MEByteStreamCharacteristicsChanged
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEVideoCaptureDeviceRemoved
),
MAKE_ENUM_PAIR
(
MediaEventType
,
MEVideoCaptureDevicePreempted
),
#endif
MAKE_ENUM_PAIR
(
MediaEventType
,
MEReservedMax
)
};
MAKE_MAP
(
MediaEventType
)
MediaEventTypeMap
(
MediaEventTypePairs
,
MediaEventTypePairs
+
sizeof
(
MediaEventTypePairs
)
/
sizeof
(
MediaEventTypePairs
[
0
]));
MAKE_ENUM
(
MFSTREAMSINK_MARKER_TYPE
)
StreamSinkMarkerTypePairs
[]
=
{
MAKE_ENUM_PAIR
(
MFSTREAMSINK_MARKER_TYPE
,
MFSTREAMSINK_MARKER_DEFAULT
),
MAKE_ENUM_PAIR
(
MFSTREAMSINK_MARKER_TYPE
,
MFSTREAMSINK_MARKER_ENDOFSEGMENT
),
MAKE_ENUM_PAIR
(
MFSTREAMSINK_MARKER_TYPE
,
MFSTREAMSINK_MARKER_TICK
),
MAKE_ENUM_PAIR
(
MFSTREAMSINK_MARKER_TYPE
,
MFSTREAMSINK_MARKER_EVENT
)
};
MAKE_MAP
(
MFSTREAMSINK_MARKER_TYPE
)
StreamSinkMarkerTypeMap
(
StreamSinkMarkerTypePairs
,
StreamSinkMarkerTypePairs
+
sizeof
(
StreamSinkMarkerTypePairs
)
/
sizeof
(
StreamSinkMarkerTypePairs
[
0
]));
#define _COM_SMARTPTR_DECLARE(T,var) T ## Ptr var
template
<
class
T
>
class
ComPtr
{
public
:
ComPtr
()
throw
()
{
}
ComPtr
(
T
*
lp
)
throw
()
{
p
=
lp
;
}
ComPtr
(
_In_
const
ComPtr
<
T
>&
lp
)
throw
()
{
p
=
lp
.
p
;
}
virtual
~
ComPtr
()
{
}
T
**
operator
&
()
throw
()
{
assert
(
p
==
NULL
);
return
p
.
operator
&
();
}
T
*
operator
->
()
const
throw
()
{
assert
(
p
!=
NULL
);
return
p
.
operator
->
();
}
bool
operator
!
()
const
throw
()
{
return
p
.
operator
==
(
NULL
);
}
bool
operator
==
(
_In_opt_
T
*
pT
)
const
throw
()
{
return
p
.
operator
==
(
pT
);
}
bool
operator
!=
(
_In_opt_
T
*
pT
)
const
throw
()
{
return
p
.
operator
!=
(
pT
);
}
operator
bool
()
{
return
p
.
operator
!=
(
NULL
);
}
T
*
const
*
GetAddressOf
()
const
throw
()
{
return
&
p
;
}
T
**
GetAddressOf
()
throw
()
{
return
&
p
;
}
T
**
ReleaseAndGetAddressOf
()
throw
()
{
p
.
Release
();
return
&
p
;
}
T
*
Get
()
const
throw
()
{
return
p
;
}
// Attach to an existing interface (does not AddRef)
void
Attach
(
_In_opt_
T
*
p2
)
throw
()
{
p
.
Attach
(
p2
);
}
// Detach the interface (does not Release)
T
*
Detach
()
throw
()
{
return
p
.
Detach
();
}
_Check_return_
HRESULT
CopyTo
(
_Deref_out_opt_
T
**
ppT
)
throw
()
{
assert
(
ppT
!=
NULL
);
if
(
ppT
==
NULL
)
return
E_POINTER
;
*
ppT
=
p
;
if
(
p
!=
NULL
)
p
->
AddRef
();
return
S_OK
;
}
void
Reset
()
{
p
.
Release
();
}
// query for U interface
template
<
typename
U
>
HRESULT
As
(
_Inout_
U
**
lp
)
const
throw
()
{
return
p
->
QueryInterface
(
__uuidof
(
U
),
reinterpret_cast
<
void
**>
(
lp
));
}
// query for U interface
template
<
typename
U
>
HRESULT
As
(
_Out_
ComPtr
<
U
>*
lp
)
const
throw
()
{
return
p
->
QueryInterface
(
__uuidof
(
U
),
reinterpret_cast
<
void
**>
(
lp
->
ReleaseAndGetAddressOf
()));
}
private
:
_COM_SMARTPTR_TYPEDEF
(
T
,
__uuidof
(
T
));
_COM_SMARTPTR_DECLARE
(
T
,
p
);
};
#define _ComPtr ComPtr
template
<
class
TBase
=
IMFAttributes
>
class
CBaseAttributes
:
public
TBase
{
protected
:
// This version of the constructor does not initialize the
// attribute store. The derived class must call Initialize() in
// its own constructor.
CBaseAttributes
()
{
}
// This version of the constructor initializes the attribute
// store, but the derived class must pass an HRESULT parameter
// to the constructor.
CBaseAttributes
(
HRESULT
&
hr
,
UINT32
cInitialSize
=
0
)
{
hr
=
Initialize
(
cInitialSize
);
}
// The next version of the constructor uses a caller-provided
// implementation of IMFAttributes.
// (Sometimes you want to delegate IMFAttributes calls to some
// other object that implements IMFAttributes, rather than using
// MFCreateAttributes.)
CBaseAttributes
(
HRESULT
&
hr
,
IUnknown
*
pUnk
)
{
hr
=
Initialize
(
pUnk
);
}
virtual
~
CBaseAttributes
()
{
}
// Initializes the object by creating the standard Media Foundation attribute store.
HRESULT
Initialize
(
UINT32
cInitialSize
=
0
)
{
if
(
_spAttributes
.
Get
()
==
nullptr
)
{
return
MFCreateAttributes
(
&
_spAttributes
,
cInitialSize
);
}
else
{
return
S_OK
;
}
}
// Initializes this object from a caller-provided attribute store.
// pUnk: Pointer to an object that exposes IMFAttributes.
HRESULT
Initialize
(
IUnknown
*
pUnk
)
{
if
(
_spAttributes
)
{
_spAttributes
.
Reset
();
_spAttributes
=
nullptr
;
}
return
pUnk
->
QueryInterface
(
IID_PPV_ARGS
(
&
_spAttributes
));
}
public
:
// IMFAttributes methods
STDMETHODIMP
GetItem
(
REFGUID
guidKey
,
PROPVARIANT
*
pValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetItem
(
guidKey
,
pValue
);
}
STDMETHODIMP
GetItemType
(
REFGUID
guidKey
,
MF_ATTRIBUTE_TYPE
*
pType
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetItemType
(
guidKey
,
pType
);
}
STDMETHODIMP
CompareItem
(
REFGUID
guidKey
,
REFPROPVARIANT
Value
,
BOOL
*
pbResult
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
CompareItem
(
guidKey
,
Value
,
pbResult
);
}
STDMETHODIMP
Compare
(
IMFAttributes
*
pTheirs
,
MF_ATTRIBUTES_MATCH_TYPE
MatchType
,
BOOL
*
pbResult
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
Compare
(
pTheirs
,
MatchType
,
pbResult
);
}
STDMETHODIMP
GetUINT32
(
REFGUID
guidKey
,
UINT32
*
punValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetUINT32
(
guidKey
,
punValue
);
}
STDMETHODIMP
GetUINT64
(
REFGUID
guidKey
,
UINT64
*
punValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetUINT64
(
guidKey
,
punValue
);
}
STDMETHODIMP
GetDouble
(
REFGUID
guidKey
,
double
*
pfValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetDouble
(
guidKey
,
pfValue
);
}
STDMETHODIMP
GetGUID
(
REFGUID
guidKey
,
GUID
*
pguidValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetGUID
(
guidKey
,
pguidValue
);
}
STDMETHODIMP
GetStringLength
(
REFGUID
guidKey
,
UINT32
*
pcchLength
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetStringLength
(
guidKey
,
pcchLength
);
}
STDMETHODIMP
GetString
(
REFGUID
guidKey
,
LPWSTR
pwszValue
,
UINT32
cchBufSize
,
UINT32
*
pcchLength
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetString
(
guidKey
,
pwszValue
,
cchBufSize
,
pcchLength
);
}
STDMETHODIMP
GetAllocatedString
(
REFGUID
guidKey
,
LPWSTR
*
ppwszValue
,
UINT32
*
pcchLength
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetAllocatedString
(
guidKey
,
ppwszValue
,
pcchLength
);
}
STDMETHODIMP
GetBlobSize
(
REFGUID
guidKey
,
UINT32
*
pcbBlobSize
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetBlobSize
(
guidKey
,
pcbBlobSize
);
}
STDMETHODIMP
GetBlob
(
REFGUID
guidKey
,
UINT8
*
pBuf
,
UINT32
cbBufSize
,
UINT32
*
pcbBlobSize
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetBlob
(
guidKey
,
pBuf
,
cbBufSize
,
pcbBlobSize
);
}
STDMETHODIMP
GetAllocatedBlob
(
REFGUID
guidKey
,
UINT8
**
ppBuf
,
UINT32
*
pcbSize
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetAllocatedBlob
(
guidKey
,
ppBuf
,
pcbSize
);
}
STDMETHODIMP
GetUnknown
(
REFGUID
guidKey
,
REFIID
riid
,
LPVOID
*
ppv
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetUnknown
(
guidKey
,
riid
,
ppv
);
}
STDMETHODIMP
SetItem
(
REFGUID
guidKey
,
REFPROPVARIANT
Value
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetItem
(
guidKey
,
Value
);
}
STDMETHODIMP
DeleteItem
(
REFGUID
guidKey
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
DeleteItem
(
guidKey
);
}
STDMETHODIMP
DeleteAllItems
()
{
assert
(
_spAttributes
);
return
_spAttributes
->
DeleteAllItems
();
}
STDMETHODIMP
SetUINT32
(
REFGUID
guidKey
,
UINT32
unValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetUINT32
(
guidKey
,
unValue
);
}
STDMETHODIMP
SetUINT64
(
REFGUID
guidKey
,
UINT64
unValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetUINT64
(
guidKey
,
unValue
);
}
STDMETHODIMP
SetDouble
(
REFGUID
guidKey
,
double
fValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetDouble
(
guidKey
,
fValue
);
}
STDMETHODIMP
SetGUID
(
REFGUID
guidKey
,
REFGUID
guidValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetGUID
(
guidKey
,
guidValue
);
}
STDMETHODIMP
SetString
(
REFGUID
guidKey
,
LPCWSTR
wszValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetString
(
guidKey
,
wszValue
);
}
STDMETHODIMP
SetBlob
(
REFGUID
guidKey
,
const
UINT8
*
pBuf
,
UINT32
cbBufSize
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetBlob
(
guidKey
,
pBuf
,
cbBufSize
);
}
STDMETHODIMP
SetUnknown
(
REFGUID
guidKey
,
IUnknown
*
pUnknown
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
SetUnknown
(
guidKey
,
pUnknown
);
}
STDMETHODIMP
LockStore
()
{
assert
(
_spAttributes
);
return
_spAttributes
->
LockStore
();
}
STDMETHODIMP
UnlockStore
()
{
assert
(
_spAttributes
);
return
_spAttributes
->
UnlockStore
();
}
STDMETHODIMP
GetCount
(
UINT32
*
pcItems
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetCount
(
pcItems
);
}
STDMETHODIMP
GetItemByIndex
(
UINT32
unIndex
,
GUID
*
pguidKey
,
PROPVARIANT
*
pValue
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
GetItemByIndex
(
unIndex
,
pguidKey
,
pValue
);
}
STDMETHODIMP
CopyAllItems
(
IMFAttributes
*
pDest
)
{
assert
(
_spAttributes
);
return
_spAttributes
->
CopyAllItems
(
pDest
);
}
// Helper functions
HRESULT
SerializeToStream
(
DWORD
dwOptions
,
IStream
*
pStm
)
// dwOptions: Flags from MF_ATTRIBUTE_SERIALIZE_OPTIONS
{
assert
(
_spAttributes
);
return
MFSerializeAttributesToStream
(
_spAttributes
.
Get
(),
dwOptions
,
pStm
);
}
HRESULT
DeserializeFromStream
(
DWORD
dwOptions
,
IStream
*
pStm
)
{
assert
(
_spAttributes
);
return
MFDeserializeAttributesFromStream
(
_spAttributes
.
Get
(),
dwOptions
,
pStm
);
}
// SerializeToBlob: Stores the attributes in a byte array.
//
// ppBuf: Receives a pointer to the byte array.
// pcbSize: Receives the size of the byte array.
//
// The caller must free the array using CoTaskMemFree.
HRESULT
SerializeToBlob
(
UINT8
**
ppBuffer
,
UINT
*
pcbSize
)
{
assert
(
_spAttributes
);
if
(
ppBuffer
==
NULL
)
{
return
E_POINTER
;
}
if
(
pcbSize
==
NULL
)
{
return
E_POINTER
;
}
HRESULT
hr
=
S_OK
;
UINT32
cbSize
=
0
;
BYTE
*
pBuffer
=
NULL
;
CHECK_HR
(
hr
=
MFGetAttributesAsBlobSize
(
_spAttributes
.
Get
(),
&
cbSize
));
pBuffer
=
(
BYTE
*
)
CoTaskMemAlloc
(
cbSize
);
if
(
pBuffer
==
NULL
)
{
CHECK_HR
(
hr
=
E_OUTOFMEMORY
);
}
CHECK_HR
(
hr
=
MFGetAttributesAsBlob
(
_spAttributes
.
Get
(),
pBuffer
,
cbSize
));
*
ppBuffer
=
pBuffer
;
*
pcbSize
=
cbSize
;
done
:
if
(
FAILED
(
hr
))
{
*
ppBuffer
=
NULL
;
*
pcbSize
=
0
;
CoTaskMemFree
(
pBuffer
);
}
return
hr
;
}
HRESULT
DeserializeFromBlob
(
const
UINT8
*
pBuffer
,
UINT
cbSize
)
{
assert
(
_spAttributes
);
return
MFInitAttributesFromBlob
(
_spAttributes
.
Get
(),
pBuffer
,
cbSize
);
}
HRESULT
GetRatio
(
REFGUID
guidKey
,
UINT32
*
pnNumerator
,
UINT32
*
punDenominator
)
{
assert
(
_spAttributes
);
return
MFGetAttributeRatio
(
_spAttributes
.
Get
(),
guidKey
,
pnNumerator
,
punDenominator
);
}
HRESULT
SetRatio
(
REFGUID
guidKey
,
UINT32
unNumerator
,
UINT32
unDenominator
)
{
assert
(
_spAttributes
);
return
MFSetAttributeRatio
(
_spAttributes
.
Get
(),
guidKey
,
unNumerator
,
unDenominator
);
}
// Gets an attribute whose value represents the size of something (eg a video frame).
HRESULT
GetSize
(
REFGUID
guidKey
,
UINT32
*
punWidth
,
UINT32
*
punHeight
)
{
assert
(
_spAttributes
);
return
MFGetAttributeSize
(
_spAttributes
.
Get
(),
guidKey
,
punWidth
,
punHeight
);
}
// Sets an attribute whose value represents the size of something (eg a video frame).
HRESULT
SetSize
(
REFGUID
guidKey
,
UINT32
unWidth
,
UINT32
unHeight
)
{
assert
(
_spAttributes
);
return
MFSetAttributeSize
(
_spAttributes
.
Get
(),
guidKey
,
unWidth
,
unHeight
);
}
protected
:
_ComPtr
<
IMFAttributes
>
_spAttributes
;
};
class
StreamSink
:
public
IMFStreamSink
,
public
IMFMediaTypeHandler
,
public
CBaseAttributes
<>
,
public
ICustomStreamSink
{
public
:
// IUnknown methods
#if defined(_MSC_VER) && _MSC_VER >= 1700 // '_Outptr_result_nullonfailure_' SAL is avaialable since VS 2012
STDMETHOD
(
QueryInterface
)(
REFIID
riid
,
_Outptr_result_nullonfailure_
void
**
ppv
)
#else
STDMETHOD
(
QueryInterface
)(
REFIID
riid
,
void
**
ppv
)
#endif
{
if
(
ppv
==
nullptr
)
{
return
E_POINTER
;
}
(
*
ppv
)
=
nullptr
;
HRESULT
hr
=
S_OK
;
if
(
riid
==
IID_IMarshal
)
{
return
MarshalQI
(
riid
,
ppv
);
}
else
{
if
(
riid
==
IID_IUnknown
||
riid
==
IID_IMFStreamSink
)
{
*
ppv
=
static_cast
<
IMFStreamSink
*>
(
this
);
AddRef
();
}
else
if
(
riid
==
IID_IMFMediaEventGenerator
)
{
*
ppv
=
static_cast
<
IMFMediaEventGenerator
*>
(
this
);
AddRef
();
}
else
if
(
riid
==
IID_IMFMediaTypeHandler
)
{
*
ppv
=
static_cast
<
IMFMediaTypeHandler
*>
(
this
);
AddRef
();
}
else
if
(
riid
==
IID_IMFAttributes
)
{
*
ppv
=
static_cast
<
IMFAttributes
*>
(
this
);
AddRef
();
}
else
if
(
riid
==
IID_ICustomStreamSink
)
{
*
ppv
=
static_cast
<
ICustomStreamSink
*>
(
this
);
AddRef
();
}
else
hr
=
E_NOINTERFACE
;
}
return
hr
;
}
ULONG
STDMETHODCALLTYPE
AddRef
()
{
return
InterlockedIncrement
(
&
m_cRef
);
}
ULONG
STDMETHODCALLTYPE
Release
()
{
ULONG
cRef
=
InterlockedDecrement
(
&
m_cRef
);
if
(
cRef
==
0
)
{
delete
this
;
}
return
cRef
;
}
HRESULT
MarshalQI
(
REFIID
riid
,
LPVOID
*
ppv
)
{
HRESULT
hr
=
S_OK
;
if
(
m_spFTM
==
nullptr
)
{
EnterCriticalSection
(
&
m_critSec
);
if
(
m_spFTM
==
nullptr
)
{
hr
=
CoCreateFreeThreadedMarshaler
((
IMFStreamSink
*
)
this
,
&
m_spFTM
);
}
LeaveCriticalSection
(
&
m_critSec
);
}
if
(
SUCCEEDED
(
hr
))
{
if
(
m_spFTM
==
nullptr
)
{
hr
=
E_UNEXPECTED
;
}
else
{
hr
=
m_spFTM
.
Get
()
->
QueryInterface
(
riid
,
ppv
);
}
}
return
hr
;
}
enum
State
{
State_TypeNotSet
=
0
,
// No media type is set
State_Ready
,
// Media type is set, Start has never been called.
State_Started
,
State_Stopped
,
State_Paused
,
State_Count
// Number of states
};
StreamSink
()
:
m_IsShutdown
(
false
),
m_StartTime
(
0
),
m_fGetStartTimeFromSample
(
false
),
m_fWaitingForFirstSample
(
false
),
m_state
(
State_TypeNotSet
),
m_pParent
(
nullptr
),
m_imageWidthInPixels
(
0
),
m_imageHeightInPixels
(
0
)
{
m_bConnected
=
false
;
InitializeCriticalSectionEx
(
&
m_critSec
,
3000
,
0
);
ZeroMemory
(
&
m_guiCurrentSubtype
,
sizeof
(
m_guiCurrentSubtype
));
CBaseAttributes
::
Initialize
(
0U
);
DebugPrintOut
(
L"StreamSink::StreamSink
\n
"
);
}
virtual
~
StreamSink
()
{
DeleteCriticalSection
(
&
m_critSec
);
assert
(
m_IsShutdown
);
DebugPrintOut
(
L"StreamSink::~StreamSink
\n
"
);
}
HRESULT
Initialize
()
{
HRESULT
hr
;
// Create the event queue helper.
hr
=
MFCreateEventQueue
(
&
m_spEventQueue
);
if
(
SUCCEEDED
(
hr
))
{
_ComPtr
<
IMFMediaSink
>
pMedSink
;
hr
=
CBaseAttributes
<>::
GetUnknown
(
MF_STREAMSINK_MEDIASINKINTERFACE
,
__uuidof
(
IMFMediaSink
),
(
LPVOID
*
)
pMedSink
.
GetAddressOf
());
assert
(
pMedSink
.
Get
()
!=
NULL
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
pMedSink
.
Get
()
->
QueryInterface
(
IID_PPV_ARGS
(
&
m_pParent
));
}
}
return
hr
;
}
HRESULT
CheckShutdown
()
const
{
if
(
m_IsShutdown
)
{
return
MF_E_SHUTDOWN
;
}
else
{
return
S_OK
;
}
}
// Called when the presentation clock starts.
HRESULT
Start
(
MFTIME
start
)
{
HRESULT
hr
=
S_OK
;
EnterCriticalSection
(
&
m_critSec
);
if
(
m_state
!=
State_TypeNotSet
)
{
if
(
start
!=
PRESENTATION_CURRENT_POSITION
)
{
m_StartTime
=
start
;
// Cache the start time.
m_fGetStartTimeFromSample
=
false
;
}
else
{
m_fGetStartTimeFromSample
=
true
;
}
m_state
=
State_Started
;
GUID
guiMajorType
;
m_fWaitingForFirstSample
=
SUCCEEDED
(
m_spCurrentType
->
GetMajorType
(
&
guiMajorType
))
&&
(
guiMajorType
==
MFMediaType_Video
);
hr
=
QueueEvent
(
MEStreamSinkStarted
,
GUID_NULL
,
hr
,
NULL
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
QueueEvent
(
MEStreamSinkRequestSample
,
GUID_NULL
,
hr
,
NULL
);
}
}
else
hr
=
MF_E_NOT_INITIALIZED
;
LeaveCriticalSection
(
&
m_critSec
);
return
hr
;
}
// Called when the presentation clock pauses.
HRESULT
Pause
()
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
S_OK
;
if
(
m_state
!=
State_Stopped
&&
m_state
!=
State_TypeNotSet
)
{
m_state
=
State_Paused
;
hr
=
QueueEvent
(
MEStreamSinkPaused
,
GUID_NULL
,
hr
,
NULL
);
}
else
if
(
hr
==
State_TypeNotSet
)
hr
=
MF_E_NOT_INITIALIZED
;
else
hr
=
MF_E_INVALIDREQUEST
;
LeaveCriticalSection
(
&
m_critSec
);
return
hr
;
}
// Called when the presentation clock restarts.
HRESULT
Restart
()
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
S_OK
;
if
(
m_state
==
State_Paused
)
{
m_state
=
State_Started
;
hr
=
QueueEvent
(
MEStreamSinkStarted
,
GUID_NULL
,
hr
,
NULL
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
QueueEvent
(
MEStreamSinkRequestSample
,
GUID_NULL
,
hr
,
NULL
);
}
}
else
if
(
hr
==
State_TypeNotSet
)
hr
=
MF_E_NOT_INITIALIZED
;
else
hr
=
MF_E_INVALIDREQUEST
;
LeaveCriticalSection
(
&
m_critSec
);
return
hr
;
}
// Called when the presentation clock stops.
HRESULT
Stop
()
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
S_OK
;
if
(
m_state
!=
State_TypeNotSet
)
{
m_state
=
State_Stopped
;
hr
=
QueueEvent
(
MEStreamSinkStopped
,
GUID_NULL
,
hr
,
NULL
);
}
else
hr
=
MF_E_NOT_INITIALIZED
;
LeaveCriticalSection
(
&
m_critSec
);
return
hr
;
}
// Shuts down the stream sink.
HRESULT
Shutdown
()
{
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
HRESULT
hr
=
S_OK
;
assert
(
!
m_IsShutdown
);
hr
=
m_pParent
->
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
if
(
SUCCEEDED
(
hr
))
{
hr
=
pSampleCallback
->
OnShutdown
();
}
if
(
m_spEventQueue
)
{
hr
=
m_spEventQueue
->
Shutdown
();
}
if
(
m_pParent
)
m_pParent
->
Release
();
m_spCurrentType
.
Reset
();
m_IsShutdown
=
TRUE
;
return
hr
;
}
//IMFStreamSink
HRESULT
STDMETHODCALLTYPE
GetMediaSink
(
/* [out] */
__RPC__deref_out_opt
IMFMediaSink
**
ppMediaSink
)
{
if
(
ppMediaSink
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
_ComPtr
<
IMFMediaSink
>
pMedSink
;
hr
=
CBaseAttributes
<>::
GetUnknown
(
MF_STREAMSINK_MEDIASINKINTERFACE
,
__uuidof
(
IMFMediaSink
),
(
LPVOID
*
)
pMedSink
.
GetAddressOf
());
if
(
SUCCEEDED
(
hr
))
{
*
ppMediaSink
=
pMedSink
.
Detach
();
}
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::GetMediaSink: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
GetIdentifier
(
/* [out] */
__RPC__out
DWORD
*
pdwIdentifier
)
{
if
(
pdwIdentifier
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
hr
=
GetUINT32
(
MF_STREAMSINK_ID
,
(
UINT32
*
)
pdwIdentifier
);
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::GetIdentifier: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
GetMediaTypeHandler
(
/* [out] */
__RPC__deref_out_opt
IMFMediaTypeHandler
**
ppHandler
)
{
if
(
ppHandler
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
// This stream object acts as its own type handler, so we QI ourselves.
if
(
SUCCEEDED
(
hr
))
{
hr
=
QueryInterface
(
IID_IMFMediaTypeHandler
,
(
void
**
)
ppHandler
);
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::GetMediaTypeHandler: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
ProcessSample
(
IMFSample
*
pSample
)
{
_ComPtr
<
IMFMediaBuffer
>
pInput
;
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
BYTE
*
pSrc
=
NULL
;
// Source buffer.
// Stride if the buffer does not support IMF2DBuffer
LONGLONG
hnsTime
=
0
;
LONGLONG
hnsDuration
=
0
;
DWORD
cbMaxLength
;
DWORD
cbCurrentLength
=
0
;
GUID
guidMajorType
;
if
(
pSample
==
NULL
)
{
return
E_INVALIDARG
;
}
HRESULT
hr
=
S_OK
;
EnterCriticalSection
(
&
m_critSec
);
if
(
m_state
!=
State_Started
&&
m_state
!=
State_Paused
)
{
if
(
m_state
==
State_TypeNotSet
)
hr
=
MF_E_NOT_INITIALIZED
;
else
hr
=
MF_E_INVALIDREQUEST
;
}
if
(
SUCCEEDED
(
hr
))
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
hr
=
pSample
->
ConvertToContiguousBuffer
(
&
pInput
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
pSample
->
GetSampleTime
(
&
hnsTime
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
pSample
->
GetSampleDuration
(
&
hnsDuration
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
GetMajorType
(
&
guidMajorType
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_pParent
->
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
pInput
->
Lock
(
&
pSrc
,
&
cbMaxLength
,
&
cbCurrentLength
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
pSampleCallback
->
OnProcessSample
(
guidMajorType
,
0
,
hnsTime
,
hnsDuration
,
pSrc
,
cbCurrentLength
);
pInput
->
Unlock
();
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
QueueEvent
(
MEStreamSinkRequestSample
,
GUID_NULL
,
S_OK
,
NULL
);
}
}
LeaveCriticalSection
(
&
m_critSec
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
PlaceMarker
(
/* [in] */
MFSTREAMSINK_MARKER_TYPE
eMarkerType
,
/* [in] */
__RPC__in
const
PROPVARIANT
*
/*pvarMarkerValue*/
,
/* [in] */
__RPC__in
const
PROPVARIANT
*
/*pvarContextValue*/
)
{
eMarkerType
;
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
S_OK
;
if
(
m_state
==
State_TypeNotSet
)
hr
=
MF_E_NOT_INITIALIZED
;
if
(
SUCCEEDED
(
hr
))
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
//at shutdown will receive MFSTREAMSINK_MARKER_ENDOFSEGMENT
hr
=
QueueEvent
(
MEStreamSinkRequestSample
,
GUID_NULL
,
S_OK
,
NULL
);
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::PlaceMarker: HRESULT=%i %s
\n
"
,
hr
,
StreamSinkMarkerTypeMap
.
at
(
eMarkerType
).
c_str
());
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
Flush
(
void
)
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::Flush: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
//IMFMediaEventGenerator
HRESULT
STDMETHODCALLTYPE
GetEvent
(
DWORD
dwFlags
,
IMFMediaEvent
**
ppEvent
)
{
// NOTE:
// GetEvent can block indefinitely, so we don't hold the lock.
// This requires some juggling with the event queue pointer.
HRESULT
hr
=
S_OK
;
_ComPtr
<
IMFMediaEventQueue
>
pQueue
;
{
EnterCriticalSection
(
&
m_critSec
);
// Check shutdown
hr
=
CheckShutdown
();
// Get the pointer to the event queue.
if
(
SUCCEEDED
(
hr
))
{
pQueue
=
m_spEventQueue
.
Get
();
}
LeaveCriticalSection
(
&
m_critSec
);
}
// Now get the event.
if
(
SUCCEEDED
(
hr
))
{
hr
=
pQueue
->
GetEvent
(
dwFlags
,
ppEvent
);
}
MediaEventType
meType
=
MEUnknown
;
if
(
SUCCEEDED
(
hr
)
&&
SUCCEEDED
((
*
ppEvent
)
->
GetType
(
&
meType
))
&&
meType
==
MEStreamSinkStopped
)
{
}
HRESULT
hrStatus
=
S_OK
;
if
(
SUCCEEDED
(
hr
))
hr
=
(
*
ppEvent
)
->
GetStatus
(
&
hrStatus
);
if
(
SUCCEEDED
(
hr
))
DebugPrintOut
(
L"StreamSink::GetEvent: HRESULT=%i %s
\n
"
,
hrStatus
,
MediaEventTypeMap
.
at
(
meType
).
c_str
());
else
DebugPrintOut
(
L"StreamSink::GetEvent: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
BeginGetEvent
(
IMFAsyncCallback
*
pCallback
,
IUnknown
*
punkState
)
{
HRESULT
hr
=
S_OK
;
EnterCriticalSection
(
&
m_critSec
);
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_spEventQueue
->
BeginGetEvent
(
pCallback
,
punkState
);
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::BeginGetEvent: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
EndGetEvent
(
IMFAsyncResult
*
pResult
,
IMFMediaEvent
**
ppEvent
)
{
HRESULT
hr
=
S_OK
;
EnterCriticalSection
(
&
m_critSec
);
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_spEventQueue
->
EndGetEvent
(
pResult
,
ppEvent
);
}
MediaEventType
meType
=
MEUnknown
;
if
(
SUCCEEDED
(
hr
)
&&
SUCCEEDED
((
*
ppEvent
)
->
GetType
(
&
meType
))
&&
meType
==
MEStreamSinkStopped
)
{
}
LeaveCriticalSection
(
&
m_critSec
);
HRESULT
hrStatus
=
S_OK
;
if
(
SUCCEEDED
(
hr
))
hr
=
(
*
ppEvent
)
->
GetStatus
(
&
hrStatus
);
if
(
SUCCEEDED
(
hr
))
DebugPrintOut
(
L"StreamSink::EndGetEvent: HRESULT=%i %s
\n
"
,
hrStatus
,
MediaEventTypeMap
.
at
(
meType
).
c_str
());
else
DebugPrintOut
(
L"StreamSink::EndGetEvent: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
QueueEvent
(
MediaEventType
met
,
REFGUID
guidExtendedType
,
HRESULT
hrStatus
,
const
PROPVARIANT
*
pvValue
)
{
HRESULT
hr
=
S_OK
;
EnterCriticalSection
(
&
m_critSec
);
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_spEventQueue
->
QueueEventParamVar
(
met
,
guidExtendedType
,
hrStatus
,
pvValue
);
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::QueueEvent: HRESULT=%i %s
\n
"
,
hrStatus
,
MediaEventTypeMap
.
at
(
met
).
c_str
());
DebugPrintOut
(
L"StreamSink::QueueEvent: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
/// IMFMediaTypeHandler methods
// Check if a media type is supported.
STDMETHODIMP
IsMediaTypeSupported
(
/* [in] */
IMFMediaType
*
pMediaType
,
/* [out] */
IMFMediaType
**
ppMediaType
)
{
if
(
pMediaType
==
nullptr
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
GUID
majorType
=
GUID_NULL
;
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
hr
=
pMediaType
->
GetGUID
(
MF_MT_MAJOR_TYPE
,
&
majorType
);
}
// First make sure it's video or audio type.
if
(
SUCCEEDED
(
hr
))
{
if
(
majorType
!=
MFMediaType_Video
&&
majorType
!=
MFMediaType_Audio
)
{
hr
=
MF_E_INVALIDTYPE
;
}
}
if
(
SUCCEEDED
(
hr
)
&&
m_spCurrentType
!=
nullptr
)
{
GUID
guiNewSubtype
;
if
(
FAILED
(
pMediaType
->
GetGUID
(
MF_MT_SUBTYPE
,
&
guiNewSubtype
))
||
guiNewSubtype
!=
m_guiCurrentSubtype
)
{
hr
=
MF_E_INVALIDTYPE
;
}
}
// We don't return any "close match" types.
if
(
ppMediaType
)
{
*
ppMediaType
=
nullptr
;
}
if
(
ppMediaType
&&
SUCCEEDED
(
hr
))
{
_ComPtr
<
IMFMediaType
>
pType
;
hr
=
MFCreateMediaType
(
ppMediaType
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_pParent
->
GetUnknown
(
MF_MEDIASINK_PREFERREDTYPE
,
__uuidof
(
IMFMediaType
),
(
LPVOID
*
)
&
pType
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
pType
->
LockStore
();
}
bool
bLocked
=
false
;
if
(
SUCCEEDED
(
hr
))
{
bLocked
=
true
;
UINT32
uiCount
;
UINT32
uiTotal
;
hr
=
pType
->
GetCount
(
&
uiTotal
);
for
(
uiCount
=
0
;
SUCCEEDED
(
hr
)
&&
uiCount
<
uiTotal
;
uiCount
++
)
{
GUID
guid
;
PROPVARIANT
propval
;
hr
=
pType
->
GetItemByIndex
(
uiCount
,
&
guid
,
&
propval
);
if
(
SUCCEEDED
(
hr
)
&&
(
guid
==
MF_MT_FRAME_SIZE
||
guid
==
MF_MT_MAJOR_TYPE
||
guid
==
MF_MT_PIXEL_ASPECT_RATIO
||
guid
==
MF_MT_ALL_SAMPLES_INDEPENDENT
||
guid
==
MF_MT_INTERLACE_MODE
||
guid
==
MF_MT_SUBTYPE
))
{
hr
=
(
*
ppMediaType
)
->
SetItem
(
guid
,
propval
);
PropVariantClear
(
&
propval
);
}
}
}
if
(
bLocked
)
{
hr
=
pType
->
UnlockStore
();
}
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::IsMediaTypeSupported: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
// Return the number of preferred media types.
STDMETHODIMP
GetMediaTypeCount
(
DWORD
*
pdwTypeCount
)
{
if
(
pdwTypeCount
==
nullptr
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
// We've got only one media type
*
pdwTypeCount
=
1
;
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::GetMediaTypeCount: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
// Return a preferred media type by index.
STDMETHODIMP
GetMediaTypeByIndex
(
/* [in] */
DWORD
dwIndex
,
/* [out] */
IMFMediaType
**
ppType
)
{
if
(
ppType
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
dwIndex
>
0
)
{
hr
=
MF_E_NO_MORE_TYPES
;
}
else
{
//return preferred type based on media capture library 6 elements preferred preview type
//hr = m_spCurrentType.CopyTo(ppType);
if
(
SUCCEEDED
(
hr
))
{
_ComPtr
<
IMFMediaType
>
pType
;
hr
=
MFCreateMediaType
(
ppType
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_pParent
->
GetUnknown
(
MF_MEDIASINK_PREFERREDTYPE
,
__uuidof
(
IMFMediaType
),
(
LPVOID
*
)
&
pType
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
pType
->
LockStore
();
}
bool
bLocked
=
false
;
if
(
SUCCEEDED
(
hr
))
{
bLocked
=
true
;
UINT32
uiCount
;
UINT32
uiTotal
;
hr
=
pType
->
GetCount
(
&
uiTotal
);
for
(
uiCount
=
0
;
SUCCEEDED
(
hr
)
&&
uiCount
<
uiTotal
;
uiCount
++
)
{
GUID
guid
;
PROPVARIANT
propval
;
hr
=
pType
->
GetItemByIndex
(
uiCount
,
&
guid
,
&
propval
);
if
(
SUCCEEDED
(
hr
)
&&
(
guid
==
MF_MT_FRAME_SIZE
||
guid
==
MF_MT_MAJOR_TYPE
||
guid
==
MF_MT_PIXEL_ASPECT_RATIO
||
guid
==
MF_MT_ALL_SAMPLES_INDEPENDENT
||
guid
==
MF_MT_INTERLACE_MODE
||
guid
==
MF_MT_SUBTYPE
))
{
hr
=
(
*
ppType
)
->
SetItem
(
guid
,
propval
);
PropVariantClear
(
&
propval
);
}
}
}
if
(
bLocked
)
{
hr
=
pType
->
UnlockStore
();
}
}
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::GetMediaTypeByIndex: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
// Set the current media type.
STDMETHODIMP
SetCurrentMediaType
(
IMFMediaType
*
pMediaType
)
{
if
(
pMediaType
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
S_OK
;
if
(
m_state
!=
State_TypeNotSet
&&
m_state
!=
State_Ready
)
hr
=
MF_E_INVALIDREQUEST
;
if
(
SUCCEEDED
(
hr
))
hr
=
CheckShutdown
();
// We don't allow format changes after streaming starts.
// We set media type already
if
(
m_state
>=
State_Ready
)
{
if
(
SUCCEEDED
(
hr
))
{
hr
=
IsMediaTypeSupported
(
pMediaType
,
NULL
);
}
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
MFCreateMediaType
(
m_spCurrentType
.
ReleaseAndGetAddressOf
());
if
(
SUCCEEDED
(
hr
))
{
hr
=
pMediaType
->
CopyAllItems
(
m_spCurrentType
.
Get
());
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_spCurrentType
->
GetGUID
(
MF_MT_SUBTYPE
,
&
m_guiCurrentSubtype
);
}
GUID
guid
;
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_spCurrentType
->
GetMajorType
(
&
guid
);
}
if
(
SUCCEEDED
(
hr
)
&&
guid
==
MFMediaType_Video
)
{
hr
=
MFGetAttributeSize
(
m_spCurrentType
.
Get
(),
MF_MT_FRAME_SIZE
,
&
m_imageWidthInPixels
,
&
m_imageHeightInPixels
);
}
if
(
SUCCEEDED
(
hr
))
{
m_state
=
State_Ready
;
}
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::SetCurrentMediaType: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
// Return the current media type, if any.
STDMETHODIMP
GetCurrentMediaType
(
IMFMediaType
**
ppMediaType
)
{
if
(
ppMediaType
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
if
(
m_spCurrentType
==
nullptr
)
{
hr
=
MF_E_NOT_INITIALIZED
;
}
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_spCurrentType
.
CopyTo
(
ppMediaType
);
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"StreamSink::GetCurrentMediaType: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
// Return the major type GUID.
STDMETHODIMP
GetMajorType
(
GUID
*
pguidMajorType
)
{
HRESULT
hr
;
if
(
pguidMajorType
==
nullptr
)
{
return
E_INVALIDARG
;
}
_ComPtr
<
IMFMediaType
>
pType
;
hr
=
m_pParent
->
GetUnknown
(
MF_MEDIASINK_PREFERREDTYPE
,
__uuidof
(
IMFMediaType
),
(
LPVOID
*
)
&
pType
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
pType
->
GetMajorType
(
pguidMajorType
);
}
DebugPrintOut
(
L"StreamSink::GetMajorType: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
private
:
bool
m_bConnected
;
bool
m_IsShutdown
;
// Flag to indicate if Shutdown() method was called.
CRITICAL_SECTION
m_critSec
;
long
m_cRef
;
IMFAttributes
*
m_pParent
;
_ComPtr
<
IMFMediaType
>
m_spCurrentType
;
_ComPtr
<
IMFMediaEventQueue
>
m_spEventQueue
;
// Event queue
_ComPtr
<
IUnknown
>
m_spFTM
;
State
m_state
;
bool
m_fGetStartTimeFromSample
;
bool
m_fWaitingForFirstSample
;
MFTIME
m_StartTime
;
// Presentation time when the clock started.
GUID
m_guiCurrentSubtype
;
UINT32
m_imageWidthInPixels
;
UINT32
m_imageHeightInPixels
;
};
// 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
;
}
assert
(
pNode
!=
&
m_anchor
);
// We should never try to remove the anchor node.
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
typename
List
<
T
*>::
Node
Node
;
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
))
{
assert
(
pItem
||
NULLABLE
);
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
))
{
assert
(
pItem
||
NULLABLE
);
if
(
ppItem
&&
pItem
)
{
*
ppItem
=
pItem
;
(
*
ppItem
)
->
AddRef
();
}
if
(
pItem
)
{
pItem
->
Release
();
pItem
=
nullptr
;
}
}
return
hr
;
}
};
extern
const
__declspec
(
selectany
)
WCHAR
RuntimeClass_CV_MediaSink
[]
=
L"cv.MediaSink"
;
class
MediaSink
:
public
IMFMediaSink
,
public
IMFClockStateSink
,
public
CBaseAttributes
<>
{
public
:
ULONG
STDMETHODCALLTYPE
AddRef
()
{
return
InterlockedIncrement
(
&
m_cRef
);
}
ULONG
STDMETHODCALLTYPE
Release
()
{
ULONG
cRef
=
InterlockedDecrement
(
&
m_cRef
);
if
(
cRef
==
0
)
{
delete
this
;
}
return
cRef
;
}
#if defined(_MSC_VER) && _MSC_VER >= 1700 // '_Outptr_result_nullonfailure_' SAL is avaialable since VS 2012
STDMETHOD
(
QueryInterface
)(
REFIID
riid
,
_Outptr_result_nullonfailure_
void
**
ppv
)
#else
STDMETHOD
(
QueryInterface
)(
REFIID
riid
,
void
**
ppv
)
#endif
{
if
(
ppv
==
nullptr
)
{
return
E_POINTER
;
}
(
*
ppv
)
=
nullptr
;
HRESULT
hr
=
S_OK
;
if
(
riid
==
IID_IUnknown
||
riid
==
IID_IMFMediaSink
)
{
(
*
ppv
)
=
static_cast
<
IMFMediaSink
*>
(
this
);
AddRef
();
}
else
if
(
riid
==
IID_IMFClockStateSink
)
{
(
*
ppv
)
=
static_cast
<
IMFClockStateSink
*>
(
this
);
AddRef
();
}
else
if
(
riid
==
IID_IMFAttributes
)
{
(
*
ppv
)
=
static_cast
<
IMFAttributes
*>
(
this
);
AddRef
();
}
else
{
hr
=
E_NOINTERFACE
;
}
return
hr
;
}
MediaSink
()
:
m_IsShutdown
(
false
),
m_llStartTime
(
0
)
{
CBaseAttributes
<>::
Initialize
(
0U
);
InitializeCriticalSectionEx
(
&
m_critSec
,
3000
,
0
);
DebugPrintOut
(
L"MediaSink::MediaSink
\n
"
);
}
virtual
~
MediaSink
()
{
DebugPrintOut
(
L"MediaSink::~MediaSink
\n
"
);
DeleteCriticalSection
(
&
m_critSec
);
assert
(
m_IsShutdown
);
}
HRESULT
CheckShutdown
()
const
{
if
(
m_IsShutdown
)
{
return
MF_E_SHUTDOWN
;
}
else
{
return
S_OK
;
}
}
//IMFMediaSink
HRESULT
STDMETHODCALLTYPE
GetCharacteristics
(
/* [out] */
__RPC__out
DWORD
*
pdwCharacteristics
)
{
HRESULT
hr
;
if
(
pdwCharacteristics
==
NULL
)
return
E_INVALIDARG
;
EnterCriticalSection
(
&
m_critSec
);
if
(
SUCCEEDED
(
hr
=
CheckShutdown
()))
{
//if had an activation object for the sink, shut down would be managed and MF_STREAM_SINK_SUPPORTS_ROTATION appears to be setable to TRUE
*
pdwCharacteristics
=
MEDIASINK_FIXED_STREAMS
;
// | MEDIASINK_REQUIRE_REFERENCE_MEDIATYPE;
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::GetCharacteristics: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
AddStreamSink
(
DWORD
dwStreamSinkIdentifier
,
IMFMediaType
*
/*pMediaType*/
,
IMFStreamSink
**
ppStreamSink
)
{
_ComPtr
<
IMFStreamSink
>
spMFStream
;
_ComPtr
<
ICustomStreamSink
>
pStream
;
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
hr
=
GetStreamSinkById
(
dwStreamSinkIdentifier
,
&
spMFStream
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
MF_E_STREAMSINK_EXISTS
;
}
else
{
hr
=
S_OK
;
}
if
(
SUCCEEDED
(
hr
))
{
StreamSink
*
pSink
=
new
StreamSink
();
if
(
pSink
)
{
hr
=
pSink
->
QueryInterface
(
IID_IMFStreamSink
,
(
void
**
)
spMFStream
.
GetAddressOf
());
if
(
SUCCEEDED
(
hr
))
{
hr
=
spMFStream
.
As
(
&
pStream
);
}
if
(
FAILED
(
hr
))
delete
pSink
;
}
}
// Initialize the stream.
_ComPtr
<
IMFAttributes
>
pAttr
;
if
(
SUCCEEDED
(
hr
))
{
hr
=
pStream
.
As
(
&
pAttr
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
pAttr
->
SetUINT32
(
MF_STREAMSINK_ID
,
dwStreamSinkIdentifier
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
pAttr
->
SetUnknown
(
MF_STREAMSINK_MEDIASINKINTERFACE
,
(
IMFMediaSink
*
)
this
);
}
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
pStream
->
Initialize
();
}
if
(
SUCCEEDED
(
hr
))
{
ComPtrList
<
IMFStreamSink
>::
POSITION
pos
=
m_streams
.
FrontPosition
();
ComPtrList
<
IMFStreamSink
>::
POSITION
posEnd
=
m_streams
.
EndPosition
();
// Insert in proper position
for
(;
pos
!=
posEnd
;
pos
=
m_streams
.
Next
(
pos
))
{
DWORD
dwCurrId
;
_ComPtr
<
IMFStreamSink
>
spCurr
;
hr
=
m_streams
.
GetItemPos
(
pos
,
&
spCurr
);
if
(
FAILED
(
hr
))
{
break
;
}
hr
=
spCurr
->
GetIdentifier
(
&
dwCurrId
);
if
(
FAILED
(
hr
))
{
break
;
}
if
(
dwCurrId
>
dwStreamSinkIdentifier
)
{
break
;
}
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_streams
.
InsertPos
(
pos
,
spMFStream
.
Get
());
}
}
if
(
SUCCEEDED
(
hr
))
{
*
ppStreamSink
=
spMFStream
.
Detach
();
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::AddStreamSink: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
RemoveStreamSink
(
DWORD
dwStreamSinkIdentifier
)
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
ComPtrList
<
IMFStreamSink
>::
POSITION
pos
=
m_streams
.
FrontPosition
();
ComPtrList
<
IMFStreamSink
>::
POSITION
endPos
=
m_streams
.
EndPosition
();
_ComPtr
<
IMFStreamSink
>
spStream
;
if
(
SUCCEEDED
(
hr
))
{
for
(;
pos
!=
endPos
;
pos
=
m_streams
.
Next
(
pos
))
{
hr
=
m_streams
.
GetItemPos
(
pos
,
&
spStream
);
DWORD
dwId
;
if
(
FAILED
(
hr
))
{
break
;
}
hr
=
spStream
->
GetIdentifier
(
&
dwId
);
if
(
FAILED
(
hr
)
||
dwId
==
dwStreamSinkIdentifier
)
{
break
;
}
}
if
(
pos
==
endPos
)
{
hr
=
MF_E_INVALIDSTREAMNUMBER
;
}
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
m_streams
.
Remove
(
pos
,
nullptr
);
_ComPtr
<
ICustomStreamSink
>
spCustomSink
;
hr
=
spStream
.
As
(
&
spCustomSink
);
if
(
SUCCEEDED
(
hr
))
hr
=
spCustomSink
->
Shutdown
();
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::RemoveStreamSink: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
GetStreamSinkCount
(
DWORD
*
pStreamSinkCount
)
{
if
(
pStreamSinkCount
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
*
pStreamSinkCount
=
m_streams
.
GetCount
();
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::GetStreamSinkCount: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
GetStreamSinkByIndex
(
DWORD
dwIndex
,
IMFStreamSink
**
ppStreamSink
)
{
if
(
ppStreamSink
==
NULL
)
{
return
E_INVALIDARG
;
}
_ComPtr
<
IMFStreamSink
>
spStream
;
EnterCriticalSection
(
&
m_critSec
);
DWORD
cStreams
=
m_streams
.
GetCount
();
if
(
dwIndex
>=
cStreams
)
{
return
MF_E_INVALIDINDEX
;
}
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
ComPtrList
<
IMFStreamSink
>::
POSITION
pos
=
m_streams
.
FrontPosition
();
ComPtrList
<
IMFStreamSink
>::
POSITION
endPos
=
m_streams
.
EndPosition
();
DWORD
dwCurrent
=
0
;
for
(;
pos
!=
endPos
&&
dwCurrent
<
dwIndex
;
pos
=
m_streams
.
Next
(
pos
),
++
dwCurrent
)
{
// Just move to proper position
}
if
(
pos
==
endPos
)
{
hr
=
MF_E_UNEXPECTED
;
}
else
{
hr
=
m_streams
.
GetItemPos
(
pos
,
&
spStream
);
}
}
if
(
SUCCEEDED
(
hr
))
{
*
ppStreamSink
=
spStream
.
Detach
();
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::GetStreamSinkByIndex: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
GetStreamSinkById
(
DWORD
dwStreamSinkIdentifier
,
IMFStreamSink
**
ppStreamSink
)
{
if
(
ppStreamSink
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
_ComPtr
<
IMFStreamSink
>
spResult
;
if
(
SUCCEEDED
(
hr
))
{
ComPtrList
<
IMFStreamSink
>::
POSITION
pos
=
m_streams
.
FrontPosition
();
ComPtrList
<
IMFStreamSink
>::
POSITION
endPos
=
m_streams
.
EndPosition
();
for
(;
pos
!=
endPos
;
pos
=
m_streams
.
Next
(
pos
))
{
_ComPtr
<
IMFStreamSink
>
spStream
;
hr
=
m_streams
.
GetItemPos
(
pos
,
&
spStream
);
DWORD
dwId
;
if
(
FAILED
(
hr
))
{
break
;
}
hr
=
spStream
->
GetIdentifier
(
&
dwId
);
if
(
FAILED
(
hr
))
{
break
;
}
else
if
(
dwId
==
dwStreamSinkIdentifier
)
{
spResult
=
spStream
;
break
;
}
}
if
(
pos
==
endPos
)
{
hr
=
MF_E_INVALIDSTREAMNUMBER
;
}
}
if
(
SUCCEEDED
(
hr
))
{
assert
(
spResult
);
*
ppStreamSink
=
spResult
.
Detach
();
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::GetStreamSinkById: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
SetPresentationClock
(
IMFPresentationClock
*
pPresentationClock
)
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
// If we already have a clock, remove ourselves from that clock's
// state notifications.
if
(
SUCCEEDED
(
hr
))
{
if
(
m_spClock
)
{
hr
=
m_spClock
->
RemoveClockStateSink
(
this
);
}
}
// Register ourselves to get state notifications from the new clock.
if
(
SUCCEEDED
(
hr
))
{
if
(
pPresentationClock
)
{
hr
=
pPresentationClock
->
AddClockStateSink
(
this
);
}
}
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
if
(
SUCCEEDED
(
hr
))
{
// Release the pointer to the old clock.
// Store the pointer to the new clock.
m_spClock
=
pPresentationClock
;
hr
=
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
}
LeaveCriticalSection
(
&
m_critSec
);
if
(
SUCCEEDED
(
hr
))
hr
=
pSampleCallback
->
OnSetPresentationClock
(
pPresentationClock
);
DebugPrintOut
(
L"MediaSink::SetPresentationClock: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
GetPresentationClock
(
IMFPresentationClock
**
ppPresentationClock
)
{
if
(
ppPresentationClock
==
NULL
)
{
return
E_INVALIDARG
;
}
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
if
(
!
m_spClock
)
{
hr
=
MF_E_NO_CLOCK
;
// There is no presentation clock.
}
else
{
// Return the pointer to the caller.
hr
=
m_spClock
.
CopyTo
(
ppPresentationClock
);
}
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::GetPresentationClock: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
Shutdown
(
void
)
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
ForEach
(
m_streams
,
ShutdownFunc
());
m_streams
.
Clear
();
m_spClock
.
ReleaseAndGetAddressOf
();
_ComPtr
<
IMFMediaType
>
pType
;
hr
=
CBaseAttributes
<>::
GetUnknown
(
MF_MEDIASINK_PREFERREDTYPE
,
__uuidof
(
IMFMediaType
),
(
LPVOID
*
)
pType
.
GetAddressOf
());
if
(
SUCCEEDED
(
hr
))
{
hr
=
DeleteItem
(
MF_MEDIASINK_PREFERREDTYPE
);
}
m_IsShutdown
=
true
;
}
LeaveCriticalSection
(
&
m_critSec
);
DebugPrintOut
(
L"MediaSink::Shutdown: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
class
ShutdownFunc
{
public
:
HRESULT
operator
()(
IMFStreamSink
*
pStream
)
const
{
_ComPtr
<
ICustomStreamSink
>
spCustomSink
;
HRESULT
hr
;
hr
=
pStream
->
QueryInterface
(
IID_PPV_ARGS
(
spCustomSink
.
GetAddressOf
()));
if
(
FAILED
(
hr
))
return
hr
;
hr
=
spCustomSink
->
Shutdown
();
return
hr
;
}
};
class
StartFunc
{
public
:
StartFunc
(
LONGLONG
llStartTime
)
:
_llStartTime
(
llStartTime
)
{
}
HRESULT
operator
()(
IMFStreamSink
*
pStream
)
const
{
_ComPtr
<
ICustomStreamSink
>
spCustomSink
;
HRESULT
hr
;
hr
=
pStream
->
QueryInterface
(
IID_PPV_ARGS
(
spCustomSink
.
GetAddressOf
()));
if
(
FAILED
(
hr
))
return
hr
;
hr
=
spCustomSink
->
Start
(
_llStartTime
);
return
hr
;
}
LONGLONG
_llStartTime
;
};
class
StopFunc
{
public
:
HRESULT
operator
()(
IMFStreamSink
*
pStream
)
const
{
_ComPtr
<
ICustomStreamSink
>
spCustomSink
;
HRESULT
hr
;
hr
=
pStream
->
QueryInterface
(
IID_PPV_ARGS
(
spCustomSink
.
GetAddressOf
()));
if
(
FAILED
(
hr
))
return
hr
;
hr
=
spCustomSink
->
Stop
();
return
hr
;
}
};
template
<
class
T
,
class
TFunc
>
HRESULT
ForEach
(
ComPtrList
<
T
>
&
col
,
TFunc
fn
)
{
ComPtrList
<
T
>::
POSITION
pos
=
col
.
FrontPosition
();
ComPtrList
<
T
>::
POSITION
endPos
=
col
.
EndPosition
();
HRESULT
hr
=
S_OK
;
for
(;
pos
!=
endPos
;
pos
=
col
.
Next
(
pos
))
{
_ComPtr
<
T
>
spStream
;
hr
=
col
.
GetItemPos
(
pos
,
&
spStream
);
if
(
FAILED
(
hr
))
{
break
;
}
hr
=
fn
(
spStream
.
Get
());
}
return
hr
;
}
//IMFClockStateSink
HRESULT
STDMETHODCALLTYPE
OnClockStart
(
MFTIME
hnsSystemTime
,
LONGLONG
llClockStartOffset
)
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
// Start each stream.
m_llStartTime
=
llClockStartOffset
;
hr
=
ForEach
(
m_streams
,
StartFunc
(
llClockStartOffset
));
}
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
if
(
SUCCEEDED
(
hr
))
hr
=
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
LeaveCriticalSection
(
&
m_critSec
);
if
(
SUCCEEDED
(
hr
))
hr
=
pSampleCallback
->
OnClockStart
(
hnsSystemTime
,
llClockStartOffset
);
DebugPrintOut
(
L"MediaSink::OnClockStart: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
OnClockStop
(
MFTIME
hnsSystemTime
)
{
EnterCriticalSection
(
&
m_critSec
);
HRESULT
hr
=
CheckShutdown
();
if
(
SUCCEEDED
(
hr
))
{
// Stop each stream
hr
=
ForEach
(
m_streams
,
StopFunc
());
}
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
if
(
SUCCEEDED
(
hr
))
hr
=
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
LeaveCriticalSection
(
&
m_critSec
);
if
(
SUCCEEDED
(
hr
))
hr
=
pSampleCallback
->
OnClockStop
(
hnsSystemTime
);
DebugPrintOut
(
L"MediaSink::OnClockStop: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
OnClockPause
(
MFTIME
hnsSystemTime
)
{
HRESULT
hr
;
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
hr
=
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
if
(
SUCCEEDED
(
hr
))
hr
=
pSampleCallback
->
OnClockPause
(
hnsSystemTime
);
DebugPrintOut
(
L"MediaSink::OnClockPause: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
OnClockRestart
(
MFTIME
hnsSystemTime
)
{
HRESULT
hr
;
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
hr
=
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
if
(
SUCCEEDED
(
hr
))
hr
=
pSampleCallback
->
OnClockRestart
(
hnsSystemTime
);
DebugPrintOut
(
L"MediaSink::OnClockRestart: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
HRESULT
STDMETHODCALLTYPE
OnClockSetRate
(
MFTIME
hnsSystemTime
,
float
flRate
)
{
HRESULT
hr
;
_ComPtr
<
IMFSampleGrabberSinkCallback
>
pSampleCallback
;
hr
=
GetUnknown
(
MF_MEDIASINK_SAMPLEGRABBERCALLBACK
,
IID_IMFSampleGrabberSinkCallback
,
(
LPVOID
*
)
pSampleCallback
.
GetAddressOf
());
if
(
SUCCEEDED
(
hr
))
hr
=
pSampleCallback
->
OnClockSetRate
(
hnsSystemTime
,
flRate
);
DebugPrintOut
(
L"MediaSink::OnClockSetRate: HRESULT=%i
\n
"
,
hr
);
return
hr
;
}
private
:
long
m_cRef
;
CRITICAL_SECTION
m_critSec
;
bool
m_IsShutdown
;
ComPtrList
<
IMFStreamSink
>
m_streams
;
_ComPtr
<
IMFPresentationClock
>
m_spClock
;
LONGLONG
m_llStartTime
;
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment