In this tutorial we show how to use a stream to capture a stream of video frames.
Even though we are now working with a different media type and we are capturing instead of playback, you will see that this example is very similar to Tutorial - Part 4: Playing A Tone.
#include <spa/param/video/format-utils.h>
#include <spa/param/video/type-info.h>
struct data {
};
static void on_process(void *userdata)
{
struct data *data = userdata;
return;
}
return;
}
static void on_param_changed(
void *userdata, uint32_t
id,
const struct spa_pod *param)
{
struct data *data = userdata;
return;
&data->format.media_type,
&data->format.media_subtype) < 0)
return;
return;
return;
printf("got video format:\n");
printf(" format: %d (%s)\n", data->format.info.raw.format,
data->format.info.raw.format));
printf(" size: %dx%d\n", data->format.info.raw.size.width,
data->format.info.raw.size.height);
printf(" framerate: %d/%d\n", data->format.info.raw.framerate.num,
data->format.info.raw.framerate.denom);
}
.param_changed = on_param_changed,
.process = on_process,
};
int main(int argc, char *argv[])
{
struct data data = { 0, };
uint8_t buffer[1024];
NULL);
if (argc > 1)
"video-capture",
props,
&stream_events,
&data);
params, 1);
return 0;
}
#define PW_ID_ANY
Definition: core.h:66
#define PW_KEY_MEDIA_TYPE
Media.
Definition: src/pipewire/keys.h:431
#define PW_KEY_TARGET_OBJECT
a target object to link to.
Definition: src/pipewire/keys.h:496
#define PW_KEY_MEDIA_ROLE
Role: Movie, Music, Camera, Screen, Communication, Game, Notification, DSP, Production,...
Definition: src/pipewire/keys.h:437
#define PW_KEY_MEDIA_CATEGORY
Media Category: Playback, Capture, Duplex, Monitor, Manager.
Definition: src/pipewire/keys.h:434
#define pw_log_warn(...)
Definition: src/pipewire/log.h:143
void pw_main_loop_destroy(struct pw_main_loop *loop)
Destroy a loop.
Definition: main-loop.c:70
int pw_main_loop_run(struct pw_main_loop *loop)
Run a main loop.
Definition: main-loop.c:119
struct pw_main_loop * pw_main_loop_new(const struct spa_dict *props)
Create a new main loop.
Definition: main-loop.c:60
struct pw_loop * pw_main_loop_get_loop(struct pw_main_loop *loop)
Get the loop implementation.
Definition: main-loop.c:93
void pw_init(int *argc, char **argv[])
Initialize PipeWire.
Definition: pipewire.c:555
#define PW_DIRECTION_INPUT
Definition: port.h:48
struct pw_properties * pw_properties_new(const char *key,...) 1
Make a new properties object.
Definition: properties.c:84
int pw_properties_set(struct pw_properties *properties, const char *key, const char *value)
Set a property value.
Definition: properties.c:421
int pw_stream_connect(struct pw_stream *stream, enum pw_direction direction, uint32_t target_id, enum pw_stream_flags flags, const struct spa_pod **params, uint32_t n_params)
Connect a stream for input or output on port_path.
Definition: stream.c:1879
struct pw_buffer * pw_stream_dequeue_buffer(struct pw_stream *stream)
Get a buffer that can be filled for playback streams or consumed for capture streams.
Definition: stream.c:2381
int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer)
Submit a buffer for playback or recycle a buffer for capture.
Definition: stream.c:2409
struct pw_stream * pw_stream_new_simple(struct pw_loop *loop, const char *name, struct pw_properties *props, const struct pw_stream_events *events, void *data)
Definition: stream.c:1578
#define PW_VERSION_STREAM_EVENTS
Definition: stream.h:321
void pw_stream_destroy(struct pw_stream *stream)
Destroy a stream.
Definition: stream.c:1672
@ PW_STREAM_FLAG_MAP_BUFFERS
mmap the buffers except DmaBuf
Definition: stream.h:369
@ PW_STREAM_FLAG_AUTOCONNECT
try to automatically connect this stream
Definition: stream.h:364
static const char * spa_debug_type_find_name(const struct spa_type_info *info, uint32_t type)
Definition: types.h:53
static int spa_format_parse(const struct spa_pod *format, uint32_t *media_type, uint32_t *media_subtype)
Definition: format-utils.h:27
static const struct spa_type_info spa_type_video_format[]
Definition: video/raw-types.h:29
static int spa_format_video_raw_parse(const struct spa_pod *format, struct spa_video_info_raw *info)
Definition: video/raw-utils.h:27
@ SPA_MEDIA_TYPE_video
Definition: param/format.h:28
@ SPA_PARAM_Format
configured format as SPA_TYPE_OBJECT_Format
Definition: param.h:34
@ SPA_PARAM_EnumFormat
available formats as SPA_TYPE_OBJECT_Format
Definition: param.h:33
@ SPA_FORMAT_VIDEO_framerate
frame rate (Fraction)
Definition: param/format.h:124
@ SPA_FORMAT_mediaType
media type (Id enum spa_media_type)
Definition: param/format.h:93
@ SPA_FORMAT_VIDEO_size
size (Rectangle)
Definition: param/format.h:123
@ SPA_FORMAT_VIDEO_format
video format (Id enum spa_video_format)
Definition: param/format.h:120
@ SPA_FORMAT_mediaSubtype
media subtype (Id enum spa_media_subtype)
Definition: param/format.h:94
@ SPA_MEDIA_SUBTYPE_raw
Definition: param/format.h:38
@ SPA_VIDEO_FORMAT_YUY2
Definition: video/raw.h:49
@ SPA_VIDEO_FORMAT_RGBA
Definition: video/raw.h:56
@ SPA_VIDEO_FORMAT_RGBx
Definition: video/raw.h:52
@ SPA_VIDEO_FORMAT_BGRx
Definition: video/raw.h:53
@ SPA_VIDEO_FORMAT_I420
Definition: video/raw.h:47
@ SPA_VIDEO_FORMAT_RGB
Definition: video/raw.h:60
#define SPA_POD_CHOICE_ENUM_Id(n_vals,...)
Definition: vararg.h:51
#define SPA_POD_CHOICE_RANGE_Fraction(def, min, max)
Definition: vararg.h:115
#define SPA_POD_Id(val)
Definition: vararg.h:49
#define SPA_POD_BUILDER_INIT(buffer, size)
Definition: builder.h:62
#define SPA_POD_CHOICE_RANGE_Rectangle(def, min, max)
Definition: vararg.h:106
#define spa_pod_builder_add_object(b, type, id,...)
Definition: builder.h:659
@ SPA_TYPE_OBJECT_Format
Definition: spa/include/spa/utils/type.h:76
#define SPA_FRACTION(num, denom)
Definition: defs.h:122
#define SPA_RECTANGLE(width, height)
Definition: defs.h:101
a buffer structure obtained from pw_stream_dequeue_buffer().
Definition: stream.h:194
struct spa_buffer * buffer
the spa buffer
Definition: stream.h:195
Definition: properties.h:33
Events for a stream.
Definition: stream.h:319
A Buffer.
Definition: buffer/buffer.h:90
struct spa_data * datas
array of data members
Definition: buffer/buffer.h:94
uint32_t size
size of valid data.
Definition: buffer/buffer.h:47
struct spa_chunk * chunk
valid chunk of memory
Definition: buffer/buffer.h:86
void * data
optional data pointer
Definition: buffer/buffer.h:85
Definition: param/video/format.h:27
We create a stream object with different properties to make it a Camera Video Capture stream.
We also optionally allow the user to pass the name of the target node where the session manager is supposed to connect the node. The user may also give the value of the unique target node serial (PW_KEY_OBJECT_SERIAL
) as the value.
Because we capture a stream of a wide range of different video formats and resolutions, we have to describe our accepted formats in a different way:
We have an enumeration of formats, we need to first give the amount of enumerations that follow, then the default (preferred) value, followed by alternatives in order of preference:
We have something similar for the framerate.
Note that there are other video parameters that we don't specify here. This means that we don't have any restrictions for their values.
And last we pass the extra parameters for our stream. Here we only have the allowed formats (SPA_PARAM_EnumFormat
).
Running the mainloop will start the connection and negotiation process. First our param_changed
event will be called with the format that was negotiated between our stream and the camera. This is always something that is compatible with what we enumerated in the EnumFormat param when we connected.
First check if there is a param. A NULL param means that it is cleared. The ID of the param tells you what param it is. We are only interested in Format param (SPA_PARAM_Format
).
We can parse the media type and subtype as below and ensure that it is of the right type. In our example this will always be true but when your EnumFormat contains different media types or subtypes, this is how you can parse them:
In this example we dump the video size and parameters but in a real playback or capture application you might want to set up the screen or encoder to deal with the format.
In a real playback application, one would do something with the data, like copy it to the screen or encode it into a file.