1 /* Simple Plugin API
2  *
3  * Copyright © 2018 Wim Taymans
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #ifndef SPA_IO_H
26 #define SPA_IO_H
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #include <spa/utils/defs.h>
33 #include <spa/pod/pod.h>
34 
35 /** IO areas
36  *
37  * IO information for a port on a node. This is allocated
38  * by the host and configured on a node or all ports for which
39  * IO is requested.
40  *
41  * The plugin will communicate with the host through the IO
42  * areas.
43  */
44 
45 /** Different IO area types */
46 enum spa_io_type {
47 	SPA_IO_Invalid,
48 	SPA_IO_Buffers,		/**< area to exchange buffers, struct spa_io_buffers */
49 	SPA_IO_Range,		/**< expected byte range, struct spa_io_range */
50 	SPA_IO_Clock,		/**< area to update clock information, struct spa_io_clock */
51 	SPA_IO_Latency,		/**< latency reporting, struct spa_io_latency */
52 	SPA_IO_Control,		/**< area for control messages, struct spa_io_sequence */
53 	SPA_IO_Notify,		/**< area for notify messages, struct spa_io_sequence */
54 	SPA_IO_Position,	/**< position information in the graph, struct spa_io_position */
55 	SPA_IO_RateMatch,	/**< rate matching between nodes, struct spa_io_rate_match */
56 	SPA_IO_Memory,		/**< memory pointer, struct spa_io_memory */
57 };
58 
59 /**
60  * IO area to exchange buffers.
61  *
62  * A set of buffers should first be configured on the node/port.
63  * Further references to those buffers will be made by using the
64  * id of the buffer.
65  *
66  * If status is SPA_STATUS_OK, the host should ignore
67  * the io area.
68  *
69  * If status is SPA_STATUS_NEED_DATA, the host should:
70  * 1) recycle the buffer in buffer_id, if possible
71  * 2) prepare a new buffer and place the id in buffer_id.
72  *
73  * If status is SPA_STATUS_HAVE_DATA, the host should consume
74  * the buffer in buffer_id and set the state to
75  * SPA_STATUS_NEED_DATA when new data is requested.
76  *
77  * If status is SPA_STATUS_STOPPED, some error occurred on the
78  * port.
79  *
80  * If status is SPA_STATUS_DRAINED, data from the io area was
81  * used to drain.
82  *
83  * Status can also be a negative errno value to indicate errors.
84  * such as:
85  * -EINVAL: buffer_id is invalid
86  * -EPIPE: no more buffers available
87  */
88 struct spa_io_buffers {
89 #define SPA_STATUS_OK			0
90 #define SPA_STATUS_NEED_DATA		(1<<0)
91 #define SPA_STATUS_HAVE_DATA		(1<<1)
92 #define SPA_STATUS_STOPPED		(1<<2)
93 #define SPA_STATUS_DRAINED		(1<<3)
94 	int32_t status;			/**< the status code */
95 	uint32_t buffer_id;		/**< a buffer id */
96 };
97 
98 #define SPA_IO_BUFFERS_INIT  (struct spa_io_buffers) { SPA_STATUS_OK, SPA_ID_INVALID, }
99 
100 /**
101  * IO area to exchange a memory region
102  */
103 struct spa_io_memory {
104 	int32_t status;			/**< the status code */
105 	uint32_t size;			/**< the size of \a data */
106 	void *data;			/**< a memory pointer */
107 };
108 #define SPA_IO_MEMORY_INIT  (struct spa_io_memory) { SPA_STATUS_OK, 0, NULL, }
109 
110 /** A range, suitable for input ports that can suggest a range to output ports */
111 struct spa_io_range {
112 	uint64_t offset;	/**< offset in range */
113 	uint32_t min_size;	/**< minimum size of data */
114 	uint32_t max_size;	/**< maximum size of data */
115 };
116 
117 /**
118  * Absolute time reporting.
119  *
120  * Nodes that can report clocking information will receive this io block.
121  * The application sets the id. This is usually set as part of the
122  * position information but can also be set separately.
123  *
124  * The clock counts the elapsed time according to the clock provider
125  * since the provider was last started.
126  */
127 struct spa_io_clock {
128 	uint32_t flags;			/**< clock flags */
129 	uint32_t id;			/**< unique clock id, set by application */
130 	char name[64];			/**< clock name prefixed with API, set by node. The clock name
131 					  *  is unique per clock and can be used to check if nodes
132 					  *  share the same clock. */
133 	uint64_t nsec;			/**< time in nanoseconds against monotonic clock */
134 	struct spa_fraction rate;	/**< rate for position/duration/delay */
135 	uint64_t position;		/**< current position */
136 	uint64_t duration;		/**< duration of current cycle */
137 	int64_t delay;			/**< delay between position and hardware,
138 					  *  positive for capture, negative for playback */
139 	double rate_diff;		/**< rate difference between clock and monotonic time */
140 	uint64_t next_nsec;		/**< extimated next wakeup time in nanoseconds */
141 	uint32_t padding[8];
142 };
143 
144 /* the size of the video in this cycle */
145 struct spa_io_video_size {
146 #define SPA_IO_VIDEO_SIZE_VALID		(1<<0)
147 	uint32_t flags;			/**< optional flags */
148 	uint32_t stride;		/**< video stride in bytes */
149 	struct spa_rectangle size;	/**< the video size */
150 	struct spa_fraction framerate;  /**< the minimum framerate, the cycle duration is
151 					  *  always smaller to ensure there is only one
152 					  *  video frame per cycle. */
153 	uint32_t padding[4];
154 };
155 
156 /** latency reporting */
157 struct spa_io_latency {
158 	struct spa_fraction rate;	/**< rate for min/max */
159 	uint64_t min;			/**< min latency */
160 	uint64_t max;			/**< max latency */
161 };
162 
163 /** control stream, io area for SPA_IO_Control and SPA_IO_Notify */
164 struct spa_io_sequence {
165 	struct spa_pod_sequence sequence;	/**< sequence of timed events */
166 };
167 
168 /** bar and beat segment */
169 struct spa_io_segment_bar {
170 #define SPA_IO_SEGMENT_BAR_FLAG_VALID		(1<<0)
171 	uint32_t flags;			/**< extra flags */
172 	uint32_t offset;		/**< offset in segment of this beat */
173 	float signature_num;		/**< time signature numerator */
174 	float signature_denom;		/**< time signature denominator */
175 	double bpm;			/**< beats per minute */
176 	double beat;			/**< current beat in segment */
177 	uint32_t padding[8];
178 };
179 
180 /** video frame segment */
181 struct spa_io_segment_video {
182 #define SPA_IO_SEGMENT_VIDEO_FLAG_VALID		(1<<0)
183 #define SPA_IO_SEGMENT_VIDEO_FLAG_DROP_FRAME	(1<<1)
184 #define SPA_IO_SEGMENT_VIDEO_FLAG_PULL_DOWN	(1<<2)
185 #define SPA_IO_SEGMENT_VIDEO_FLAG_INTERLACED	(1<<3)
186 	uint32_t flags;			/**< flags */
187 	uint32_t offset;		/**< offset in segment */
188 	struct spa_fraction framerate;
189 	uint32_t hours;
190 	uint32_t minutes;
191 	uint32_t seconds;
192 	uint32_t frames;
193 	uint32_t field_count;		/**< 0 for progressive, 1 and 2 for interlaced */
194 	uint32_t padding[11];
195 };
196 
197 /**
198  * A segment converts a running time to a segment (stream) position.
199  *
200  * The segment position is valid when the current running time is between
201  * start and start + duration. The position is then
202  * calculated as:
203  *
204  *   (running time - start) * rate + position;
205  *
206  * Support for looping is done by specifying the LOOPING flags with a
207  * non-zero duration. When the running time reaches start + duration,
208  * duration is added to start and the loop repeats.
209  *
210  * Care has to be taken when the running time + clock.duration extends
211  * past the start + duration from the segment; the user should correctly
212  * wrap around and partially repeat the loop in the current cycle.
213  *
214  * Extra information can be placed in the segment by setting the valid flags
215  * and filling up the corresponding structures.
216  */
217 struct spa_io_segment {
218 	uint32_t version;
219 #define SPA_IO_SEGMENT_FLAG_LOOPING	(1<<0)	/**< after the duration, the segment repeats */
220 #define SPA_IO_SEGMENT_FLAG_NO_POSITION	(1<<1)	/**< position is invalid. The position can be invalid
221 						  *  after a seek, for example, when the exact mapping
222 						  *  of the extra segment info (bar, video, ...) to
223 						  *  position has not been determined yet */
224 	uint32_t flags;				/**< extra flags */
225 	uint64_t start;				/**< value of running time when this
226 						  *  info is active. Can be in the future for
227 						  *  pending changes. It does not have to be in
228 						  *  exact multiples of the clock duration. */
229 	uint64_t duration;			/**< duration when this info becomes invalid expressed
230 						  *  in running time. If the duration is 0, this
231 						  *  segment extends to the next segment. If the
232 						  *  segment becomes invalid and the looping flag is
233 						  *  set, the segment repeats. */
234 	double rate;				/**< overal rate of the segment, can be negative for
235 						  *  backwards time reporting. */
236 	uint64_t position;			/**< The position when the running time == start.
237 						  *  can be invalid when the owner of the extra segment
238 						  *  information has not yet made the mapping. */
239 
240 	struct spa_io_segment_bar bar;
241 	struct spa_io_segment_video video;
242 };
243 
244 enum spa_io_position_state {
245 	SPA_IO_POSITION_STATE_STOPPED,
246 	SPA_IO_POSITION_STATE_STARTING,
247 	SPA_IO_POSITION_STATE_RUNNING,
248 };
249 
250 /** the maximum number of segments visible in the future */
251 #define SPA_IO_POSITION_MAX_SEGMENTS	8
252 
253 /**
254  * The position information adds extra meaning to the raw clock times.
255  *
256  * It is set on all nodes and the clock id will contain the clock of the
257  * driving node in the graph.
258  *
259  * The position information contains 1 or more segments that convert the
260  * raw clock times to a stream time. They are sorted based on their
261  * start times, and thus the order in which they will activate in
262  * the future. This makes it possible to look ahead in the scheduled
263  * segments and anticipate the changes in the timeline.
264  */
265 struct spa_io_position {
266 	struct spa_io_clock clock;		/**< clock position of driver, always valid and
267 						  *  read only */
268 	struct spa_io_video_size video;		/**< size of the video in the current cycle */
269 	int64_t offset;				/**< an offset to subtract from the clock position
270 						  *  to get a running time. This is the time that
271 						  *  the state has been in the RUNNING state and the
272 						  *  time that should be used to compare the segment
273 						  *  start values against. */
274 	uint32_t state;				/**< one of enum spa_io_position_state */
275 
276 	uint32_t n_segments;			/**< number of segments */
277 	struct spa_io_segment segments[SPA_IO_POSITION_MAX_SEGMENTS];	/**< segments */
278 };
279 
280 /** rate matching */
281 struct spa_io_rate_match {
282 	uint32_t delay;			/**< extra delay in samples for resampler */
283 	uint32_t size;			/**< requested input size for resampler */
284 	double rate;			/**< rate for resampler */
285 #define SPA_IO_RATE_MATCH_FLAG_ACTIVE	(1 << 0)
286 	uint32_t flags;			/**< extra flags */
287 	uint32_t padding[7];
288 };
289 
290 #ifdef __cplusplus
291 }  /* extern "C" */
292 #endif
293 
294 #endif /* SPA_IO_H */
295