mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 17:18:15 +00:00
mfvideosrc: Expose sorted caps
Sort the list of supported caps for downstream to be able to select the best image in terms of quality (resolution and framerate) by default. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1452>
This commit is contained in:
parent
c3ecea0aa4
commit
6c52008413
4 changed files with 109 additions and 20 deletions
|
@ -27,6 +27,7 @@
|
|||
#include "mediacapturewrapper.h"
|
||||
#include <memorybuffer.h>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
|
@ -161,6 +162,13 @@ gst_mf_capture_winrt_main_loop_running_cb (GstMFCaptureWinRT * self)
|
|||
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
|
||||
gst_mf_capture_winrt_thread_func (GstMFCaptureWinRT * self)
|
||||
{
|
||||
|
@ -232,30 +240,33 @@ gst_mf_capture_winrt_thread_func (GstMFCaptureWinRT * self)
|
|||
goto run_loop;
|
||||
}
|
||||
|
||||
if (target_group->source_list_.empty ()) {
|
||||
GST_WARNING_OBJECT (self, "No available source list");
|
||||
goto run_loop;
|
||||
}
|
||||
|
||||
self->capture->SetSourceGroup(*target_group);
|
||||
|
||||
for (auto iter: target_group->source_list_) {
|
||||
if (!self->supported_caps)
|
||||
self->supported_caps = gst_caps_ref (iter.caps_);
|
||||
else
|
||||
self->supported_caps =
|
||||
gst_caps_merge (self->supported_caps, gst_caps_ref (iter.caps_));
|
||||
}
|
||||
std::sort (target_group->source_list_.begin (),
|
||||
target_group->source_list_.end (), winrt_compare_caps_func);
|
||||
|
||||
self->supported_caps = gst_caps_new_empty ();
|
||||
|
||||
for (auto iter: target_group->source_list_)
|
||||
gst_caps_append (self->supported_caps, gst_caps_copy (iter.caps_));
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Available output caps %" GST_PTR_FORMAT,
|
||||
self->supported_caps);
|
||||
|
||||
source->opened = !!self->supported_caps;
|
||||
source->opened = TRUE;
|
||||
|
||||
if (source->opened) {
|
||||
g_free (source->device_path);
|
||||
source->device_path = g_strdup (target_group->id_.c_str());
|
||||
g_free (source->device_path);
|
||||
source->device_path = g_strdup (target_group->id_.c_str());
|
||||
|
||||
g_free (source->device_name);
|
||||
source->device_name = g_strdup (target_group->display_name_.c_str());
|
||||
g_free (source->device_name);
|
||||
source->device_name = g_strdup (target_group->display_name_.c_str());
|
||||
|
||||
source->device_index = index;
|
||||
}
|
||||
source->device_index = index;
|
||||
|
||||
run_loop:
|
||||
GST_DEBUG_OBJECT (self, "Starting main loop");
|
||||
|
|
|
@ -338,3 +338,64 @@ gst_mf_source_object_new (GstMFSourceType type, gint device_index,
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
gst_mf_source_object_caps_compare (GstCaps * caps1, GstCaps * caps2)
|
||||
{
|
||||
GstStructure *s1, *s2;
|
||||
const gchar *n1, *n2;
|
||||
gboolean m1_is_raw, m2_is_raw;
|
||||
gint w1 = 0, h1 = 0, w2 = 0, h2 = 0;
|
||||
gint r1, r2;
|
||||
gint num1 = 0, den1 = 1, num2 = 0, den2 = 1;
|
||||
gint fraction_cmp;
|
||||
|
||||
/* sorting priority
|
||||
* - raw video > comprssed
|
||||
* - raw video format
|
||||
* - higher resolution
|
||||
* - higher framerate
|
||||
*/
|
||||
s1 = gst_caps_get_structure (caps1, 0);
|
||||
n1 = gst_structure_get_name (s1);
|
||||
|
||||
s2 = gst_caps_get_structure (caps2, 0);
|
||||
n2 = gst_structure_get_name (s2);
|
||||
|
||||
m1_is_raw = g_strcmp0 (n1, "video/x-raw") == 0;
|
||||
m2_is_raw = g_strcmp0 (n2, "video/x-raw") == 0;
|
||||
|
||||
if (m1_is_raw && !m2_is_raw)
|
||||
return -1;
|
||||
else if (!m1_is_raw && m2_is_raw)
|
||||
return 1;
|
||||
|
||||
/* if both are raw formats */
|
||||
if (m1_is_raw) {
|
||||
gint format_cmp = g_strcmp0 (gst_structure_get_string (s1, "format"),
|
||||
gst_structure_get_string (s2, "format"));
|
||||
if (format_cmp)
|
||||
return format_cmp;
|
||||
}
|
||||
|
||||
/* resolution */
|
||||
gst_structure_get_int (s1, "width", &w1);
|
||||
gst_structure_get_int (s1, "height", &h1);
|
||||
gst_structure_get_int (s2, "width", &w2);
|
||||
gst_structure_get_int (s2, "height", &h2);
|
||||
|
||||
r1 = w1 * h1;
|
||||
r2 = w2 * h2;
|
||||
|
||||
/* higher resolution first */
|
||||
if (r1 != r2)
|
||||
return r2 - r1;
|
||||
|
||||
gst_structure_get_fraction (s1, "framerate", &num1, &den1);
|
||||
gst_structure_get_fraction (s2, "framerate", &num2, &den2);
|
||||
|
||||
fraction_cmp = gst_util_fraction_compare (num1, den1, num2, den2);
|
||||
|
||||
/* higher framerate first */
|
||||
return fraction_cmp * -1;
|
||||
}
|
||||
|
|
|
@ -108,6 +108,10 @@ GstMFSourceObject * gst_mf_source_object_new (GstMFSourceType type,
|
|||
const gchar * device_name,
|
||||
const gchar * device_path);
|
||||
|
||||
/* Utility methods */
|
||||
gint gst_mf_source_object_caps_compare (GstCaps * caps1,
|
||||
GstCaps * caps2);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMFSourceObject, gst_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -244,6 +244,17 @@ gst_mf_stream_media_type_free (GstMFStreamMediaType * media_type)
|
|||
g_free (media_type);
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_caps_func (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
GstMFStreamMediaType *m1, *m2;
|
||||
|
||||
m1 = (GstMFStreamMediaType *) a;
|
||||
m2 = (GstMFStreamMediaType *) b;
|
||||
|
||||
return gst_mf_source_object_caps_compare (m1->caps, m2->caps);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_mf_source_reader_open (GstMFSourceReader * self, IMFActivate * activate)
|
||||
{
|
||||
|
@ -280,13 +291,15 @@ gst_mf_source_reader_open (GstMFSourceReader * self, IMFActivate * activate)
|
|||
self->source = source.Detach ();
|
||||
self->reader = reader.Detach ();
|
||||
|
||||
self->media_types = g_list_sort (self->media_types,
|
||||
(GCompareFunc) compare_caps_func);
|
||||
|
||||
self->supported_caps = gst_caps_new_empty ();
|
||||
|
||||
for (iter = self->media_types; iter; iter = g_list_next (iter)) {
|
||||
GstMFStreamMediaType *mtype = (GstMFStreamMediaType *) iter->data;
|
||||
if (!self->supported_caps)
|
||||
self->supported_caps = gst_caps_ref (mtype->caps);
|
||||
else
|
||||
self->supported_caps =
|
||||
gst_caps_merge (self->supported_caps, gst_caps_ref (mtype->caps));
|
||||
|
||||
gst_caps_append (self->supported_caps, gst_caps_copy (mtype->caps));
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Available output caps %" GST_PTR_FORMAT,
|
||||
|
|
Loading…
Reference in a new issue