mfvideosrc: Select common formats if both VideoPreview and VideoRecord are available

Some devices (e.g., Surface Book 2, Surface Pro X) will expose
both MediaStreamType_VideoPreview and MediaStreamType_VideoRecord types
for a logical device. And for some reason, MediaStreamType_VideoPreview
seems to be selected between them while initiailzing device.
But I cannot find any documentation for the decision rule.
To be safe, we will select common formats between them.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1478>
This commit is contained in:
Seungha Yang 2020-08-01 02:19:07 +09:00 committed by GStreamer Merge Bot
parent 479a67c1b7
commit 4986b0dd34
3 changed files with 74 additions and 11 deletions

View file

@ -214,13 +214,6 @@ gst_mf_capture_winrt_main_loop_running_cb (GstMFCaptureWinRT * self)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static bool
winrt_compare_caps_func (const GstWinRTMediaDescription & a,
const GstWinRTMediaDescription & b)
{
return gst_mf_source_object_caps_compare (a.caps_, b.caps_) < 0;
}
static gpointer static gpointer
gst_mf_capture_winrt_thread_func (GstMFCaptureWinRT * self) gst_mf_capture_winrt_thread_func (GstMFCaptureWinRT * self)
{ {
@ -300,7 +293,7 @@ gst_mf_capture_winrt_thread_func (GstMFCaptureWinRT * self)
self->capture->SetSourceGroup(*target_group); self->capture->SetSourceGroup(*target_group);
std::sort (target_group->source_list_.begin (), std::sort (target_group->source_list_.begin (),
target_group->source_list_.end (), winrt_compare_caps_func); target_group->source_list_.end (), WinRTCapsCompareFunc);
self->supported_caps = gst_caps_new_empty (); self->supported_caps = gst_caps_new_empty ();

View file

@ -23,6 +23,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include "gstmfutils.h" #include "gstmfutils.h"
#include "gstmfsourceobject.h"
#include "mediacapturewrapper.h" #include "mediacapturewrapper.h"
#include "AsyncOperations.h" #include "AsyncOperations.h"
@ -30,6 +31,8 @@
#include <locale> #include <locale>
#include <codecvt> #include <codecvt>
#include <string.h> #include <string.h>
#include <algorithm>
#include <iterator>
using namespace ABI::Windows::ApplicationModel::Core; using namespace ABI::Windows::ApplicationModel::Core;
using namespace ABI::Windows::Foundation::Collections; using namespace ABI::Windows::Foundation::Collections;
@ -261,6 +264,8 @@ GstWinRTMediaFrameSourceGroup::Fill
HString hstr_display_name; HString hstr_display_name;
ComPtr<IVectorView<MediaFrameSourceInfo*>> info_list; ComPtr<IVectorView<MediaFrameSourceInfo*>> info_list;
UINT32 count = 0; UINT32 count = 0;
std::vector<GstWinRTMediaDescription> preview_list;
std::vector<GstWinRTMediaDescription> record_list;
Release(); Release();
@ -313,6 +318,7 @@ GstWinRTMediaFrameSourceGroup::Fill
UINT32 desc_count = 0; UINT32 desc_count = 0;
HString source_id; HString source_id;
std::string source_id_str; std::string source_id_str;
std::vector<GstWinRTMediaDescription> *target_list = nullptr;
hr = info_list->GetAt(i, &info); hr = info_list->GetAt(i, &info);
if (!gst_mf_result (hr)) if (!gst_mf_result (hr))
@ -339,8 +345,21 @@ GstWinRTMediaFrameSourceGroup::Fill
continue; continue;
/* FIXME: support audio */ /* FIXME: support audio */
if (source_type != MediaStreamType::MediaStreamType_VideoPreview && if (source_type == MediaStreamType::MediaStreamType_VideoPreview) {
source_type != MediaStreamType::MediaStreamType_VideoRecord) { if (!preview_list.empty ()) {
GST_FIXME ("VideoPreview type was checked already");
continue;
}
target_list = &preview_list;
} else if (source_type == MediaStreamType::MediaStreamType_VideoRecord) {
if (!record_list.empty ()) {
GST_FIXME ("VideoRecord type was checked already");
continue;
}
target_list = &record_list;
} else {
GST_FIXME ("source-group %d, source-info %d, " GST_FIXME ("source-group %d, source-info %d, "
"type %d is not VideoPreview or VideoRecord", "type %d is not VideoPreview or VideoRecord",
index, i, (gint) source_type); index, i, (gint) source_type);
@ -382,10 +401,50 @@ GstWinRTMediaFrameSourceGroup::Fill
if (FAILED (hr)) if (FAILED (hr))
continue; continue;
source_list_.push_back(media_desc); target_list->push_back(media_desc);
} }
} }
if (!preview_list.empty () && !record_list.empty ()) {
/* FIXME: Some devices (e.g., Surface Book 2, Surface Pro X) will expose
* both MediaStreamType_VideoPreview and MediaStreamType_VideoRecord types
* for a logical device. And for some reason, MediaStreamType_VideoPreview
* seems to be selected between them while initiailzing device.
* But I cannot find any documentation for the decision rule.
* To be safe, we will select common formats between them.
*/
std::vector<GstWinRTMediaDescription> common;
/* Sort first */
std::sort (preview_list.begin (),
preview_list.end (), WinRTCapsCompareFunc);
std::sort (record_list.begin (),
record_list.end (), WinRTCapsCompareFunc);
/* Find common formats */
std::set_intersection(preview_list.begin (), preview_list.end(),
record_list.begin (), record_list.end (), std::back_inserter (common),
WinRTCapsCompareFunc);
source_list_.insert (source_list_.end (), common.begin (),
common.end ());
#ifndef GST_DISABLE_GST_DEBUG
std::vector<GstWinRTMediaDescription> diff;
std::set_difference(preview_list.begin (), preview_list.end(),
record_list.begin (), record_list.end (),
std::inserter (diff, diff.begin ()), WinRTCapsCompareFunc);
for (auto iter: diff)
GST_FIXME ("Drop uncommon format %" GST_PTR_FORMAT, iter.caps_);
#endif
} else if (!preview_list.empty ()) {
source_list_.insert (source_list_.end (), preview_list.begin (),
preview_list.end ());
} else if (!record_list.empty ()) {
source_list_.insert (source_list_.end (), record_list.begin (),
record_list.end ());
}
if (source_list_.empty()) { if (source_list_.empty()) {
GST_WARNING ("No usable source infos"); GST_WARNING ("No usable source infos");
hr = E_FAIL; hr = E_FAIL;
@ -1118,3 +1177,10 @@ FindCoreDispatcherForCurrentThread (ICoreDispatcher ** dispatcher)
return core_window->get_Dispatcher (dispatcher); return core_window->get_Dispatcher (dispatcher);
} }
bool
WinRTCapsCompareFunc (const GstWinRTMediaDescription & a,
const GstWinRTMediaDescription & b)
{
return gst_mf_source_object_caps_compare (a.caps_, b.caps_) < 0;
}

View file

@ -172,4 +172,8 @@ private:
HRESULT HRESULT
FindCoreDispatcherForCurrentThread(ICoreDispatcher ** dispatcher); FindCoreDispatcherForCurrentThread(ICoreDispatcher ** dispatcher);
bool
WinRTCapsCompareFunc(const GstWinRTMediaDescription & a,
const GstWinRTMediaDescription & b);
#endif /* __GST_MEDIA_CAPTURE_WRAPPER_H__ */ #endif /* __GST_MEDIA_CAPTURE_WRAPPER_H__ */