mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-18 13:25:56 +00:00
Updated python port of Tutorial 2 with fixed line numbers
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-docs/-/merge_requests/126>
This commit is contained in:
parent
be19c30254
commit
ddbe5ce83b
4 changed files with 263 additions and 196 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,6 @@
|
|||
/built_doc
|
||||
.vscode
|
||||
build/
|
||||
/hotdoc-private*
|
||||
/.hotdoc.d
|
||||
/*.stamp
|
||||
|
|
64
examples/tutorials/python/basic-tutorial-2.py
Normal file
64
examples/tutorials/python/basic-tutorial-2.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import gi
|
||||
import logging
|
||||
|
||||
gi.require_version("GLib", "2.0")
|
||||
gi.require_version("GObject", "2.0")
|
||||
gi.require_version("Gst", "1.0")
|
||||
|
||||
from gi.repository import Gst, GLib, GObject
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG, format="[%(name)s] [%(levelname)8s] - %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Initialize GStreamer
|
||||
Gst.init(sys.argv[1:])
|
||||
|
||||
# Create the elements
|
||||
source = Gst.ElementFactory.make("videotestsrc", "source")
|
||||
sink = Gst.ElementFactory.make("autovideosink", "sink")
|
||||
|
||||
# Create the empty pipeline
|
||||
pipeline = Gst.Pipeline.new("test-pipeline")
|
||||
|
||||
if not pipeline or not source or not sink:
|
||||
logger.error("Not all elements could be created.")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Build the pipeline
|
||||
pipeline.add(source, sink)
|
||||
if not source.link(sink):
|
||||
logger.error("Elements could not be linked.")
|
||||
sys.exit(1)
|
||||
|
||||
# Modify the source's properties
|
||||
source.props.pattern = 0
|
||||
# Can alternatively be done using `source.set_property("pattern",0)`
|
||||
# or using `Gst.util_set_object_arg(source, "pattern", 0)`
|
||||
|
||||
# Start playing
|
||||
ret = pipeline.set_state(Gst.State.PLAYING)
|
||||
if ret == Gst.StateChangeReturn.FAILURE:
|
||||
logger.error("Unable to set the pipeline to the playing state.")
|
||||
sys.exit(1)
|
||||
|
||||
# Wait for EOS or error
|
||||
bus = pipeline.get_bus()
|
||||
msg = bus.timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS)
|
||||
|
||||
# Parse message
|
||||
if msg:
|
||||
if msg.type == Gst.MessageType.ERROR:
|
||||
err, debug_info = msg.parse_error()
|
||||
logger.error(f"Error received from element {msg.src.get_name()}: {err.message}")
|
||||
logger.error(f"Debugging information: {debug_info if debug_info else 'none'}")
|
||||
elif msg.type == Gst.MessageType.EOS:
|
||||
logger.info("End-Of-Stream reached.")
|
||||
else:
|
||||
# This should not happen as we only asked for ERRORs and EOS
|
||||
logger.error("Unexpected message received.")
|
||||
|
||||
pipeline.set_state(Gst.State.NULL)
|
BIN
images/basic-concepts-pipeline.png
Normal file
BIN
images/basic-concepts-pipeline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -1,9 +1,12 @@
|
|||
---
|
||||
short-description: Gstreamer Elements, Pipeline and the Bus
|
||||
...
|
||||
|
||||
{{ ALERT_JS.md }}
|
||||
|
||||
# Basic tutorial 2: GStreamer concepts
|
||||
|
||||
|
||||
{{ ALERT_PY.md }}
|
||||
|
||||
{{ ALERT_JS.md }}
|
||||
|
||||
## Goal
|
||||
|
||||
|
@ -22,102 +25,40 @@ and linking them all together. In the process, we will learn:
|
|||
|
||||
## Manual Hello World
|
||||
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
Copy this code into a text file named `basic-tutorial-2.c` (or find it
|
||||
in your GStreamer installation).
|
||||
|
||||
**basic-tutorial-2.c**
|
||||
|
||||
``` c
|
||||
#include <gst/gst.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
GstElement *pipeline, *source, *sink;
|
||||
GstBus *bus;
|
||||
GstMessage *msg;
|
||||
GstStateChangeReturn ret;
|
||||
|
||||
/* Initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
/* Create the elements */
|
||||
source = gst_element_factory_make ("videotestsrc", "source");
|
||||
sink = gst_element_factory_make ("autovideosink", "sink");
|
||||
|
||||
/* Create the empty pipeline */
|
||||
pipeline = gst_pipeline_new ("test-pipeline");
|
||||
|
||||
if (!pipeline || !source || !sink) {
|
||||
g_printerr ("Not all elements could be created.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Build the pipeline */
|
||||
gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
|
||||
if (gst_element_link (source, sink) != TRUE) {
|
||||
g_printerr ("Elements could not be linked.\n");
|
||||
gst_object_unref (pipeline);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Modify the source's properties */
|
||||
g_object_set (source, "pattern", 0, NULL);
|
||||
|
||||
/* Start playing */
|
||||
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||
g_printerr ("Unable to set the pipeline to the playing state.\n");
|
||||
gst_object_unref (pipeline);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wait until error or EOS */
|
||||
bus = gst_element_get_bus (pipeline);
|
||||
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
|
||||
|
||||
/* Parse message */
|
||||
if (msg != NULL) {
|
||||
GError *err;
|
||||
gchar *debug_info;
|
||||
|
||||
switch (GST_MESSAGE_TYPE (msg)) {
|
||||
case GST_MESSAGE_ERROR:
|
||||
gst_message_parse_error (msg, &err, &debug_info);
|
||||
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
|
||||
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
|
||||
g_clear_error (&err);
|
||||
g_free (debug_info);
|
||||
break;
|
||||
case GST_MESSAGE_EOS:
|
||||
g_print ("End-Of-Stream reached.\n");
|
||||
break;
|
||||
default:
|
||||
/* We should not reach here because we only asked for ERRORs and EOS */
|
||||
g_printerr ("Unexpected message received.\n");
|
||||
break;
|
||||
}
|
||||
gst_message_unref (msg);
|
||||
}
|
||||
|
||||
/* Free resources */
|
||||
gst_object_unref (bus);
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
{{ tutorials/basic-tutorial-2.c }}
|
||||
|
||||
> ![Information](images/icons/emoticons/information.svg)
|
||||
> Need help?
|
||||
>
|
||||
> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux:
|
||||
> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux], [Mac OS X] or [Windows], or use this specific command on Linux:
|
||||
>
|
||||
> `` gcc basic-tutorial-2.c -o basic-tutorial-2 `pkg-config --cflags --libs gstreamer-1.0` ``
|
||||
>
|
||||
>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run).
|
||||
>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux][1], [Mac OS X][[2]] or [Windows][3].
|
||||
>
|
||||
>This tutorial opens a window and displays a test pattern, without audio
|
||||
>
|
||||
>Required libraries: `gstreamer-1.0`
|
||||
{{ END_LANG.md }}
|
||||
|
||||
|
||||
{{ PY.md }}
|
||||
Copy this code into a text file named `basic-tutorial-2.py` (or find it
|
||||
in your GStreamer installation).
|
||||
**basic-tutorial-2.py**
|
||||
|
||||
{{ tutorials/python/basic-tutorial-2.py }}
|
||||
|
||||
Then, you can run the file with `python3 basic-tutorial-2.py`
|
||||
{{ END_LANG.md }}
|
||||
|
||||
|
||||
|
||||
## Walkthrough
|
||||
|
||||
|
@ -134,68 +75,84 @@ to the sink elements (data consumers), passing through filter elements.
|
|||
We will skip GStreamer initialization, since it is the same as the
|
||||
previous tutorial:
|
||||
|
||||
``` c
|
||||
/* Create the elements */
|
||||
source = gst_element_factory_make ("videotestsrc", "source");
|
||||
sink = gst_element_factory_make ("autovideosink", "sink");
|
||||
```
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
{{ tutorials/basic-tutorial-2.c[13:16] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
{{ PY.md }}
|
||||
{{ tutorials/python/basic-tutorial-2.py[18:21] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
|
||||
As seen in this code, new elements can be created
|
||||
with `gst_element_factory_make()`. The first parameter is the type of
|
||||
with [gst_element_factory_make]\(). The first parameter is the type of
|
||||
element to create ([Basic tutorial 14: Handy
|
||||
elements](tutorials/basic/handy-elements.md) shows a
|
||||
elements] shows a
|
||||
few common types, and [Basic tutorial 10: GStreamer
|
||||
tools](tutorials/basic/gstreamer-tools.md) shows how to
|
||||
tools] shows how to
|
||||
obtain the list of all available types). The second parameter is the
|
||||
name we want to give to this particular instance. Naming your elements
|
||||
is useful to retrieve them later if you didn't keep a pointer (and for
|
||||
more meaningful debug output). If you pass NULL for the name, however,
|
||||
more meaningful debug output). If you pass [NULL] for the name, however,
|
||||
GStreamer will provide a unique name for you.
|
||||
|
||||
For this tutorial we create two elements: a `videotestsrc` and
|
||||
an `autovideosink`.
|
||||
For this tutorial we create two elements: a [videotestsrc] and
|
||||
an [autovideosink]. There are no filter elements. Hence, the pipeline would
|
||||
look like the following:
|
||||
|
||||
`videotestsrc` is a source element (it produces data), which creates a
|
||||
![](images/basic-concepts-pipeline.png)
|
||||
|
||||
**Figure 2**. Pipeline built in this tutorial
|
||||
|
||||
[videotestsrc] is a source element (it produces data), which creates a
|
||||
test video pattern. This element is useful for debugging purposes (and
|
||||
tutorials) and is not usually found in real applications.
|
||||
|
||||
`autovideosink` is a sink element (it consumes data), which displays on
|
||||
[autovideosink] is a sink element (it consumes data), which displays on
|
||||
a window the images it receives. There exist several video sinks,
|
||||
depending on the operating system, with a varying range of capabilities.
|
||||
`autovideosink` automatically selects and instantiates the best one, so
|
||||
[autovideosink] automatically selects and instantiates the best one, so
|
||||
you do not have to worry with the details, and your code is more
|
||||
platform-independent.
|
||||
|
||||
### Pipeline creation
|
||||
|
||||
``` c
|
||||
/* Create the empty pipeline */
|
||||
pipeline = gst_pipeline_new ("test-pipeline");
|
||||
```
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
{{ tutorials/basic-tutorial-2.c[17:19] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
{{ PY.md }}
|
||||
{{ tutorials/python/basic-tutorial-2.py[22:24] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
All elements in GStreamer must typically be contained inside a pipeline
|
||||
before they can be used, because it takes care of some clocking and
|
||||
messaging functions. We create the pipeline with `gst_pipeline_new()`.
|
||||
messaging functions. We create the pipeline with [gst_pipeline_new]\().
|
||||
|
||||
``` c
|
||||
/* Build the pipeline */
|
||||
gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
|
||||
if (gst_element_link (source, sink) != TRUE) {
|
||||
g_printerr ("Elements could not be linked.\n");
|
||||
gst_object_unref (pipeline);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
{{ tutorials/basic-tutorial-2.c[25:32] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
A pipeline is a particular type of `bin`, which is the element used to
|
||||
{{ PY.md }}
|
||||
{{ tutorials/python/basic-tutorial-2.py[30:35] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
|
||||
A pipeline is a particular type of [bin], which is the element used to
|
||||
contain other elements. Therefore all methods which apply to bins also
|
||||
apply to pipelines. In our case, we call `gst_bin_add_many()` to add the
|
||||
apply to pipelines.
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
In our case, we call [gst_bin_add_many]\() to add the
|
||||
elements to the pipeline (mind the cast). This function accepts a list
|
||||
of elements to be added, ending with `NULL`. Individual elements can be
|
||||
added with `gst_bin_add()`.
|
||||
|
||||
of elements to be added, ending with [NULL]. Individual elements can be
|
||||
added with [gst_bin_add]\().
|
||||
{{ END_LANG.md }}
|
||||
{{ PY.md }}
|
||||
In our case, we call [gst_bin_add]\() to add elements to the pipeline.
|
||||
The function accepts any number of Gst Elements as its arguments
|
||||
{{ END_LANG.md }}
|
||||
These elements, however, are not linked with each other yet. For this,
|
||||
we need to use `gst_element_link()`. Its first parameter is the source,
|
||||
we need to use [gst_element_link]\(). Its first parameter is the source,
|
||||
and the second one the destination. The order counts, because links must
|
||||
be established following the data flow (this is, from source elements to
|
||||
sink elements). Keep in mind that only elements residing in the same bin
|
||||
|
@ -204,33 +161,66 @@ trying to link them!
|
|||
|
||||
### Properties
|
||||
|
||||
``` c
|
||||
/* Modify the source's properties */
|
||||
g_object_set (source, "pattern", 0, NULL);
|
||||
```
|
||||
GStreamer elements are all a particular kind of [GObject], which is the
|
||||
entity offering **property** facilities.
|
||||
|
||||
Most GStreamer elements have customizable properties: named attributes
|
||||
that can be modified to change the element's behavior (writable
|
||||
properties) or inquired to find out about the element's internal state
|
||||
(readable properties).
|
||||
|
||||
Properties are read from with `g_object_get()` and written to
|
||||
with `g_object_set()`.
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
Properties are read from with [g_object_get]\() and written to
|
||||
with [g_object_set]\().
|
||||
|
||||
`g_object_set()` accepts a `NULL`-terminated list of property-name,
|
||||
[g_object_set]\() accepts a [NULL]-terminated list of property-name,
|
||||
property-value pairs, so multiple properties can be changed in one go.
|
||||
|
||||
GStreamer elements are all a particular kind of `GObject`, which is the
|
||||
entity offering property facilities. This is why the property handling
|
||||
methods have the `g_` prefix.
|
||||
This is why the property handling methods have the `g_` prefix.
|
||||
{{ END_LANG.md }}
|
||||
|
||||
The line of code above changes the “pattern” property of `videotestsrc`,
|
||||
{{ PY.md }}
|
||||
For understanding how to get and set [properties](https://pygobject.readthedocs.io/en/latest/guide/api/properties.html),
|
||||
let us assume we have a Gst Element `source` with a property `pattern`
|
||||
|
||||
The current state of a property can be fetched by either:
|
||||
1. Accessing the property as an attribute of the `props` attribute of an
|
||||
element. Ex: `_ = source.props.pattern` to print it on the screen
|
||||
2. Using the `get_property` method of the element.
|
||||
Ex: `_ = source.get_property("pattern")`
|
||||
|
||||
And properties can be set by one of three methods:
|
||||
1. Setting the property as an attribute of the `props` attribute.
|
||||
Ex: `source.props.pattern = 1` or equivalently `source.props.pattern="snow"`
|
||||
2. Using the `set_property` method of the element.
|
||||
Ex: `source.set_property("pattern", 1)` or equivalently `source.set_property("pattern", "snow")`
|
||||
3. Using the `Gst.util_set_object_arg()` method. This mode also allows you to
|
||||
pass Gst Caps and other structures. Ex: `Gst.util_set_object_arg(source, "pattern", "snow")`,
|
||||
or equivalently, `Gst.util_set_object_arg(source, "pattern", 1)`
|
||||
|
||||
Note: In all three methods of setting a property, if a string is passed as
|
||||
the value to set, it has to be the serialized version of a flag or value
|
||||
(using [gst_value_serialize]\())
|
||||
{{ END_LANG.md }}
|
||||
|
||||
Coming back to what's in the example above,
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
{{ tutorials/basic-tutorial-2.c[33:35] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
{{ PY.md }}
|
||||
{{ tutorials/python/basic-tutorial-2.py[36:40] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
|
||||
The line of code above changes the “pattern” property of [videotestsrc],
|
||||
which controls the type of test video the element outputs. Try different
|
||||
values!
|
||||
|
||||
The names and possible values of all the properties an element exposes
|
||||
can be found using the gst-inspect-1.0 tool described in [Basic tutorial 10:
|
||||
GStreamer tools](tutorials/basic/gstreamer-tools.md).
|
||||
GStreamer tools] or alternatively in the docs for that element
|
||||
([here](GstVideoTestSrcPattern) in the case of videotestsrc).
|
||||
|
||||
### Error checking
|
||||
|
||||
|
@ -238,65 +228,41 @@ At this point, we have the whole pipeline built and setup, and the rest
|
|||
of the tutorial is very similar to the previous one, but we are going to
|
||||
add more error checking:
|
||||
|
||||
``` c
|
||||
/* Start playing */
|
||||
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||
g_printerr ("Unable to set the pipeline to the playing state.\n");
|
||||
gst_object_unref (pipeline);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
{{ tutorials/basic-tutorial-2.c[36:43] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
We call `gst_element_set_state()`, but this time we check its return
|
||||
{{ PY.md }}
|
||||
{{ tutorials/python/basic-tutorial-2.py[41:46] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
We call [gst_element_set_state]\(), but this time we check its return
|
||||
value for errors. Changing states is a delicate process and a few more
|
||||
details are given in [Basic tutorial 3: Dynamic
|
||||
pipelines](tutorials/basic/dynamic-pipelines.md).
|
||||
pipelines].
|
||||
|
||||
``` c
|
||||
/* Wait until error or EOS */
|
||||
bus = gst_element_get_bus (pipeline);
|
||||
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
|
||||
{{ C+JS_FALLBACK.md }}
|
||||
{{ tutorials/basic-tutorial-2.c[44:75] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
/* Parse message */
|
||||
if (msg != NULL) {
|
||||
GError *err;
|
||||
gchar *debug_info;
|
||||
{{ PY.md }}
|
||||
{{ tutorials/python/basic-tutorial-2.py[47:62] }}
|
||||
{{ END_LANG.md }}
|
||||
|
||||
switch (GST_MESSAGE_TYPE (msg)) {
|
||||
case GST_MESSAGE_ERROR:
|
||||
gst_message_parse_error (msg, &err, &debug_info);
|
||||
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
|
||||
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
|
||||
g_clear_error (&err);
|
||||
g_free (debug_info);
|
||||
break;
|
||||
case GST_MESSAGE_EOS:
|
||||
g_print ("End-Of-Stream reached.\n");
|
||||
break;
|
||||
default:
|
||||
/* We should not reach here because we only asked for ERRORs and EOS */
|
||||
g_printerr ("Unexpected message received.\n");
|
||||
break;
|
||||
}
|
||||
gst_message_unref (msg);
|
||||
}
|
||||
```
|
||||
|
||||
`gst_bus_timed_pop_filtered()` waits for execution to end and returns
|
||||
with a `GstMessage` which we previously ignored. We
|
||||
asked `gst_bus_timed_pop_filtered()` to return when GStreamer
|
||||
encountered either an error condition or an `EOS`, so we need to check
|
||||
[gst_bus_timed_pop_filtered]\() waits for execution to end and returns
|
||||
with a [GstMessage] which we previously ignored. We
|
||||
asked [gst_bus_timed_pop_filtered]\() to return when GStreamer
|
||||
encountered either an error condition or an [EOS], so we need to check
|
||||
which one happened, and print a message on screen (Your application will
|
||||
probably want to undertake more complex actions).
|
||||
|
||||
`GstMessage` is a very versatile structure which can deliver virtually
|
||||
[GstMessage] is a very versatile structure which can deliver virtually
|
||||
any kind of information. Fortunately, GStreamer provides a series of
|
||||
parsing functions for each kind of message.
|
||||
|
||||
In this case, once we know the message contains an error (by using the
|
||||
`GST_MESSAGE_TYPE()` macro), we can use
|
||||
`gst_message_parse_error()` which returns a GLib `GError` error
|
||||
[GST_MESSAGE_TYPE]\() macro), we can use
|
||||
[gst_message_parse_error]\() which returns a GLib [GError] error
|
||||
structure and a string useful for debugging. Examine the code to see how
|
||||
these are used and freed afterward.
|
||||
|
||||
|
@ -304,48 +270,48 @@ these are used and freed afterward.
|
|||
|
||||
At this point it is worth introducing the GStreamer bus a bit more
|
||||
formally. It is the object responsible for delivering to the application
|
||||
the `GstMessage`s generated by the elements, in order and to the
|
||||
the [GstMessage]s generated by the elements, in order and to the
|
||||
application thread. This last point is important, because the actual
|
||||
streaming of media is done in another thread than the application.
|
||||
|
||||
Messages can be extracted from the bus synchronously with
|
||||
`gst_bus_timed_pop_filtered()` and its siblings, or asynchronously,
|
||||
[gst_bus_timed_pop_filtered]\() and its siblings, or asynchronously,
|
||||
using signals (shown in the next tutorial). Your application should
|
||||
always keep an eye on the bus to be notified of errors and other
|
||||
playback-related issues.
|
||||
|
||||
The rest of the code is the cleanup sequence, which is the same as
|
||||
in [Basic tutorial 1: Hello
|
||||
world!](tutorials/basic/hello-world.md).
|
||||
world!].
|
||||
|
||||
## Exercise
|
||||
|
||||
If you feel like practicing, try this exercise: Add a video filter
|
||||
element in between the source and the sink of this pipeline. Use
|
||||
`vertigotv` for a nice effect. You will need to create it, add it to the
|
||||
[vertigotv] for a nice effect. You will need to create it, add it to the
|
||||
pipeline, and link it with the other elements.
|
||||
|
||||
Depending on your platform and available plugins, you might get a
|
||||
“negotiation” error, because the sink does not understand what the
|
||||
filter is producing (more about negotiation in [Basic tutorial 6: Media
|
||||
formats and Pad
|
||||
Capabilities](tutorials/basic/media-formats-and-pad-capabilities.md)).
|
||||
In this case, try to add an element called `videoconvert` after the
|
||||
Capabilities]).
|
||||
In this case, try to add an element called [videoconvert] after the
|
||||
filter (this is, build a pipeline of 4 elements. More on
|
||||
`videoconvert` in [Basic tutorial 14: Handy
|
||||
elements](tutorials/basic/handy-elements.md)).
|
||||
[videoconvert] in [Basic tutorial 14: Handy
|
||||
elements]).
|
||||
|
||||
## Conclusion
|
||||
|
||||
This tutorial showed:
|
||||
|
||||
- How to create elements with `gst_element_factory_make()`
|
||||
- How to create elements with [gst_element_factory_make]\()
|
||||
|
||||
- How to create an empty pipeline with `gst_pipeline_new()`
|
||||
- How to create an empty pipeline with [gst_pipeline_new]\()
|
||||
|
||||
- How to add elements to the pipeline with `gst_bin_add_many()`
|
||||
- How to add elements to the pipeline with [gst_bin_add_many]\()
|
||||
|
||||
- How to link the elements with each other with `gst_element_link()`
|
||||
- How to link the elements with each other with [gst_element_link]\()
|
||||
|
||||
This concludes the first of the two tutorials devoted to basic GStreamer
|
||||
concepts. The second one comes next.
|
||||
|
@ -354,3 +320,38 @@ Remember that attached to this page you should find the complete source
|
|||
code of the tutorial and any accessory files needed to build it.
|
||||
|
||||
It has been a pleasure having you here, and see you soon!
|
||||
|
||||
[Linux]: installing/on-linux.md#InstallingonLinux-Build
|
||||
[Mac OS X]: installing/on-mac-osx.md#InstallingonMacOSX-Build
|
||||
[Windows]: installing/on-windows.md#InstallingonWindows-Build
|
||||
[1]: installing/on-linux.md#InstallingonLinux-Run
|
||||
[2]: installing/on-mac-osx.md#InstallingonMacOSX-Run
|
||||
[3]: installing/on-windows.md#InstallingonWindows-Run
|
||||
[Basic tutorial 14: Handy elements]: tutorials/basic/handy-elements.md
|
||||
[Basic tutorial 10: GStreamer tools]: tutorials/basic/gstreamer-tools.md
|
||||
[Basic tutorial 10: GStreamer tools]: tutorials/basic/gstreamer-tools.md
|
||||
[Basic tutorial 3: Dynamic pipelines]: tutorials/basic/dynamic-pipelines.md
|
||||
[Basic tutorial 1: Hello world!]: tutorials/basic/hello-world.md
|
||||
[Basic tutorial 6: Media formats and Pad Capabilities]: tutorials/basic/media-formats-and-pad-capabilities.md
|
||||
[gst_element_factory_make]: gst_element_factory_make
|
||||
[videotestsrc]: videotestsrc
|
||||
[autovideosink]: autovideosink
|
||||
[bin]: GstBin
|
||||
[NULL]: NULL
|
||||
[gst_bin_add_many]: gst_bin_add_many
|
||||
[gst_bin_add]: gst_bin_add
|
||||
[gst_element_link]: gst_element_link
|
||||
[GObject]: GObject
|
||||
[gst_value_serialize]: gst_value_serialize
|
||||
[g_object_get]: g_object_get
|
||||
[g_object_set]: g_object_set
|
||||
[gst_element_set_state]: gst_element_set_state
|
||||
[gst_bus_timed_pop_filtered]: gst_bus_timed_pop_filtered
|
||||
[GstMessage]: GstMessage
|
||||
[EOS]: GST_MESSAGE_EOS
|
||||
[GST_MESSAGE_TYPE]: GST_MESSAGE_TYPE
|
||||
[gst_message_parse_error]: gst_message_parse_error
|
||||
[GError]: GError
|
||||
[vertigotv]: vertigotv
|
||||
[videoconvert]: videoconvert
|
||||
[gst_pipeline_new]: gst_pipeline_new
|
Loading…
Reference in a new issue