mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-28 18:18:38 +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 "mediacapturewrapper.h"
|
||||||
#include <memorybuffer.h>
|
#include <memorybuffer.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
using namespace Microsoft::WRL::Wrappers;
|
using namespace Microsoft::WRL::Wrappers;
|
||||||
|
@ -161,6 +162,13 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -232,30 +240,33 @@ gst_mf_capture_winrt_thread_func (GstMFCaptureWinRT * self)
|
||||||
goto run_loop;
|
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);
|
self->capture->SetSourceGroup(*target_group);
|
||||||
|
|
||||||
for (auto iter: target_group->source_list_) {
|
std::sort (target_group->source_list_.begin (),
|
||||||
if (!self->supported_caps)
|
target_group->source_list_.end (), winrt_compare_caps_func);
|
||||||
self->supported_caps = gst_caps_ref (iter.caps_);
|
|
||||||
else
|
self->supported_caps = gst_caps_new_empty ();
|
||||||
self->supported_caps =
|
|
||||||
gst_caps_merge (self->supported_caps, gst_caps_ref (iter.caps_));
|
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,
|
GST_DEBUG_OBJECT (self, "Available output caps %" GST_PTR_FORMAT,
|
||||||
self->supported_caps);
|
self->supported_caps);
|
||||||
|
|
||||||
source->opened = !!self->supported_caps;
|
source->opened = TRUE;
|
||||||
|
|
||||||
if (source->opened) {
|
g_free (source->device_path);
|
||||||
g_free (source->device_path);
|
source->device_path = g_strdup (target_group->id_.c_str());
|
||||||
source->device_path = g_strdup (target_group->id_.c_str());
|
|
||||||
|
|
||||||
g_free (source->device_name);
|
g_free (source->device_name);
|
||||||
source->device_name = g_strdup (target_group->display_name_.c_str());
|
source->device_name = g_strdup (target_group->display_name_.c_str());
|
||||||
|
|
||||||
source->device_index = index;
|
source->device_index = index;
|
||||||
}
|
|
||||||
|
|
||||||
run_loop:
|
run_loop:
|
||||||
GST_DEBUG_OBJECT (self, "Starting main loop");
|
GST_DEBUG_OBJECT (self, "Starting main loop");
|
||||||
|
|
|
@ -338,3 +338,64 @@ gst_mf_source_object_new (GstMFSourceType type, gint device_index,
|
||||||
|
|
||||||
return NULL;
|
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_name,
|
||||||
const gchar * device_path);
|
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_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMFSourceObject, gst_object_unref)
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -244,6 +244,17 @@ gst_mf_stream_media_type_free (GstMFStreamMediaType * media_type)
|
||||||
g_free (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
|
static gboolean
|
||||||
gst_mf_source_reader_open (GstMFSourceReader * self, IMFActivate * activate)
|
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->source = source.Detach ();
|
||||||
self->reader = reader.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)) {
|
for (iter = self->media_types; iter; iter = g_list_next (iter)) {
|
||||||
GstMFStreamMediaType *mtype = (GstMFStreamMediaType *) iter->data;
|
GstMFStreamMediaType *mtype = (GstMFStreamMediaType *) iter->data;
|
||||||
if (!self->supported_caps)
|
|
||||||
self->supported_caps = gst_caps_ref (mtype->caps);
|
gst_caps_append (self->supported_caps, gst_caps_copy (mtype->caps));
|
||||||
else
|
|
||||||
self->supported_caps =
|
|
||||||
gst_caps_merge (self->supported_caps, gst_caps_ref (mtype->caps));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Available output caps %" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (self, "Available output caps %" GST_PTR_FORMAT,
|
||||||
|
|
Loading…
Reference in a new issue