mirror of
https://github.com/lvgl/lvgl.git
synced 2026-03-23 13:14:28 +08:00
feat(gstreamer): integrate webrtc plugin (#9799)
Some checks failed
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify GDB constants are up-to-date / verify-gdb-consts (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Some checks failed
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify GDB constants are up-to-date / verify-gdb-consts (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
8fa1c29773
commit
5435384d49
@@ -27,6 +27,7 @@ LVGL's GStreamer implementation provides comprehensive media playback capabiliti
|
||||
* Video4Linux2 (V4L2) camera devices on Linux
|
||||
* Audio capture from ALSA and PulseAudio devices
|
||||
* Test sources for audio and video development
|
||||
* WebRTC streaming for real-time communication applications
|
||||
|
||||
**URI Scheme Support:**
|
||||
|
||||
@@ -42,6 +43,10 @@ Using the URI factory (:c:macro:`LV_GSTREAMER_FACTORY_URI_DECODE`), you can spec
|
||||
|
||||
GStreamer's ``uridecodebin`` automatically selects the appropriate source element and decoder based on the URI scheme and media format.
|
||||
|
||||
.. note::
|
||||
|
||||
WebRTC streaming is supported via a dedicated WebRTC source factory (for example, ``webrtcsrc``) configured with a signalling URI (for example, ``signaller::uri``), and is not provided through :c:macro:`LV_GSTREAMER_FACTORY_URI_DECODE` / ``uridecodebin``.
|
||||
|
||||
**Playback Control:**
|
||||
|
||||
* Play, pause, and stop operations
|
||||
@@ -255,6 +260,15 @@ The GStreamer widget supports various media sources through different factories:
|
||||
"/path/to/video.mp4");
|
||||
|
||||
|
||||
**WebRTC Factory:**
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* WebRTC stream */
|
||||
lv_gstreamer_set_src(streamer, LV_GSTREAMER_FACTORY_WEBRTCSRC,
|
||||
LV_GSTREAMER_PROPERTY_WEBRTCSRC,
|
||||
"ws://signalserver:port/");
|
||||
|
||||
Playback Control
|
||||
----------------
|
||||
|
||||
@@ -326,6 +340,20 @@ Once media is loaded (LV_EVENT_READY), you can access:
|
||||
- Current volume level via ``lv_gstreamer_get_volume()``
|
||||
- Current playback state via ``lv_gstreamer_get_state()``
|
||||
|
||||
WebRTC Notes
|
||||
************
|
||||
|
||||
WebRTC is using the Rust plugin "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs"
|
||||
So to be able to stream to an LVGL player application you will need to run a signaller server and then a simpler pipeline like so:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./gst-webrtc-signalling-server &
|
||||
gst-launch-1.0 videotestsrc pattern=ball ! webrtcsink
|
||||
|
||||
Then, in your LVGL application, configure WebRTC by passing the signalling server URI (for example, ``ws://localhost:8443``) to ``lv_gstreamer_set_src(..., LV_GSTREAMER_PROPERTY_WEBRTCSRC, ...)``.
|
||||
|
||||
|
||||
.. _gstreamer_example:
|
||||
|
||||
Example
|
||||
|
||||
@@ -40,7 +40,11 @@ void lv_example_gstreamer_1(void)
|
||||
* specify various URI schemes as media sources including local files (file://),
|
||||
* web streams (http://, https://), RTSP streams (rtsp://), UDP streams (udp://),
|
||||
* and many others. GStreamer's uridecodebin automatically selects the appropriate
|
||||
* source element and decoder based on the URI scheme and media format. */
|
||||
* source element and decoder based on the URI scheme and media format.
|
||||
* WebRTC streams, however, are provided via a dedicated WebRTC source (webrtcsrc)
|
||||
* configured with a signalling server URI (e.g. ws://[ipsignallerserver]:[port])
|
||||
* through its signaller-related properties, rather than via LV_GSTREAMER_FACTORY_URI_DECODE.
|
||||
*/
|
||||
lv_gstreamer_set_src(event_data.streamer, LV_GSTREAMER_FACTORY_URI_DECODE, LV_GSTREAMER_PROPERTY_URI_DECODE,
|
||||
"https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm");
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ static void gstreamer_update_frame(lv_gstreamer_t * streamer);
|
||||
static lv_result_t gstreamer_make_and_add_to_pipeline(lv_gstreamer_t * streamer,
|
||||
const lv_gstreamer_pipeline_element_t * elements, size_t element_count);
|
||||
static lv_result_t gstreamer_send_state_changed(lv_gstreamer_t * streamer, lv_gstreamer_stream_state_t state);
|
||||
static bool gstreamer_element_has_property(GstElement * element, const char * property_name);
|
||||
static bool gstreamer_set_child_proxy_string(GstElement * element, const char * property_name, const char * value);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -135,31 +137,53 @@ lv_result_t lv_gstreamer_set_src(lv_obj_t * obj, const char * factory_name, cons
|
||||
}
|
||||
|
||||
if(property != NULL && source != NULL) {
|
||||
g_object_set(G_OBJECT(head), property, source, NULL);
|
||||
/* LV_GSTREAMER_PROPERTY_WEBRTCSRC is a child-proxy property path */
|
||||
if(lv_streq(property, LV_GSTREAMER_PROPERTY_WEBRTCSRC)) {
|
||||
if(!gstreamer_set_child_proxy_string(head, property, source)) {
|
||||
gst_object_unref(pipeline);
|
||||
LV_LOG_ERROR("Failed to set '%s' via child proxy", property);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_object_set(G_OBJECT(head), property, source, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* The uri decode source element will automatically handle parsing and decoding for us
|
||||
* for other source types, we need to add a parser and a decoder ourselves element*/
|
||||
if(!lv_streq(LV_GSTREAMER_FACTORY_URI_DECODE, factory_name)) {
|
||||
GstElement * decodebin = gst_element_factory_make("decodebin", "lv_gstreamer_decodebin");
|
||||
if(!decodebin) {
|
||||
gst_object_unref(pipeline);
|
||||
LV_LOG_ERROR("Failed to create decodebin element");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
if(!gst_bin_add(GST_BIN(pipeline), decodebin)) {
|
||||
gst_object_unref(decodebin);
|
||||
gst_object_unref(pipeline);
|
||||
LV_LOG_ERROR("Failed to add decodebin element to pipeline");
|
||||
return LV_RESULT_INVALID;
|
||||
/* webrtcsrc plugins require its own handling to be able to connect on the first available video stream */
|
||||
if(lv_streq(LV_GSTREAMER_FACTORY_WEBRTCSRC, factory_name)) {
|
||||
LV_LOG_INFO("Setting up webrtc pipeline");
|
||||
if(gstreamer_element_has_property(head, "connect-to-first-producer")) {
|
||||
g_object_set(G_OBJECT(head), "connect-to-first-producer", TRUE, NULL);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("webrtcsrc property 'connect-to-first-producer' is not available in this plugin build");
|
||||
}
|
||||
}
|
||||
else {
|
||||
GstElement * decodebin = gst_element_factory_make("decodebin", "lv_gstreamer_decodebin");
|
||||
if(!decodebin) {
|
||||
gst_object_unref(pipeline);
|
||||
LV_LOG_ERROR("Failed to create decodebin element");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
if(!gst_bin_add(GST_BIN(pipeline), decodebin)) {
|
||||
gst_object_unref(decodebin);
|
||||
gst_object_unref(pipeline);
|
||||
LV_LOG_ERROR("Failed to add decodebin element to pipeline");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
if(!gst_element_link(head, decodebin)) {
|
||||
gst_object_unref(pipeline);
|
||||
LV_LOG_ERROR("Failed to link source with parsebin elements");
|
||||
return LV_RESULT_INVALID;
|
||||
if(!gst_element_link(head, decodebin)) {
|
||||
gst_object_unref(pipeline);
|
||||
LV_LOG_ERROR("Failed to link source with parsebin elements");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
head = decodebin;
|
||||
}
|
||||
head = decodebin;
|
||||
}
|
||||
|
||||
/* At this point we don't yet know the input format
|
||||
@@ -412,7 +436,18 @@ static lv_result_t gstreamer_poll_bus(lv_gstreamer_t * streamer)
|
||||
GError * err;
|
||||
gchar * debug;
|
||||
gst_message_parse_error(msg, &err, &debug);
|
||||
LV_LOG_ERROR("GStreamer error: %s", err->message);
|
||||
GstObject * src = GST_MESSAGE_SRC(msg);
|
||||
const gchar * name = NULL;
|
||||
if(src != NULL) {
|
||||
name = GST_OBJECT_NAME(src);
|
||||
}
|
||||
if(!name) {
|
||||
name = "unknown";
|
||||
}
|
||||
LV_LOG_ERROR("GStreamer error from %s: %s", name, err->message);
|
||||
if(debug && debug[0] != '\0') {
|
||||
LV_LOG_ERROR("GStreamer error details: %s", debug);
|
||||
}
|
||||
g_error_free(err);
|
||||
g_free(debug);
|
||||
break;
|
||||
@@ -563,11 +598,50 @@ static lv_result_t gstreamer_make_and_add_to_pipeline(lv_gstreamer_t * streamer,
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
static bool gstreamer_element_has_property(GstElement * element, const char * property_name)
|
||||
{
|
||||
LV_ASSERT_NULL(element);
|
||||
LV_ASSERT_NULL(property_name);
|
||||
|
||||
GObjectClass * klass = G_OBJECT_GET_CLASS(element);
|
||||
return g_object_class_find_property(klass, property_name) != NULL;
|
||||
}
|
||||
|
||||
static bool gstreamer_set_child_proxy_string(GstElement * element, const char * property_name, const char * value)
|
||||
{
|
||||
LV_ASSERT_NULL(element);
|
||||
LV_ASSERT_NULL(property_name);
|
||||
LV_ASSERT_NULL(value);
|
||||
|
||||
if(!GST_IS_CHILD_PROXY(element)) {
|
||||
LV_LOG_WARN("Element does not support child proxy for property '%s'", property_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
GObject * target = NULL;
|
||||
GParamSpec * pspec = NULL;
|
||||
if(!gst_child_proxy_lookup(GST_CHILD_PROXY(element), property_name, &target, &pspec)) {
|
||||
LV_LOG_WARN("Property '%s' not found in child proxy", property_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(target) {
|
||||
g_object_unref(target);
|
||||
}
|
||||
|
||||
GValue gvalue = G_VALUE_INIT;
|
||||
g_value_init(&gvalue, G_TYPE_STRING);
|
||||
g_value_set_string(&gvalue, value);
|
||||
gst_child_proxy_set_property(GST_CHILD_PROXY(element), property_name, &gvalue);
|
||||
g_value_unset(&gvalue);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void on_decode_pad_added(GstElement * element, GstPad * pad, gpointer user_data)
|
||||
{
|
||||
LV_UNUSED(element);
|
||||
lv_gstreamer_t * streamer = (lv_gstreamer_t *)user_data;
|
||||
GstCaps * caps = gst_pad_get_current_caps(pad);
|
||||
GstCaps * caps = gst_pad_query_caps(pad, NULL);
|
||||
|
||||
GstStructure * structure = gst_caps_get_structure(caps, 0);
|
||||
const gchar * name = gst_structure_get_name(structure);
|
||||
|
||||
@@ -62,6 +62,9 @@ extern "C" {
|
||||
#define LV_GSTREAMER_FACTORY_APP "appsrc"
|
||||
#define LV_GSTREAMER_PROPERTY_APP NULL
|
||||
|
||||
#define LV_GSTREAMER_FACTORY_WEBRTCSRC "webrtcsrc"
|
||||
#define LV_GSTREAMER_PROPERTY_WEBRTCSRC "signaller::uri"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
Reference in New Issue
Block a user