io.h 10.8 KB
Newer Older
Wim Taymans's avatar
Wim Taymans committed
1
2
/* Simple Plugin API
 *
Wim Taymans's avatar
Wim Taymans committed
3
 * Copyright © 2018 Wim Taymans
Wim Taymans's avatar
Wim Taymans committed
4
 *
Wim Taymans's avatar
Wim Taymans committed
5
6
7
8
9
10
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
Wim Taymans's avatar
Wim Taymans committed
11
 *
Wim Taymans's avatar
Wim Taymans committed
12
13
14
15
16
17
18
19
20
21
22
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
Wim Taymans's avatar
Wim Taymans committed
23
24
 */

25
26
#ifndef SPA_IO_H
#define SPA_IO_H
Wim Taymans's avatar
Wim Taymans committed
27
28
29
30
31

#ifdef __cplusplus
extern "C" {
#endif

32
33
34
35
36
/**
 * \addtogroup spa_node
 * \{
 */

Wim Taymans's avatar
Wim Taymans committed
37
#include <spa/utils/defs.h>
Wim Taymans's avatar
Wim Taymans committed
38
#include <spa/pod/pod.h>
Wim Taymans's avatar
Wim Taymans committed
39

40
/** IO areas
Wim Taymans's avatar
Wim Taymans committed
41
42
 *
 * IO information for a port on a node. This is allocated
43
44
 * by the host and configured on a node or all ports for which
 * IO is requested.
45
46
47
 *
 * The plugin will communicate with the host through the IO
 * areas.
Wim Taymans's avatar
Wim Taymans committed
48
 */
Wim Taymans's avatar
Wim Taymans committed
49

Wim Taymans's avatar
Wim Taymans committed
50
51
/** Different IO area types */
enum spa_io_type {
52
	SPA_IO_Invalid,
53
54
55
56
57
58
59
60
61
	SPA_IO_Buffers,		/**< area to exchange buffers, struct spa_io_buffers */
	SPA_IO_Range,		/**< expected byte range, struct spa_io_range */
	SPA_IO_Clock,		/**< area to update clock information, struct spa_io_clock */
	SPA_IO_Latency,		/**< latency reporting, struct spa_io_latency */
	SPA_IO_Control,		/**< area for control messages, struct spa_io_sequence */
	SPA_IO_Notify,		/**< area for notify messages, struct spa_io_sequence */
	SPA_IO_Position,	/**< position information in the graph, struct spa_io_position */
	SPA_IO_RateMatch,	/**< rate matching between nodes, struct spa_io_rate_match */
	SPA_IO_Memory,		/**< memory pointer, struct spa_io_memory */
Wim Taymans's avatar
Wim Taymans committed
62
63
};

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * IO area to exchange buffers.
 *
 * A set of buffers should first be configured on the node/port.
 * Further references to those buffers will be made by using the
 * id of the buffer.
 *
 * If status is SPA_STATUS_OK, the host should ignore
 * the io area.
 *
 * If status is SPA_STATUS_NEED_DATA, the host should:
 * 1) recycle the buffer in buffer_id, if possible
 * 2) prepare a new buffer and place the id in buffer_id.
 *
 * If status is SPA_STATUS_HAVE_DATA, the host should consume
 * the buffer in buffer_id and set the state to
 * SPA_STATUS_NEED_DATA when new data is requested.
 *
82
 * If status is SPA_STATUS_STOPPED, some error occurred on the
83
84
 * port.
 *
Wim Taymans's avatar
Wim Taymans committed
85
86
87
 * If status is SPA_STATUS_DRAINED, data from the io area was
 * used to drain.
 *
88
89
90
91
92
 * Status can also be a negative errno value to indicate errors.
 * such as:
 * -EINVAL: buffer_id is invalid
 * -EPIPE: no more buffers available
 */
Wim Taymans's avatar
Wim Taymans committed
93
94
struct spa_io_buffers {
#define SPA_STATUS_OK			0
95
96
#define SPA_STATUS_NEED_DATA		(1<<0)
#define SPA_STATUS_HAVE_DATA		(1<<1)
Wim Taymans's avatar
Wim Taymans committed
97
#define SPA_STATUS_STOPPED		(1<<2)
Wim Taymans's avatar
Wim Taymans committed
98
#define SPA_STATUS_DRAINED		(1<<3)
Wim Taymans's avatar
Wim Taymans committed
99
100
101
102
103
104
	int32_t status;			/**< the status code */
	uint32_t buffer_id;		/**< a buffer id */
};

#define SPA_IO_BUFFERS_INIT  (struct spa_io_buffers) { SPA_STATUS_OK, SPA_ID_INVALID, }

105
106
107
108
109
110
111
112
113
114
/**
 * IO area to exchange a memory region
 */
struct spa_io_memory {
	int32_t status;			/**< the status code */
	uint32_t size;			/**< the size of \a data */
	void *data;			/**< a memory pointer */
};
#define SPA_IO_MEMORY_INIT  (struct spa_io_memory) { SPA_STATUS_OK, 0, NULL, }

Wim Taymans's avatar
Wim Taymans committed
115
/** A range, suitable for input ports that can suggest a range to output ports */
Wim Taymans's avatar
Wim Taymans committed
116
struct spa_io_range {
Wim Taymans's avatar
Wim Taymans committed
117
118
119
120
121
	uint64_t offset;	/**< offset in range */
	uint32_t min_size;	/**< minimum size of data */
	uint32_t max_size;	/**< maximum size of data */
};

Wim Taymans's avatar
Wim Taymans committed
122
123
124
125
126
127
128
129
130
131
/**
 * Absolute time reporting.
 *
 * Nodes that can report clocking information will receive this io block.
 * The application sets the id. This is usually set as part of the
 * position information but can also be set separately.
 *
 * The clock counts the elapsed time according to the clock provider
 * since the provider was last started.
 */
Wim Taymans's avatar
Wim Taymans committed
132
struct spa_io_clock {
133
#define SPA_IO_CLOCK_FLAG_FREEWHEEL (1u<<0)
134
	uint32_t flags;			/**< clock flags */
Wim Taymans's avatar
Wim Taymans committed
135
	uint32_t id;			/**< unique clock id, set by application */
136
137
138
	char name[64];			/**< clock name prefixed with API, set by node. The clock name
					  *  is unique per clock and can be used to check if nodes
					  *  share the same clock. */
Wim Taymans's avatar
Wim Taymans committed
139
	uint64_t nsec;			/**< time in nanoseconds against monotonic clock */
Wim Taymans's avatar
Wim Taymans committed
140
	struct spa_fraction rate;	/**< rate for position/duration/delay */
Wim Taymans's avatar
Wim Taymans committed
141
	uint64_t position;		/**< current position */
Wim Taymans's avatar
Wim Taymans committed
142
	uint64_t duration;		/**< duration of current cycle */
143
144
145
	int64_t delay;			/**< delay between position and hardware,
					  *  positive for capture, negative for playback */
	double rate_diff;		/**< rate difference between clock and monotonic time */
Andrea Gelmini's avatar
Andrea Gelmini committed
146
	uint64_t next_nsec;		/**< estimated next wakeup time in nanoseconds */
147
148
149
150
151
152
153
154
155
156
157
158
159
	uint32_t padding[8];
};

/* the size of the video in this cycle */
struct spa_io_video_size {
#define SPA_IO_VIDEO_SIZE_VALID		(1<<0)
	uint32_t flags;			/**< optional flags */
	uint32_t stride;		/**< video stride in bytes */
	struct spa_rectangle size;	/**< the video size */
	struct spa_fraction framerate;  /**< the minimum framerate, the cycle duration is
					  *  always smaller to ensure there is only one
					  *  video frame per cycle. */
	uint32_t padding[4];
Wim Taymans's avatar
Wim Taymans committed
160
161
};

Wim Taymans's avatar
Wim Taymans committed
162
163
164
165
166
167
168
/** latency reporting */
struct spa_io_latency {
	struct spa_fraction rate;	/**< rate for min/max */
	uint64_t min;			/**< min latency */
	uint64_t max;			/**< max latency */
};

169
/** control stream, io area for SPA_IO_Control and SPA_IO_Notify */
Wim Taymans's avatar
Wim Taymans committed
170
struct spa_io_sequence {
Wim Taymans's avatar
Wim Taymans committed
171
172
173
	struct spa_pod_sequence sequence;	/**< sequence of timed events */
};

Wim Taymans's avatar
Wim Taymans committed
174
175
/** bar and beat segment */
struct spa_io_segment_bar {
176
177
#define SPA_IO_SEGMENT_BAR_FLAG_VALID		(1<<0)
	uint32_t flags;			/**< extra flags */
178
	uint32_t offset;		/**< offset in segment of this beat */
Wim Taymans's avatar
Wim Taymans committed
179
180
	float signature_num;		/**< time signature numerator */
	float signature_denom;		/**< time signature denominator */
181
	double bpm;			/**< beats per minute */
Wim Taymans's avatar
Wim Taymans committed
182
	double beat;			/**< current beat in segment */
183
	uint32_t padding[8];
184
185
};

Wim Taymans's avatar
Wim Taymans committed
186
187
/** video frame segment */
struct spa_io_segment_video {
188
189
190
191
#define SPA_IO_SEGMENT_VIDEO_FLAG_VALID		(1<<0)
#define SPA_IO_SEGMENT_VIDEO_FLAG_DROP_FRAME	(1<<1)
#define SPA_IO_SEGMENT_VIDEO_FLAG_PULL_DOWN	(1<<2)
#define SPA_IO_SEGMENT_VIDEO_FLAG_INTERLACED	(1<<3)
192
	uint32_t flags;			/**< flags */
193
	uint32_t offset;		/**< offset in segment */
194
	struct spa_fraction framerate;
195
196
197
198
199
	uint32_t hours;
	uint32_t minutes;
	uint32_t seconds;
	uint32_t frames;
	uint32_t field_count;		/**< 0 for progressive, 1 and 2 for interlaced */
200
	uint32_t padding[11];
201
202
};

Wim Taymans's avatar
Wim Taymans committed
203
/**
Wim Taymans's avatar
Wim Taymans committed
204
 * A segment converts a running time to a segment (stream) position.
Wim Taymans's avatar
Wim Taymans committed
205
 *
Wim Taymans's avatar
Wim Taymans committed
206
 * The segment position is valid when the current running time is between
207
 * start and start + duration. The position is then
Wim Taymans's avatar
Wim Taymans committed
208
209
 * calculated as:
 *
Wim Taymans's avatar
Wim Taymans committed
210
 *   (running time - start) * rate + position;
Wim Taymans's avatar
Wim Taymans committed
211
 *
Wim Taymans's avatar
Wim Taymans committed
212
213
214
 * Support for looping is done by specifying the LOOPING flags with a
 * non-zero duration. When the running time reaches start + duration,
 * duration is added to start and the loop repeats.
Wim Taymans's avatar
Wim Taymans committed
215
 *
Wim Taymans's avatar
Wim Taymans committed
216
217
 * Care has to be taken when the running time + clock.duration extends
 * past the start + duration from the segment; the user should correctly
Wim Taymans's avatar
Wim Taymans committed
218
219
220
221
222
223
 * wrap around and partially repeat the loop in the current cycle.
 *
 * Extra information can be placed in the segment by setting the valid flags
 * and filling up the corresponding structures.
 */
struct spa_io_segment {
224
225
226
227
228
229
230
	uint32_t version;
#define SPA_IO_SEGMENT_FLAG_LOOPING	(1<<0)	/**< after the duration, the segment repeats */
#define SPA_IO_SEGMENT_FLAG_NO_POSITION	(1<<1)	/**< position is invalid. The position can be invalid
						  *  after a seek, for example, when the exact mapping
						  *  of the extra segment info (bar, video, ...) to
						  *  position has not been determined yet */
	uint32_t flags;				/**< extra flags */
Wim Taymans's avatar
Wim Taymans committed
231
	uint64_t start;				/**< value of running time when this
Wim Taymans's avatar
Wim Taymans committed
232
233
234
						  *  info is active. Can be in the future for
						  *  pending changes. It does not have to be in
						  *  exact multiples of the clock duration. */
Wim Taymans's avatar
Wim Taymans committed
235
236
237
238
239
	uint64_t duration;			/**< duration when this info becomes invalid expressed
						  *  in running time. If the duration is 0, this
						  *  segment extends to the next segment. If the
						  *  segment becomes invalid and the looping flag is
						  *  set, the segment repeats. */
Andrea Gelmini's avatar
Andrea Gelmini committed
240
	double rate;				/**< overall rate of the segment, can be negative for
Wim Taymans's avatar
Wim Taymans committed
241
						  *  backwards time reporting. */
242
243
	uint64_t position;			/**< The position when the running time == start.
						  *  can be invalid when the owner of the extra segment
244
						  *  information has not yet made the mapping. */
Wim Taymans's avatar
Wim Taymans committed
245

246
247
	struct spa_io_segment_bar bar;
	struct spa_io_segment_video video;
Wim Taymans's avatar
Wim Taymans committed
248
249
};

Wim Taymans's avatar
Wim Taymans committed
250
251
252
253
254
255
enum spa_io_position_state {
	SPA_IO_POSITION_STATE_STOPPED,
	SPA_IO_POSITION_STATE_STARTING,
	SPA_IO_POSITION_STATE_RUNNING,
};

Wim Taymans's avatar
Wim Taymans committed
256
257
258
/** the maximum number of segments visible in the future */
#define SPA_IO_POSITION_MAX_SEGMENTS	8

Wim Taymans's avatar
Wim Taymans committed
259
260
261
262
/**
 * The position information adds extra meaning to the raw clock times.
 *
 * It is set on all nodes and the clock id will contain the clock of the
Wim Taymans's avatar
Wim Taymans committed
263
 * driving node in the graph.
Wim Taymans's avatar
Wim Taymans committed
264
 *
Wim Taymans's avatar
Wim Taymans committed
265
266
 * The position information contains 1 or more segments that convert the
 * raw clock times to a stream time. They are sorted based on their
267
 * start times, and thus the order in which they will activate in
Wim Taymans's avatar
Wim Taymans committed
268
269
 * the future. This makes it possible to look ahead in the scheduled
 * segments and anticipate the changes in the timeline.
Wim Taymans's avatar
Wim Taymans committed
270
 */
271
272
273
struct spa_io_position {
	struct spa_io_clock clock;		/**< clock position of driver, always valid and
						  *  read only */
274
	struct spa_io_video_size video;		/**< size of the video in the current cycle */
Wim Taymans's avatar
Wim Taymans committed
275
276
277
278
279
	int64_t offset;				/**< an offset to subtract from the clock position
						  *  to get a running time. This is the time that
						  *  the state has been in the RUNNING state and the
						  *  time that should be used to compare the segment
						  *  start values against. */
Wim Taymans's avatar
Wim Taymans committed
280
281
	uint32_t state;				/**< one of enum spa_io_position_state */

Wim Taymans's avatar
Wim Taymans committed
282
283
	uint32_t n_segments;			/**< number of segments */
	struct spa_io_segment segments[SPA_IO_POSITION_MAX_SEGMENTS];	/**< segments */
284
};
Wim Taymans's avatar
Wim Taymans committed
285

286
287
288
289
290
/** rate matching */
struct spa_io_rate_match {
	uint32_t delay;			/**< extra delay in samples for resampler */
	uint32_t size;			/**< requested input size for resampler */
	double rate;			/**< rate for resampler */
291
292
#define SPA_IO_RATE_MATCH_FLAG_ACTIVE	(1 << 0)
	uint32_t flags;			/**< extra flags */
Wim Taymans's avatar
Wim Taymans committed
293
	uint32_t padding[7];
294
295
};

296
297
298
299
/**
 * \}
 */

Wim Taymans's avatar
Wim Taymans committed
300
301
302
303
#ifdef __cplusplus
}  /* extern "C" */
#endif

304
#endif /* SPA_IO_H */