summaryrefslogtreecommitdiffstats
path: root/plugins/pluginWinMF/plugin_win_mf_producer_video.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pluginWinMF/plugin_win_mf_producer_video.cxx')
-rwxr-xr-xplugins/pluginWinMF/plugin_win_mf_producer_video.cxx1131
1 files changed, 553 insertions, 578 deletions
diff --git a/plugins/pluginWinMF/plugin_win_mf_producer_video.cxx b/plugins/pluginWinMF/plugin_win_mf_producer_video.cxx
index f20f9e4..e4bf690 100755
--- a/plugins/pluginWinMF/plugin_win_mf_producer_video.cxx
+++ b/plugins/pluginWinMF/plugin_win_mf_producer_video.cxx
@@ -50,7 +50,7 @@
#endif /* PLUGIN_MF_GOP_SIZE_IN_SECONDS */
DEFINE_GUID(PLUGIN_MF_LOW_LATENCY,
- 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee);
+ 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee);
extern const tmedia_codec_plugin_def_t *mf_codec_h264_main_plugin_def_t;
extern const tmedia_codec_plugin_def_t *mf_codec_h264_base_plugin_def_t;
@@ -61,548 +61,527 @@ static int _plugin_win_mf_producer_video_unprepare(struct plugin_win_mf_producer
//
// plugin_win_mf_producer_video_t
//
-typedef struct plugin_win_mf_producer_video_s
-{
- TMEDIA_DECLARE_PRODUCER;
-
- bool bStarted, bPrepared, bMuted;
- tsk_thread_handle_t* ppTread[1];
- HWND hWndPreview;
-
- int32_t bitrate_bps; // used when encoder bundled only
-
- DeviceListVideo* pDeviceList;
-
- MFCodecVideo *pEncoder;
- IMFMediaSession *pSession;
- IMFMediaSource *pSource;
- SampleGrabberCB *pCallback;
- IMFActivate *pSinkGrabber;
- IMFActivate *pSinkActivatePreview;
- DisplayWatcher* pWatcherPreview;
- IMFTopology *pTopology;
- IMFMediaType *pGrabberInputType;
+typedef struct plugin_win_mf_producer_video_s {
+ TMEDIA_DECLARE_PRODUCER;
+
+ bool bStarted, bPrepared, bMuted;
+ tsk_thread_handle_t* ppTread[1];
+ HWND hWndPreview;
+
+ int32_t bitrate_bps; // used when encoder bundled only
+
+ DeviceListVideo* pDeviceList;
+
+ MFCodecVideo *pEncoder;
+ IMFMediaSession *pSession;
+ IMFMediaSource *pSource;
+ SampleGrabberCB *pCallback;
+ IMFActivate *pSinkGrabber;
+ IMFActivate *pSinkActivatePreview;
+ DisplayWatcher* pWatcherPreview;
+ IMFTopology *pTopology;
+ IMFMediaType *pGrabberInputType;
}
plugin_win_mf_producer_video_t;
/* ============ Video MF Producer Interface ================= */
static int plugin_win_mf_producer_video_set(tmedia_producer_t *self, const tmedia_param_t* param)
{
- int ret = 0;
- HRESULT hr = S_OK;
- plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
-
- if (!pSelf || !param){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if (tsk_striequals(param->key, "action")){
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- HRESULT hr = S_OK;
- switch (action){
- case tmedia_codec_action_encode_idr:
- {
- if (pSelf->pEncoder)
- {
- CHECK_HR(hr = pSelf->pEncoder->RequestKeyFrame());
- }
- break;
- }
- case tmedia_codec_action_bw_down:
- {
- pSelf->bitrate_bps = TSK_CLAMP(0, (int32_t)((pSelf->bitrate_bps << 1) / 3), TMEDIA_CODEC(pSelf)->bandwidth_max_upload);
- TSK_DEBUG_INFO("New target bitrate = %d kbps", pSelf->bitrate_bps);
- if (pSelf->pEncoder)
- {
- CHECK_HR(hr = pSelf->pEncoder->SetBitRate(pSelf->bitrate_bps));
- }
- break;
- }
- case tmedia_codec_action_bw_up:
- {
- pSelf->bitrate_bps = TSK_CLAMP(0, (int32_t)((pSelf->bitrate_bps * 3) >> 1), TMEDIA_CODEC(pSelf)->bandwidth_max_upload);
- TSK_DEBUG_INFO("New target bitrate = %d kbps", pSelf->bitrate_bps);
- if (pSelf->pEncoder)
- {
- CHECK_HR(hr = pSelf->pEncoder->SetBitRate(pSelf->bitrate_bps));
- }
- break;
- }
- }
- }
- else if (param->value_type == tmedia_pvt_int64){
- if (tsk_striequals(param->key, "local-hwnd")){
- HWND hWnd = reinterpret_cast<HWND>((INT64)*((int64_t*)param->value));
- if (hWnd != pSelf->hWndPreview)
- {
- pSelf->hWndPreview = hWnd;
- if (pSelf->pWatcherPreview)
- {
- CHECK_HR(hr = pSelf->pWatcherPreview->SetHwnd(hWnd));
- }
- }
- }
- }
- else if (param->value_type == tmedia_pvt_int32){
- if (tsk_striequals(param->key, "mute")){
- pSelf->bMuted = (TSK_TO_INT32((uint8_t*)param->value) != 0);
- if (pSelf->pCallback) {
- pSelf->pCallback->SetMute(pSelf->bMuted);
- }
+ int ret = 0;
+ HRESULT hr = S_OK;
+ plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
+
+ if (!pSelf || !param) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ HRESULT hr = S_OK;
+ switch (action) {
+ case tmedia_codec_action_encode_idr: {
+ if (pSelf->pEncoder) {
+ CHECK_HR(hr = pSelf->pEncoder->RequestKeyFrame());
+ }
+ break;
+ }
+ case tmedia_codec_action_bw_down: {
+ pSelf->bitrate_bps = TSK_CLAMP(0, (int32_t)((pSelf->bitrate_bps << 1) / 3), TMEDIA_CODEC(pSelf)->bandwidth_max_upload);
+ TSK_DEBUG_INFO("New target bitrate = %d kbps", pSelf->bitrate_bps);
+ if (pSelf->pEncoder) {
+ CHECK_HR(hr = pSelf->pEncoder->SetBitRate(pSelf->bitrate_bps));
+ }
+ break;
+ }
+ case tmedia_codec_action_bw_up: {
+ pSelf->bitrate_bps = TSK_CLAMP(0, (int32_t)((pSelf->bitrate_bps * 3) >> 1), TMEDIA_CODEC(pSelf)->bandwidth_max_upload);
+ TSK_DEBUG_INFO("New target bitrate = %d kbps", pSelf->bitrate_bps);
+ if (pSelf->pEncoder) {
+ CHECK_HR(hr = pSelf->pEncoder->SetBitRate(pSelf->bitrate_bps));
+ }
+ break;
+ }
+ }
+ }
+ else if (param->value_type == tmedia_pvt_int64) {
+ if (tsk_striequals(param->key, "local-hwnd")) {
+ HWND hWnd = reinterpret_cast<HWND>((INT64)*((int64_t*)param->value));
+ if (hWnd != pSelf->hWndPreview) {
+ pSelf->hWndPreview = hWnd;
+ if (pSelf->pWatcherPreview) {
+ CHECK_HR(hr = pSelf->pWatcherPreview->SetHwnd(hWnd));
+ }
+ }
+ }
+ }
+ else if (param->value_type == tmedia_pvt_int32) {
+ if (tsk_striequals(param->key, "mute")) {
+ pSelf->bMuted = (TSK_TO_INT32((uint8_t*)param->value) != 0);
+ if (pSelf->pCallback) {
+ pSelf->pCallback->SetMute(pSelf->bMuted);
+ }
#if 0
- if (pSelf->bStarted && pSelf->pSession) {
- if (pSelf->bMuted) {
- pSelf->pSession->Pause();
- }
- else {
- CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopology));
- }
- }
+ if (pSelf->bStarted && pSelf->pSession) {
+ if (pSelf->bMuted) {
+ pSelf->pSession->Pause();
+ }
+ else {
+ CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopology));
+ }
+ }
#endif
- }
- else if (tsk_striequals(param->key, "create-on-current-thead")){
- //producer->create_on_ui_thread = *((int32_t*)param->value) ? tsk_false : tsk_true;
- }
- else if (tsk_striequals(param->key, "plugin-firefox")){
- //producer->plugin_firefox = (*((int32_t*)param->value) != 0);
- //if(producer->grabber){
- // producer->grabber->setPluginFirefox((producer->plugin_firefox == tsk_true));
- //}
- }
- }
+ }
+ else if (tsk_striequals(param->key, "create-on-current-thead")) {
+ //producer->create_on_ui_thread = *((int32_t*)param->value) ? tsk_false : tsk_true;
+ }
+ else if (tsk_striequals(param->key, "plugin-firefox")) {
+ //producer->plugin_firefox = (*((int32_t*)param->value) != 0);
+ //if(producer->grabber){
+ // producer->grabber->setPluginFirefox((producer->plugin_firefox == tsk_true));
+ //}
+ }
+ }
bail:
- return SUCCEEDED(hr) ? 0 : -1;
+ return SUCCEEDED(hr) ? 0 : -1;
}
static int plugin_win_mf_producer_video_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
{
- plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
-
- if (!pSelf || !codec && codec->plugin){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- if (pSelf->bPrepared){
- TSK_DEBUG_WARN("MF video producer already prepared");
- return -1;
- }
-
- // FIXME: DirectShow requires flipping but not MF
- // The Core library always tries to flip when OSType==Win32. Must be changed
- TMEDIA_CODEC_VIDEO(codec)->out.flip = tsk_false;
-
- TMEDIA_PRODUCER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps;
- TMEDIA_PRODUCER(pSelf)->video.width = TMEDIA_CODEC_VIDEO(codec)->out.width;
- TMEDIA_PRODUCER(pSelf)->video.height = TMEDIA_CODEC_VIDEO(codec)->out.height;
- TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input
-
- TSK_DEBUG_INFO("MF video producer: fps=%d, width=%d, height=%d",
- TMEDIA_PRODUCER(pSelf)->video.fps,
- TMEDIA_PRODUCER(pSelf)->video.width,
- TMEDIA_PRODUCER(pSelf)->video.height);
-
- HRESULT hr = S_OK;
- IMFAttributes* pSessionAttributes = NULL;
- IMFTopology *pTopology = NULL;
- IMFMediaSink* pEvr = NULL;
- IMFMediaType* pEncoderInputType = NULL;
- IMFTopologyNode *pNodeGrabber = NULL;
- IMFMediaType* pGrabberNegotiatedInputMedia = NULL;
- BOOL bVideoProcessorIsSupported = FALSE;
- const VideoSubTypeGuidPair *pcPreferredSubTypeGuidPair = NULL;
-
- // create device list object
- if (!pSelf->pDeviceList && !(pSelf->pDeviceList = new DeviceListVideo())){
- TSK_DEBUG_ERROR("Failed to create device list");
- hr = E_OUTOFMEMORY;
- goto bail;
- }
- // enumerate devices
- hr = pSelf->pDeviceList->EnumerateDevices();
- if (!SUCCEEDED(hr)){
- goto bail;
- }
-
- // check if we have at least one MF video source connected to the PC
- if (pSelf->pDeviceList->Count() == 0){
- TSK_DEBUG_WARN("No MF video source could be found...no video will be sent");
- // do not break the negotiation as one-way video connection is a valid use-case
- }
- else{
- // Get best MF video source
- IMFActivate* pActivate = NULL;
- const char* pczSrcFriendlyName = tmedia_producer_get_friendly_name(tmedia_video);
- if (!tsk_strnullORempty(pczSrcFriendlyName)) {
- TSK_DEBUG_INFO("MF pref. video source = %s", pczSrcFriendlyName);
- wchar_t pczwSrcFriendlyName[MAX_PATH] = { 0 };
- mbstowcs(pczwSrcFriendlyName, pczSrcFriendlyName, sizeof(pczwSrcFriendlyName) / sizeof(pczwSrcFriendlyName[0]));
- hr = pSelf->pDeviceList->GetDeviceBest(&pActivate, pczwSrcFriendlyName);
- }
- else {
- hr = pSelf->pDeviceList->GetDeviceBest(&pActivate);
- }
- if (!SUCCEEDED(hr) || !pActivate){
- TSK_DEBUG_ERROR("Failed to get best MF video source");
- if (!pActivate){
- hr = E_OUTOFMEMORY;
- }
- goto bail;
- }
-
- // Create the media source for the device.
- hr = pActivate->ActivateObject(
- __uuidof(IMFMediaSource),
- (void**)&pSelf->pSource
- );
- SafeRelease(&pActivate);
- if (!SUCCEEDED(hr)){
- TSK_DEBUG_ERROR("ActivateObject(MF video source) failed");
- goto bail;
- }
-
- // Check whether video processor (http://msdn.microsoft.com/en-us/library/windows/desktop/hh162913(v=vs.85).aspx) is supported
- CHECK_HR(hr = MFUtils::IsVideoProcessorSupported(&bVideoProcessorIsSupported));
-
- // Must not be set because not supported by Frame Rate Converter DSP (http://msdn.microsoft.com/en-us/library/windows/desktop/ff819100(v=vs.85).aspx).aspx) because of color (neither I420 nor NV12)
- // Video Processor (http://msdn.microsoft.com/en-us/library/windows/desktop/hh162913(v=vs.85).aspx) supports both NV12 and I420
- if (!bVideoProcessorIsSupported) {
- UINT32 nWidth, nHeight, nFps;
- hr = MFUtils::GetBestFormat(
- pSelf->pSource,
- &MFVideoFormat_I420,
- (UINT32)TMEDIA_PRODUCER(pSelf)->video.width,
- (UINT32)TMEDIA_PRODUCER(pSelf)->video.height,
- (UINT32)TMEDIA_PRODUCER(pSelf)->video.fps,
- &nWidth,
- &nHeight,
- &nFps,
- &pcPreferredSubTypeGuidPair
- );
- if (SUCCEEDED(hr))
- {
- TSK_DEBUG_INFO("Video processor not supported...using source fps=%u, width=%u, height=%u", nFps, nWidth, nHeight);
- TMEDIA_PRODUCER(pSelf)->video.width = nWidth;
- TMEDIA_PRODUCER(pSelf)->video.height = nHeight;
- TMEDIA_PRODUCER(pSelf)->video.fps = nFps;
- }
- }
-
- // If H.264 is negotiated for this session then, try to find hardware encoder
- // If no HW encoder is found will fallback to SW implementation from x264
+ plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
+
+ if (!pSelf || !codec && codec->plugin) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (pSelf->bPrepared) {
+ TSK_DEBUG_WARN("MF video producer already prepared");
+ return -1;
+ }
+
+ // FIXME: DirectShow requires flipping but not MF
+ // The Core library always tries to flip when OSType==Win32. Must be changed
+ TMEDIA_CODEC_VIDEO(codec)->out.flip = tsk_false;
+
+ TMEDIA_PRODUCER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps;
+ TMEDIA_PRODUCER(pSelf)->video.width = TMEDIA_CODEC_VIDEO(codec)->out.width;
+ TMEDIA_PRODUCER(pSelf)->video.height = TMEDIA_CODEC_VIDEO(codec)->out.height;
+ TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input
+
+ TSK_DEBUG_INFO("MF video producer: fps=%d, width=%d, height=%d",
+ TMEDIA_PRODUCER(pSelf)->video.fps,
+ TMEDIA_PRODUCER(pSelf)->video.width,
+ TMEDIA_PRODUCER(pSelf)->video.height);
+
+ HRESULT hr = S_OK;
+ IMFAttributes* pSessionAttributes = NULL;
+ IMFTopology *pTopology = NULL;
+ IMFMediaSink* pEvr = NULL;
+ IMFMediaType* pEncoderInputType = NULL;
+ IMFTopologyNode *pNodeGrabber = NULL;
+ IMFMediaType* pGrabberNegotiatedInputMedia = NULL;
+ BOOL bVideoProcessorIsSupported = FALSE;
+ const VideoSubTypeGuidPair *pcPreferredSubTypeGuidPair = NULL;
+
+ // create device list object
+ if (!pSelf->pDeviceList && !(pSelf->pDeviceList = new DeviceListVideo())) {
+ TSK_DEBUG_ERROR("Failed to create device list");
+ hr = E_OUTOFMEMORY;
+ goto bail;
+ }
+ // enumerate devices
+ hr = pSelf->pDeviceList->EnumerateDevices();
+ if (!SUCCEEDED(hr)) {
+ goto bail;
+ }
+
+ // check if we have at least one MF video source connected to the PC
+ if (pSelf->pDeviceList->Count() == 0) {
+ TSK_DEBUG_WARN("No MF video source could be found...no video will be sent");
+ // do not break the negotiation as one-way video connection is a valid use-case
+ }
+ else {
+ // Get best MF video source
+ IMFActivate* pActivate = NULL;
+ const char* pczSrcFriendlyName = tmedia_producer_get_friendly_name(tmedia_video);
+ if (!tsk_strnullORempty(pczSrcFriendlyName)) {
+ TSK_DEBUG_INFO("MF pref. video source = %s", pczSrcFriendlyName);
+ wchar_t pczwSrcFriendlyName[MAX_PATH] = { 0 };
+ mbstowcs(pczwSrcFriendlyName, pczSrcFriendlyName, sizeof(pczwSrcFriendlyName) / sizeof(pczwSrcFriendlyName[0]));
+ hr = pSelf->pDeviceList->GetDeviceBest(&pActivate, pczwSrcFriendlyName);
+ }
+ else {
+ hr = pSelf->pDeviceList->GetDeviceBest(&pActivate);
+ }
+ if (!SUCCEEDED(hr) || !pActivate) {
+ TSK_DEBUG_ERROR("Failed to get best MF video source");
+ if (!pActivate) {
+ hr = E_OUTOFMEMORY;
+ }
+ goto bail;
+ }
+
+ // Create the media source for the device.
+ hr = pActivate->ActivateObject(
+ __uuidof(IMFMediaSource),
+ (void**)&pSelf->pSource
+ );
+ SafeRelease(&pActivate);
+ if (!SUCCEEDED(hr)) {
+ TSK_DEBUG_ERROR("ActivateObject(MF video source) failed");
+ goto bail;
+ }
+
+ // Check whether video processor (http://msdn.microsoft.com/en-us/library/windows/desktop/hh162913(v=vs.85).aspx) is supported
+ CHECK_HR(hr = MFUtils::IsVideoProcessorSupported(&bVideoProcessorIsSupported));
+
+ // Must not be set because not supported by Frame Rate Converter DSP (http://msdn.microsoft.com/en-us/library/windows/desktop/ff819100(v=vs.85).aspx).aspx) because of color (neither I420 nor NV12)
+ // Video Processor (http://msdn.microsoft.com/en-us/library/windows/desktop/hh162913(v=vs.85).aspx) supports both NV12 and I420
+ if (!bVideoProcessorIsSupported) {
+ UINT32 nWidth, nHeight, nFps;
+ hr = MFUtils::GetBestFormat(
+ pSelf->pSource,
+ &MFVideoFormat_I420,
+ (UINT32)TMEDIA_PRODUCER(pSelf)->video.width,
+ (UINT32)TMEDIA_PRODUCER(pSelf)->video.height,
+ (UINT32)TMEDIA_PRODUCER(pSelf)->video.fps,
+ &nWidth,
+ &nHeight,
+ &nFps,
+ &pcPreferredSubTypeGuidPair
+ );
+ if (SUCCEEDED(hr)) {
+ TSK_DEBUG_INFO("Video processor not supported...using source fps=%u, width=%u, height=%u", nFps, nWidth, nHeight);
+ TMEDIA_PRODUCER(pSelf)->video.width = nWidth;
+ TMEDIA_PRODUCER(pSelf)->video.height = nHeight;
+ TMEDIA_PRODUCER(pSelf)->video.fps = nFps;
+ }
+ }
+
+ // If H.264 is negotiated for this session then, try to find hardware encoder
+ // If no HW encoder is found will fallback to SW implementation from x264
#if PLUGIN_MF_PV_BUNDLE_CODEC
- // Before embedding a H.264 encoder we have to be sure that:
- // - Low latency is supported
- // - The user decided to use MF encoder (Microsoft, Intel Quick Sync or any other)
- if ((codec->id == tmedia_codec_id_h264_bp || codec->id == tmedia_codec_id_h264_mp) && MFUtils::IsLowLatencyH264Supported()) {
- BOOL bMFEncoderIsRegistered =
- (codec->id == tmedia_codec_id_h264_mp && codec->plugin == mf_codec_h264_main_plugin_def_t)
- || (codec->id == tmedia_codec_id_h264_bp && codec->plugin == mf_codec_h264_base_plugin_def_t);
- if (bMFEncoderIsRegistered)
- {
- // both Microsoft and Intel encoders support NV12 only as input
- // static const BOOL kIsEncoder = TRUE;
- // hr = MFUtils::GetBestCodec(kIsEncoder, MFMediaType_Video, MFVideoFormat_NV12, MFVideoFormat_H264, &pSelf->pEncoder);
- pSelf->pEncoder = (codec->id == tmedia_codec_id_h264_bp) ? MFCodecVideoH264::CreateCodecH264Base(MFCodecType_Encoder) : MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Encoder);
- if (pSelf->pEncoder)
- {
- pSelf->pEncoder->setBundled(TRUE);
- int32_t avg_bitrate_kbps = tmedia_get_video_bandwidth_kbps_2((unsigned int)TMEDIA_PRODUCER(pSelf)->video.width, (unsigned int)TMEDIA_PRODUCER(pSelf)->video.height, TMEDIA_PRODUCER(pSelf)->video.fps);
- TSK_DEBUG_INFO("MF_MT_AVG_BITRATE defined with value = %d kbps", avg_bitrate_kbps);
- pSelf->bitrate_bps = (avg_bitrate_kbps * 1024);
-
- hr = pSelf->pEncoder->Initialize(
- (UINT32)TMEDIA_PRODUCER(pSelf)->video.fps,
- (UINT32)TMEDIA_PRODUCER(pSelf)->video.width,
- (UINT32)TMEDIA_PRODUCER(pSelf)->video.height,
- (UINT32)pSelf->bitrate_bps);
- if (SUCCEEDED(hr))
- {
- /*hr =*/ pSelf->pEncoder->SetGOPSize((PLUGIN_MF_GOP_SIZE_IN_SECONDS * TMEDIA_PRODUCER(pSelf)->video.fps));
- }
- if (FAILED(hr))
- {
- SafeRelease(&pSelf->pEncoder);
- hr = S_OK;
- }
- }
- if (SUCCEEDED(hr) && pSelf->pEncoder)
- {
- TMEDIA_PRODUCER(pSelf)->encoder.codec_id = codec->id; // means encoded frames as input
- }
- else
- {
- SafeRelease(&pSelf->pEncoder);
- TSK_DEBUG_WARN("Failed to find H.264 HW encoder...fallback to SW implementation");
- }
- }
- else /* if(!bMFEncoderIsRegistered) */
- {
- TSK_DEBUG_INFO("Not bundling MF H.264 encoder even if low latency is supported because another implementation is registered: %s", codec->plugin->desc);
- }
- }
+ // Before embedding a H.264 encoder we have to be sure that:
+ // - Low latency is supported
+ // - The user decided to use MF encoder (Microsoft, Intel Quick Sync or any other)
+ if ((codec->id == tmedia_codec_id_h264_bp || codec->id == tmedia_codec_id_h264_mp) && MFUtils::IsLowLatencyH264Supported()) {
+ BOOL bMFEncoderIsRegistered =
+ (codec->id == tmedia_codec_id_h264_mp && codec->plugin == mf_codec_h264_main_plugin_def_t)
+ || (codec->id == tmedia_codec_id_h264_bp && codec->plugin == mf_codec_h264_base_plugin_def_t);
+ if (bMFEncoderIsRegistered) {
+ // both Microsoft and Intel encoders support NV12 only as input
+ // static const BOOL kIsEncoder = TRUE;
+ // hr = MFUtils::GetBestCodec(kIsEncoder, MFMediaType_Video, MFVideoFormat_NV12, MFVideoFormat_H264, &pSelf->pEncoder);
+ pSelf->pEncoder = (codec->id == tmedia_codec_id_h264_bp) ? MFCodecVideoH264::CreateCodecH264Base(MFCodecType_Encoder) : MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Encoder);
+ if (pSelf->pEncoder) {
+ pSelf->pEncoder->setBundled(TRUE);
+ int32_t avg_bitrate_kbps = tmedia_get_video_bandwidth_kbps_2((unsigned int)TMEDIA_PRODUCER(pSelf)->video.width, (unsigned int)TMEDIA_PRODUCER(pSelf)->video.height, TMEDIA_PRODUCER(pSelf)->video.fps);
+ TSK_DEBUG_INFO("MF_MT_AVG_BITRATE defined with value = %d kbps", avg_bitrate_kbps);
+ pSelf->bitrate_bps = (avg_bitrate_kbps * 1024);
+
+ hr = pSelf->pEncoder->Initialize(
+ (UINT32)TMEDIA_PRODUCER(pSelf)->video.fps,
+ (UINT32)TMEDIA_PRODUCER(pSelf)->video.width,
+ (UINT32)TMEDIA_PRODUCER(pSelf)->video.height,
+ (UINT32)pSelf->bitrate_bps);
+ if (SUCCEEDED(hr)) {
+ /*hr =*/ pSelf->pEncoder->SetGOPSize((PLUGIN_MF_GOP_SIZE_IN_SECONDS * TMEDIA_PRODUCER(pSelf)->video.fps));
+ }
+ if (FAILED(hr)) {
+ SafeRelease(&pSelf->pEncoder);
+ hr = S_OK;
+ }
+ }
+ if (SUCCEEDED(hr) && pSelf->pEncoder) {
+ TMEDIA_PRODUCER(pSelf)->encoder.codec_id = codec->id; // means encoded frames as input
+ }
+ else {
+ SafeRelease(&pSelf->pEncoder);
+ TSK_DEBUG_WARN("Failed to find H.264 HW encoder...fallback to SW implementation");
+ }
+ }
+ else { /* if(!bMFEncoderIsRegistered) */
+ TSK_DEBUG_INFO("Not bundling MF H.264 encoder even if low latency is supported because another implementation is registered: %s", codec->plugin->desc);
+ }
+ }
#endif
- // Set session attributes
- CHECK_HR(hr = MFCreateAttributes(&pSessionAttributes, 1));
- CHECK_HR(hr = pSessionAttributes->SetUINT32(PLUGIN_MF_LOW_LATENCY, 1));
-
- // 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.
-
- CHECK_HR(hr = MFCreateMediaType(&pSelf->pGrabberInputType));
- CHECK_HR(hr = pSelf->pGrabberInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
- CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
-
- CHECK_HR(hr = MFSetAttributeSize(pSelf->pGrabberInputType, MF_MT_FRAME_SIZE, (UINT32)TMEDIA_PRODUCER(pSelf)->video.width, (UINT32)TMEDIA_PRODUCER(pSelf)->video.height));
- CHECK_HR(hr = MFSetAttributeRatio(pSelf->pGrabberInputType, MF_MT_FRAME_RATE, TMEDIA_PRODUCER(pSelf)->video.fps, 1));
-
- CHECK_HR(hr = MFSetAttributeRatio(pSelf->pGrabberInputType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
- CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, pSelf->pEncoder ? FALSE : TRUE));
- CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, pSelf->pEncoder ? FALSE : TRUE));
- if (pSelf->pEncoder) {
- switch (codec->id){
- case tmedia_codec_id_h264_bp: case tmedia_codec_id_h264_mp:
- {
- CHECK_HR(hr = pSelf->pGrabberInputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));
- CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_MPEG2_PROFILE, (codec->id == tmedia_codec_id_h264_bp) ? eAVEncH264VProfile_Base : eAVEncH264VProfile_Main));
- CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_AVG_BITRATE, pSelf->bitrate_bps));
- break;
- }
- default:
- {
- TSK_DEBUG_ERROR("HW encoder with id = %d not expected", codec->id);
- assert(false);
- }
- }
- TMEDIA_PRODUCER(pSelf)->video.chroma = tmedia_chroma_nv12;
- TSK_DEBUG_INFO("MF video producer chroma = NV12 (because of HW encoder)");
- }
- else {
- // Video Processors will be inserted in the topology if the source cannot produce I420 frames
- // IMPORTANT: Must not be NV12 because not supported by Video Resizer DSP (http://msdn.microsoft.com/en-us/library/windows/desktop/ff819491(v=vs.85).aspx)
- CHECK_HR(hr = pSelf->pGrabberInputType->SetGUID(MF_MT_SUBTYPE, pcPreferredSubTypeGuidPair ? pcPreferredSubTypeGuidPair->fourcc : MFVideoFormat_I420));
- TMEDIA_PRODUCER(pSelf)->video.chroma = pcPreferredSubTypeGuidPair ? pcPreferredSubTypeGuidPair->chroma : tmedia_chroma_yuv420p;
- TSK_DEBUG_INFO("MF video producer chroma = %d", TMEDIA_PRODUCER(pSelf)->video.chroma);
- }
-
- if (pSelf->pEncoder) {
- // Unlock the encoder
- //BOOL bIsAsyncMFT = FALSE;
- //CHECK_HR(hr = MFUtils::IsAsyncMFT(pSelf->pEncoder->GetMFT(), &bIsAsyncMFT));
- //if(bIsAsyncMFT)
- //{
- // CHECK_HR(hr = MFUtils::UnlockAsyncMFT(pSelf->pEncoderpSelf->pEncoder->GetMFT()));
- //}
- // Apply Encoder output type (must be called before SetInputType)
- //CHECK_HR(hr = pSelf->pEncoder->GetMFT()->SetOutputType(0, pSelf->pGrabberInputType, 0/*MFT_SET_TYPE_TEST_ONLY*/));
-
- // HW encoders support only NV12
- //CHECK_HR(hr = MFUtils::ConvertVideoTypeToUncompressedType(pSelf->pGrabberInputType, MFVideoFormat_NV12, &pEncoderInputType));
- //CHECK_HR(hr = pSelf->pEncoder->GetMFT()->SetInputType(0, pEncoderInputType, 0/*MFT_SET_TYPE_TEST_ONLY*/));
- }
- // Create the sample grabber sink.
- CHECK_HR(hr = SampleGrabberCB::CreateInstance(TMEDIA_PRODUCER(pSelf), &pSelf->pCallback));
- CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pSelf->pGrabberInputType, pSelf->pCallback, &pSelf->pSinkGrabber));
-
- // To run as fast as possible, set this attribute (requires Windows 7):
- CHECK_HR(hr = pSelf->pSinkGrabber->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE));
-
- // Create the Media Session.
- CHECK_HR(hr = MFCreateMediaSession(pSessionAttributes, &pSelf->pSession));
-
- // Create the EVR activation object for the preview.
- CHECK_HR(hr = MFCreateVideoRendererActivate(pSelf->hWndPreview, &pSelf->pSinkActivatePreview));
-
- // Create the topology.
- CHECK_HR(hr = MFUtils::CreateTopology(
- pSelf->pSource,
- pSelf->pEncoder ? pSelf->pEncoder->GetMFT() : NULL,
- pSelf->pSinkGrabber,
- pSelf->pSinkActivatePreview,
- pSelf->pGrabberInputType,
- &pTopology));
- // Resolve topology (adds video processors if needed).
- CHECK_HR(hr = MFUtils::ResolveTopology(pTopology, &pSelf->pTopology));
-
- // Find EVR for the preview.
- CHECK_HR(hr = MFUtils::FindNodeObject(pSelf->pTopology, MFUtils::g_ullTopoIdSinkPreview, (void**)&pEvr));
-
- // Find negotiated media and update producer
- UINT32 nNegWidth = (UINT32)TMEDIA_PRODUCER(pSelf)->video.width, nNegHeight = (UINT32)TMEDIA_PRODUCER(pSelf)->video.height, nNegNumeratorFps = (UINT32)TMEDIA_PRODUCER(pSelf)->video.fps, nNegDenominatorFps = 1;
- CHECK_HR(hr = pSelf->pTopology->GetNodeByID(MFUtils::g_ullTopoIdSinkMain, &pNodeGrabber));
- CHECK_HR(hr = pNodeGrabber->GetInputPrefType(0, &pGrabberNegotiatedInputMedia));
- hr = MFGetAttributeSize(pGrabberNegotiatedInputMedia, MF_MT_FRAME_SIZE, &nNegWidth, &nNegHeight);
- if (SUCCEEDED(hr))
- {
- TSK_DEBUG_INFO("MF video producer topology vs sdp parameters: width(%u/%u), height(%u/%u)",
- TMEDIA_PRODUCER(pSelf)->video.width, nNegWidth,
- TMEDIA_PRODUCER(pSelf)->video.height, nNegHeight
- );
- TMEDIA_PRODUCER(pSelf)->video.width = nNegWidth;
- TMEDIA_PRODUCER(pSelf)->video.height = nNegHeight;
- }
- hr = MFGetAttributeRatio(pGrabberNegotiatedInputMedia, MF_MT_FRAME_RATE, &nNegNumeratorFps, &nNegDenominatorFps);
- if (SUCCEEDED(hr))
- {
- TSK_DEBUG_INFO("MF video producer topology vs sdp parameters: fps(%u/%u)",
- TMEDIA_PRODUCER(pSelf)->video.fps, (nNegNumeratorFps / nNegDenominatorFps)
- );
- TMEDIA_PRODUCER(pSelf)->video.fps = (nNegNumeratorFps / nNegDenominatorFps);
- }
-
- // Create EVR watcher for the preview.
- pSelf->pWatcherPreview = new DisplayWatcher(pSelf->hWndPreview, pEvr, hr);
- CHECK_HR(hr);
- }
+ // Set session attributes
+ CHECK_HR(hr = MFCreateAttributes(&pSessionAttributes, 1));
+ CHECK_HR(hr = pSessionAttributes->SetUINT32(PLUGIN_MF_LOW_LATENCY, 1));
+
+ // 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.
+
+ CHECK_HR(hr = MFCreateMediaType(&pSelf->pGrabberInputType));
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
+
+ CHECK_HR(hr = MFSetAttributeSize(pSelf->pGrabberInputType, MF_MT_FRAME_SIZE, (UINT32)TMEDIA_PRODUCER(pSelf)->video.width, (UINT32)TMEDIA_PRODUCER(pSelf)->video.height));
+ CHECK_HR(hr = MFSetAttributeRatio(pSelf->pGrabberInputType, MF_MT_FRAME_RATE, TMEDIA_PRODUCER(pSelf)->video.fps, 1));
+
+ CHECK_HR(hr = MFSetAttributeRatio(pSelf->pGrabberInputType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, pSelf->pEncoder ? FALSE : TRUE));
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, pSelf->pEncoder ? FALSE : TRUE));
+ if (pSelf->pEncoder) {
+ switch (codec->id) {
+ case tmedia_codec_id_h264_bp:
+ case tmedia_codec_id_h264_mp: {
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_MPEG2_PROFILE, (codec->id == tmedia_codec_id_h264_bp) ? eAVEncH264VProfile_Base : eAVEncH264VProfile_Main));
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetUINT32(MF_MT_AVG_BITRATE, pSelf->bitrate_bps));
+ break;
+ }
+ default: {
+ TSK_DEBUG_ERROR("HW encoder with id = %d not expected", codec->id);
+ assert(false);
+ }
+ }
+ TMEDIA_PRODUCER(pSelf)->video.chroma = tmedia_chroma_nv12;
+ TSK_DEBUG_INFO("MF video producer chroma = NV12 (because of HW encoder)");
+ }
+ else {
+ // Video Processors will be inserted in the topology if the source cannot produce I420 frames
+ // IMPORTANT: Must not be NV12 because not supported by Video Resizer DSP (http://msdn.microsoft.com/en-us/library/windows/desktop/ff819491(v=vs.85).aspx)
+ CHECK_HR(hr = pSelf->pGrabberInputType->SetGUID(MF_MT_SUBTYPE, pcPreferredSubTypeGuidPair ? pcPreferredSubTypeGuidPair->fourcc : MFVideoFormat_I420));
+ TMEDIA_PRODUCER(pSelf)->video.chroma = pcPreferredSubTypeGuidPair ? pcPreferredSubTypeGuidPair->chroma : tmedia_chroma_yuv420p;
+ TSK_DEBUG_INFO("MF video producer chroma = %d", TMEDIA_PRODUCER(pSelf)->video.chroma);
+ }
+
+ if (pSelf->pEncoder) {
+ // Unlock the encoder
+ //BOOL bIsAsyncMFT = FALSE;
+ //CHECK_HR(hr = MFUtils::IsAsyncMFT(pSelf->pEncoder->GetMFT(), &bIsAsyncMFT));
+ //if(bIsAsyncMFT)
+ //{
+ // CHECK_HR(hr = MFUtils::UnlockAsyncMFT(pSelf->pEncoderpSelf->pEncoder->GetMFT()));
+ //}
+ // Apply Encoder output type (must be called before SetInputType)
+ //CHECK_HR(hr = pSelf->pEncoder->GetMFT()->SetOutputType(0, pSelf->pGrabberInputType, 0/*MFT_SET_TYPE_TEST_ONLY*/));
+
+ // HW encoders support only NV12
+ //CHECK_HR(hr = MFUtils::ConvertVideoTypeToUncompressedType(pSelf->pGrabberInputType, MFVideoFormat_NV12, &pEncoderInputType));
+ //CHECK_HR(hr = pSelf->pEncoder->GetMFT()->SetInputType(0, pEncoderInputType, 0/*MFT_SET_TYPE_TEST_ONLY*/));
+ }
+ // Create the sample grabber sink.
+ CHECK_HR(hr = SampleGrabberCB::CreateInstance(TMEDIA_PRODUCER(pSelf), &pSelf->pCallback));
+ CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pSelf->pGrabberInputType, pSelf->pCallback, &pSelf->pSinkGrabber));
+
+ // To run as fast as possible, set this attribute (requires Windows 7):
+ CHECK_HR(hr = pSelf->pSinkGrabber->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE));
+
+ // Create the Media Session.
+ CHECK_HR(hr = MFCreateMediaSession(pSessionAttributes, &pSelf->pSession));
+
+ // Create the EVR activation object for the preview.
+ CHECK_HR(hr = MFCreateVideoRendererActivate(pSelf->hWndPreview, &pSelf->pSinkActivatePreview));
+
+ // Create the topology.
+ CHECK_HR(hr = MFUtils::CreateTopology(
+ pSelf->pSource,
+ pSelf->pEncoder ? pSelf->pEncoder->GetMFT() : NULL,
+ pSelf->pSinkGrabber,
+ pSelf->pSinkActivatePreview,
+ pSelf->pGrabberInputType,
+ &pTopology));
+ // Resolve topology (adds video processors if needed).
+ CHECK_HR(hr = MFUtils::ResolveTopology(pTopology, &pSelf->pTopology));
+
+ // Find EVR for the preview.
+ CHECK_HR(hr = MFUtils::FindNodeObject(pSelf->pTopology, MFUtils::g_ullTopoIdSinkPreview, (void**)&pEvr));
+
+ // Find negotiated media and update producer
+ UINT32 nNegWidth = (UINT32)TMEDIA_PRODUCER(pSelf)->video.width, nNegHeight = (UINT32)TMEDIA_PRODUCER(pSelf)->video.height, nNegNumeratorFps = (UINT32)TMEDIA_PRODUCER(pSelf)->video.fps, nNegDenominatorFps = 1;
+ CHECK_HR(hr = pSelf->pTopology->GetNodeByID(MFUtils::g_ullTopoIdSinkMain, &pNodeGrabber));
+ CHECK_HR(hr = pNodeGrabber->GetInputPrefType(0, &pGrabberNegotiatedInputMedia));
+ hr = MFGetAttributeSize(pGrabberNegotiatedInputMedia, MF_MT_FRAME_SIZE, &nNegWidth, &nNegHeight);
+ if (SUCCEEDED(hr)) {
+ TSK_DEBUG_INFO("MF video producer topology vs sdp parameters: width(%u/%u), height(%u/%u)",
+ TMEDIA_PRODUCER(pSelf)->video.width, nNegWidth,
+ TMEDIA_PRODUCER(pSelf)->video.height, nNegHeight
+ );
+ TMEDIA_PRODUCER(pSelf)->video.width = nNegWidth;
+ TMEDIA_PRODUCER(pSelf)->video.height = nNegHeight;
+ }
+ hr = MFGetAttributeRatio(pGrabberNegotiatedInputMedia, MF_MT_FRAME_RATE, &nNegNumeratorFps, &nNegDenominatorFps);
+ if (SUCCEEDED(hr)) {
+ TSK_DEBUG_INFO("MF video producer topology vs sdp parameters: fps(%u/%u)",
+ TMEDIA_PRODUCER(pSelf)->video.fps, (nNegNumeratorFps / nNegDenominatorFps)
+ );
+ TMEDIA_PRODUCER(pSelf)->video.fps = (nNegNumeratorFps / nNegDenominatorFps);
+ }
+
+ // Create EVR watcher for the preview.
+ pSelf->pWatcherPreview = new DisplayWatcher(pSelf->hWndPreview, pEvr, hr);
+ CHECK_HR(hr);
+ }
bail:
- SafeRelease(&pSessionAttributes);
- SafeRelease(&pTopology);
- SafeRelease(&pEvr);
- SafeRelease(&pEncoderInputType);
- SafeRelease(&pNodeGrabber);
- SafeRelease(&pGrabberNegotiatedInputMedia);
-
- pSelf->bPrepared = SUCCEEDED(hr);
- return pSelf->bPrepared ? 0 : -1;
+ SafeRelease(&pSessionAttributes);
+ SafeRelease(&pTopology);
+ SafeRelease(&pEvr);
+ SafeRelease(&pEncoderInputType);
+ SafeRelease(&pNodeGrabber);
+ SafeRelease(&pGrabberNegotiatedInputMedia);
+
+ pSelf->bPrepared = SUCCEEDED(hr);
+ return pSelf->bPrepared ? 0 : -1;
}
static int plugin_win_mf_producer_video_start(tmedia_producer_t* self)
{
- plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
-
- if (!pSelf){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if (pSelf->bStarted){
- TSK_DEBUG_INFO("MF video producer already started");
- return 0;
- }
- if (!pSelf->bPrepared){
- TSK_DEBUG_ERROR("MF video producer not prepared");
- return -1;
- }
-
- HRESULT hr = S_OK;
-
- // Run preview watcher
- if (pSelf->pWatcherPreview) {
- CHECK_HR(hr = pSelf->pWatcherPreview->Start());
- }
-
- // Run the media session.
- CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopology));
-
- // Start asynchronous watcher thread
- pSelf->bStarted = true;
- int ret = tsk_thread_create(&pSelf->ppTread[0], RunSessionThread, pSelf);
- if (ret != 0) {
- TSK_DEBUG_ERROR("Failed to create thread");
- hr = E_FAIL;
- pSelf->bStarted = false;
- if (pSelf->ppTread[0]){
- tsk_thread_join(&pSelf->ppTread[0]);
- }
- MFUtils::ShutdownSession(pSelf->pSession, pSelf->pSource);
- goto bail;
- }
+ plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
+
+ if (!pSelf) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (pSelf->bStarted) {
+ TSK_DEBUG_INFO("MF video producer already started");
+ return 0;
+ }
+ if (!pSelf->bPrepared) {
+ TSK_DEBUG_ERROR("MF video producer not prepared");
+ return -1;
+ }
+
+ HRESULT hr = S_OK;
+
+ // Run preview watcher
+ if (pSelf->pWatcherPreview) {
+ CHECK_HR(hr = pSelf->pWatcherPreview->Start());
+ }
+
+ // Run the media session.
+ CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopology));
+
+ // Start asynchronous watcher thread
+ pSelf->bStarted = true;
+ int ret = tsk_thread_create(&pSelf->ppTread[0], RunSessionThread, pSelf);
+ if (ret != 0) {
+ TSK_DEBUG_ERROR("Failed to create thread");
+ hr = E_FAIL;
+ pSelf->bStarted = false;
+ if (pSelf->ppTread[0]) {
+ tsk_thread_join(&pSelf->ppTread[0]);
+ }
+ MFUtils::ShutdownSession(pSelf->pSession, pSelf->pSource);
+ goto bail;
+ }
bail:
- return SUCCEEDED(hr) ? 0 : -1;
+ return SUCCEEDED(hr) ? 0 : -1;
}
static int plugin_win_mf_producer_video_pause(tmedia_producer_t* self)
{
- plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
+ plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
- if (!pSelf){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- if (!pSelf->bStarted)
- {
- TSK_DEBUG_INFO("MF video producer not started");
- return 0;
- }
+ if (!pSelf) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!pSelf->bStarted) {
+ TSK_DEBUG_INFO("MF video producer not started");
+ return 0;
+ }
- HRESULT hr = MFUtils::PauseSession(pSelf->pSession);
+ HRESULT hr = MFUtils::PauseSession(pSelf->pSession);
- return SUCCEEDED(hr) ? 0 : -1;
+ return SUCCEEDED(hr) ? 0 : -1;
}
static int plugin_win_mf_producer_video_stop(tmedia_producer_t* self)
{
- plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
+ plugin_win_mf_producer_video_t* pSelf = (plugin_win_mf_producer_video_t*)self;
- if (!pSelf){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!pSelf) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- HRESULT hr = S_OK;
+ HRESULT hr = S_OK;
- if (pSelf->pWatcherPreview){
- hr = pSelf->pWatcherPreview->Stop();
- }
+ if (pSelf->pWatcherPreview) {
+ hr = pSelf->pWatcherPreview->Stop();
+ }
- // for the thread
- pSelf->bStarted = false;
- hr = MFUtils::ShutdownSession(pSelf->pSession, NULL); // stop session to wakeup the asynchronous thread
- if (pSelf->ppTread[0]){
- tsk_thread_join(&pSelf->ppTread[0]);
- }
- hr = MFUtils::ShutdownSession(NULL, pSelf->pSource); // stop source to release the camera
+ // for the thread
+ pSelf->bStarted = false;
+ hr = MFUtils::ShutdownSession(pSelf->pSession, NULL); // stop session to wakeup the asynchronous thread
+ if (pSelf->ppTread[0]) {
+ tsk_thread_join(&pSelf->ppTread[0]);
+ }
+ hr = MFUtils::ShutdownSession(NULL, pSelf->pSource); // stop source to release the camera
- // next start() will be called after prepare()
- return _plugin_win_mf_producer_video_unprepare(pSelf);
+ // next start() will be called after prepare()
+ return _plugin_win_mf_producer_video_unprepare(pSelf);
}
static int _plugin_win_mf_producer_video_unprepare(plugin_win_mf_producer_video_t* pSelf)
{
- if (!pSelf){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if (pSelf->bStarted) {
- // plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf));
- TSK_DEBUG_ERROR("Producer must be stopped before calling unprepare");
- }
- if (pSelf->pDeviceList){
- delete pSelf->pDeviceList, pSelf->pDeviceList = NULL;
- }
- if (pSelf->pWatcherPreview){
- pSelf->pWatcherPreview->Stop();
- }
- if (pSelf->pSource){
- pSelf->pSource->Shutdown();
- }
- if (pSelf->pSession){
- pSelf->pSession->Shutdown();
- }
-
- SafeRelease(&pSelf->pEncoder);
- SafeRelease(&pSelf->pSession);
- SafeRelease(&pSelf->pSource);
- SafeRelease(&pSelf->pSinkActivatePreview);
- SafeRelease(&pSelf->pCallback);
- SafeRelease(&pSelf->pSinkGrabber);
- SafeRelease(&pSelf->pTopology);
- SafeRelease(&pSelf->pGrabberInputType);
-
- if (pSelf->pWatcherPreview){
- delete pSelf->pWatcherPreview;
- pSelf->pWatcherPreview = NULL;
- }
-
- pSelf->bPrepared = false;
-
- return 0;
+ if (!pSelf) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (pSelf->bStarted) {
+ // plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf));
+ TSK_DEBUG_ERROR("Producer must be stopped before calling unprepare");
+ }
+ if (pSelf->pDeviceList) {
+ delete pSelf->pDeviceList, pSelf->pDeviceList = NULL;
+ }
+ if (pSelf->pWatcherPreview) {
+ pSelf->pWatcherPreview->Stop();
+ }
+ if (pSelf->pSource) {
+ pSelf->pSource->Shutdown();
+ }
+ if (pSelf->pSession) {
+ pSelf->pSession->Shutdown();
+ }
+
+ SafeRelease(&pSelf->pEncoder);
+ SafeRelease(&pSelf->pSession);
+ SafeRelease(&pSelf->pSource);
+ SafeRelease(&pSelf->pSinkActivatePreview);
+ SafeRelease(&pSelf->pCallback);
+ SafeRelease(&pSelf->pSinkGrabber);
+ SafeRelease(&pSelf->pTopology);
+ SafeRelease(&pSelf->pGrabberInputType);
+
+ if (pSelf->pWatcherPreview) {
+ delete pSelf->pWatcherPreview;
+ pSelf->pWatcherPreview = NULL;
+ }
+
+ pSelf->bPrepared = false;
+
+ return 0;
}
//
@@ -611,63 +590,61 @@ static int _plugin_win_mf_producer_video_unprepare(plugin_win_mf_producer_video_
/* constructor */
static tsk_object_t* plugin_win_mf_producer_video_ctor(tsk_object_t * self, va_list * app)
{
- MFUtils::Startup();
-
- plugin_win_mf_producer_video_t *pSelf = (plugin_win_mf_producer_video_t *)self;
- if (pSelf){
- /* init base */
- tmedia_producer_init(TMEDIA_PRODUCER(pSelf));
-
- /* init self with default values*/
- TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input
- TMEDIA_PRODUCER(pSelf)->video.chroma = tmedia_chroma_nv12;
- TMEDIA_PRODUCER(pSelf)->video.fps = 15;
- TMEDIA_PRODUCER(pSelf)->video.width = 352;
- TMEDIA_PRODUCER(pSelf)->video.height = 288;
-
- TSK_DEBUG_INFO("Create WinMF video producer");
- }
- return self;
+ MFUtils::Startup();
+
+ plugin_win_mf_producer_video_t *pSelf = (plugin_win_mf_producer_video_t *)self;
+ if (pSelf) {
+ /* init base */
+ tmedia_producer_init(TMEDIA_PRODUCER(pSelf));
+
+ /* init self with default values*/
+ TMEDIA_PRODUCER(pSelf)->encoder.codec_id = tmedia_codec_id_none; // means RAW frames as input
+ TMEDIA_PRODUCER(pSelf)->video.chroma = tmedia_chroma_nv12;
+ TMEDIA_PRODUCER(pSelf)->video.fps = 15;
+ TMEDIA_PRODUCER(pSelf)->video.width = 352;
+ TMEDIA_PRODUCER(pSelf)->video.height = 288;
+
+ TSK_DEBUG_INFO("Create WinMF video producer");
+ }
+ return self;
}
/* destructor */
static tsk_object_t* plugin_win_mf_producer_video_dtor(tsk_object_t * self)
{
- plugin_win_mf_producer_video_t *pSelf = (plugin_win_mf_producer_video_t *)self;
- if (pSelf){
- /* stop */
- if (pSelf->bStarted){
- plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf));
- }
-
- /* deinit base */
- tmedia_producer_deinit(TMEDIA_PRODUCER(pSelf));
- /* deinit self */
- _plugin_win_mf_producer_video_unprepare(pSelf);
- }
-
- return self;
+ plugin_win_mf_producer_video_t *pSelf = (plugin_win_mf_producer_video_t *)self;
+ if (pSelf) {
+ /* stop */
+ if (pSelf->bStarted) {
+ plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf));
+ }
+
+ /* deinit base */
+ tmedia_producer_deinit(TMEDIA_PRODUCER(pSelf));
+ /* deinit self */
+ _plugin_win_mf_producer_video_unprepare(pSelf);
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t plugin_win_mf_producer_video_def_s =
-{
- sizeof(plugin_win_mf_producer_video_t),
- plugin_win_mf_producer_video_ctor,
- plugin_win_mf_producer_video_dtor,
- tsk_null,
+static const tsk_object_def_t plugin_win_mf_producer_video_def_s = {
+ sizeof(plugin_win_mf_producer_video_t),
+ plugin_win_mf_producer_video_ctor,
+ plugin_win_mf_producer_video_dtor,
+ tsk_null,
};
/* plugin definition*/
-static const tmedia_producer_plugin_def_t plugin_win_mf_producer_video_plugin_def_s =
-{
- &plugin_win_mf_producer_video_def_s,
+static const tmedia_producer_plugin_def_t plugin_win_mf_producer_video_plugin_def_s = {
+ &plugin_win_mf_producer_video_def_s,
- tmedia_video,
- "Microsoft Windows Media Foundation producer (Video)",
+ tmedia_video,
+ "Microsoft Windows Media Foundation producer (Video)",
- plugin_win_mf_producer_video_set,
- plugin_win_mf_producer_video_prepare,
- plugin_win_mf_producer_video_start,
- plugin_win_mf_producer_video_pause,
- plugin_win_mf_producer_video_stop
+ plugin_win_mf_producer_video_set,
+ plugin_win_mf_producer_video_prepare,
+ plugin_win_mf_producer_video_start,
+ plugin_win_mf_producer_video_pause,
+ plugin_win_mf_producer_video_stop
};
const tmedia_producer_plugin_def_t *plugin_win_mf_producer_video_plugin_def_t = &plugin_win_mf_producer_video_plugin_def_s;
@@ -675,40 +652,38 @@ const tmedia_producer_plugin_def_t *plugin_win_mf_producer_video_plugin_def_t =
// Run session async thread
static void* TSK_STDCALL RunSessionThread(void *pArg)
{
- plugin_win_mf_producer_video_t *pSelf = (plugin_win_mf_producer_video_t *)pArg;
- HRESULT hrStatus = S_OK;
- HRESULT hr = S_OK;
- IMFMediaEvent *pEvent = NULL;
- MediaEventType met;
-
- TSK_DEBUG_INFO("RunSessionThread (MF video producer) - ENTER");
-
- while (pSelf->bStarted){
- hr = pSelf->pSession->GetEvent(0, &pEvent);
- if (hr == MF_E_SHUTDOWN) {
- if (pSelf->bStarted) {
- CHECK_HR(hr); // Shutdown called but "bStarted" not equal to false
- }
- break; // Shutdown called and "bStarted" is equal to false => break the loop
- }
- CHECK_HR(hr = pEvent->GetStatus(&hrStatus));
- CHECK_HR(hr = pEvent->GetType(&met));
-
- if (FAILED(hrStatus) /*&& hrStatus != MF_E_NO_SAMPLE_TIMESTAMP*/)
- {
- TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met);
- hr = hrStatus;
- goto bail;
- }
- if (met == MESessionEnded)
- {
- break;
- }
- SafeRelease(&pEvent);
- }
+ plugin_win_mf_producer_video_t *pSelf = (plugin_win_mf_producer_video_t *)pArg;
+ HRESULT hrStatus = S_OK;
+ HRESULT hr = S_OK;
+ IMFMediaEvent *pEvent = NULL;
+ MediaEventType met;
+
+ TSK_DEBUG_INFO("RunSessionThread (MF video producer) - ENTER");
+
+ while (pSelf->bStarted) {
+ hr = pSelf->pSession->GetEvent(0, &pEvent);
+ if (hr == MF_E_SHUTDOWN) {
+ if (pSelf->bStarted) {
+ CHECK_HR(hr); // Shutdown called but "bStarted" not equal to false
+ }
+ break; // Shutdown called and "bStarted" is equal to false => break the loop
+ }
+ CHECK_HR(hr = pEvent->GetStatus(&hrStatus));
+ CHECK_HR(hr = pEvent->GetType(&met));
+
+ if (FAILED(hrStatus) /*&& hrStatus != MF_E_NO_SAMPLE_TIMESTAMP*/) {
+ TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met);
+ hr = hrStatus;
+ goto bail;
+ }
+ if (met == MESessionEnded) {
+ break;
+ }
+ SafeRelease(&pEvent);
+ }
bail:
- TSK_DEBUG_INFO("RunSessionThread (MF video producer) - EXIT");
+ TSK_DEBUG_INFO("RunSessionThread (MF video producer) - EXIT");
- return NULL;
+ return NULL;
} \ No newline at end of file
OpenPOWER on IntegriCloud