xref: /haiku/src/add-ons/media/media-add-ons/video_mixer/VideoMixerNode.h (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2 * Copyright (C) 2009-2010 David McPaul
3 *
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6 
7 #ifndef _VIDEO_MIXER_NODE_H
8 #define _VIDEO_MIXER_NODE_H
9 
10 #include <Buffer.h>
11 #include <BufferConsumer.h>
12 #include <BufferGroup.h>
13 #include <BufferProducer.h>
14 #include <MediaAddOn.h>
15 #include <MediaDefs.h>
16 #include <MediaEventLooper.h>
17 #include <MediaNode.h>
18 #include <TimeSource.h>
19 
20 #include <vector>
21 
22 #include "BufferMixer.h"
23 
24 class VideoMixerNode :
25 	public BBufferConsumer,
26 	public BBufferProducer,
27     public BMediaEventLooper
28 {
29 protected:
30 virtual ~VideoMixerNode(void);
31 
32 public:
33 
34 explicit VideoMixerNode(
35 				const flavor_info * info = 0,
36 				BMessage *config = 0,
37 				BMediaAddOn *addOn = 0);
38 
39 virtual status_t InitCheck(void) const;
40 
41 // see BMediaAddOn::GetConfigurationFor
42 virtual	status_t GetConfigurationFor(
43 				BMessage *into_message);
44 
45 public:
46 //	/* this port is what a media node listens to for commands */
47 // virtual port_id ControlPort(void) const;
48 
49 virtual	BMediaAddOn* AddOn(
50 				int32 *internal_id) const;	/* Who instantiated you -- or NULL for app class */
51 
52 protected:
53 		/* These don't return errors; instead, they use the global error condition reporter. */
54 		/* A node is required to have a queue of at least one pending command (plus TimeWarp) */
55 		/* and is recommended to allow for at least one pending command of each type. */
56 		/* Allowing an arbitrary number of outstanding commands might be nice, but apps */
57 		/* cannot depend on that happening. */
58 virtual	void Start(
59 				bigtime_t performance_time);
60 virtual	void Stop(
61 				bigtime_t performance_time,
62 				bool immediate);
63 virtual	void Seek(
64 				bigtime_t media_time,
65 				bigtime_t performance_time);
66 virtual	void SetRunMode(
67 				run_mode mode);
68 virtual	void TimeWarp(
69 				bigtime_t at_real_time,
70 				bigtime_t to_performance_time);
71 virtual	void Preroll(void);
72 virtual	void SetTimeSource(BTimeSource *time_source);
73 
74 public:
75 virtual	status_t HandleMessage(
76 				int32 message,
77 				const void *data,
78 				size_t size);
79 
80 protected:
81 		/* Called when requests have completed, or failed. */
82 virtual	status_t RequestCompleted(	/* reserved 0 */
83 				const media_request_info &info);
84 
85 protected:
86 virtual		status_t DeleteHook(BMediaNode *node);		/* reserved 1 */
87 
88 virtual		void NodeRegistered(void);	/* reserved 2 */
89 
90 public:
91 
92 		/* fill out your attributes in the provided array, returning however many you have. */
93 virtual		status_t GetNodeAttributes(	/* reserved 3 */
94 					media_node_attribute *outAttributes,
95 					size_t inMaxCount);
96 
97 virtual		status_t AddTimer(
98 					bigtime_t at_performance_time,
99 					int32 cookie);
100 
101 	/* Someone, probably the producer, is asking you about this format. Give */
102 	/* your honest opinion, possibly modifying *format. Do not ask upstream */
103 	/* producer about the format, since he's synchronously waiting for your */
104 	/* reply. */
105 virtual	status_t AcceptFormat(
106 				const media_destination &dest,
107 				media_format *format);
108 virtual	status_t GetNextInput(
109 				int32 * cookie,
110 				media_input *out_input);
111 virtual	void DisposeInputCookie(int32 cookie);
112 virtual	void BufferReceived(BBuffer *buffer);
113 virtual	void ProducerDataStatus(
114 				const media_destination &for_whom,
115 				int32 status,
116 				bigtime_t at_performance_time);
117 virtual	status_t GetLatencyFor(
118 				const media_destination &for_whom,
119 				bigtime_t *out_latency,
120 				media_node_id *out_timesource);
121 virtual	status_t Connected(
122 				const media_source &producer,	/* here's a good place to request buffer group usage */
123 				const media_destination &where,
124 				const media_format &with_format,
125 				media_input *out_input);
126 virtual	void Disconnected(
127 				const media_source &producer,
128 				const media_destination &where);
129 	/* The notification comes from the upstream producer, so he's already cool with */
130 	/* the format; you should not ask him about it in here. */
131 virtual	status_t FormatChanged(
132 				const media_source &producer,
133 				const media_destination &consumer,
134 				int32 change_tag,
135 				const media_format &format);
136 
137 	/* Given a performance time of some previous buffer, retrieve the remembered tag */
138 	/* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
139 	/* idea being that flags can be added later, and the understood flags returned in */
140 	/* *out_flags. */
141 virtual	status_t SeekTagRequested(
142 				const media_destination &destination,
143 				bigtime_t in_target_time,
144 				uint32 in_flags,
145 				media_seek_tag *out_seek_tag,
146 				bigtime_t *out_tagged_time,
147 				uint32 *out_flags);
148 
149 
150 protected:
151 	/* functionality of BBufferProducer */
152 virtual	status_t FormatSuggestionRequested(
153 				media_type type,
154 				int32 quality,
155 				media_format *format);
156 virtual	status_t FormatProposal(
157 				const media_source &output,
158 				media_format *format);
159 	/* If the format isn't good, put a good format into *io_format and return error */
160 	/* If format has wildcard, specialize to what you can do (and change). */
161 	/* If you can change the format, return OK. */
162 	/* The request comes from your destination sychronously, so you cannot ask it */
163 	/* whether it likes it -- you should assume it will since it asked. */
164 virtual	status_t FormatChangeRequested(
165 				const media_source &source,
166 				const media_destination &destination,
167 				media_format *io_format,
168 				int32 *_deprecated_);
169 virtual	status_t GetNextOutput(	/* cookie starts as 0 */
170 				int32 *cookie,
171 				media_output *out_output);
172 virtual	status_t DisposeOutputCookie(
173 				int32 cookie);
174 	/* In this function, you should either pass on the group to your upstream guy, */
175 	/* or delete your current group and hang on to this group. Deleting the previous */
176 	/* group (unless you passed it on with the reclaim flag set to false) is very */
177 	/* important, else you will 1) leak memory and 2) block someone who may want */
178 	/* to reclaim the buffers living in that group. */
179 virtual	status_t SetBufferGroup(
180 				const media_source &for_source,
181 				BBufferGroup * group);
182 	/* Format of clipping is (as int16-s): <from line> <npairs> <startclip> <endclip>. */
183 	/* Repeat for each line where the clipping is different from the previous line. */
184 	/* If <npairs> is negative, use the data from line -<npairs> (there are 0 pairs after */
185 	/* a negative <npairs>. Yes, we only support 32k*32k frame buffers for clipping. */
186 	/* Any non-0 field of 'display' means that that field changed, and if you don't support */
187 	/* that change, you should return an error and ignore the request. Note that the buffer */
188 	/* offset values do not have wildcards; 0 (or -1, or whatever) are real values and must */
189 	/* be adhered to. */
190 virtual	status_t VideoClippingChanged(
191 				const media_source &for_source,
192 				int16 num_shorts,
193 				int16 *clip_data,
194 				const media_video_display_info &display,
195 				int32 *_deprecated_);
196 	/* Iterates over all outputs and maxes the latency found */
197 virtual	status_t GetLatency(bigtime_t *out_latency);
198 virtual	status_t PrepareToConnect(
199 				const media_source &what,
200 				const media_destination &where,
201 				media_format *format,
202 				media_source *out_source,
203 				char *out_name);
204 virtual	void Connect(
205 				status_t error,
206 				const media_source &source,
207 				const media_destination &destination,
208 				const media_format &format,
209 				char *io_name);
210 virtual	void Disconnect(
211 				const media_source &what,
212 				const media_destination &where);
213 virtual	void LateNoticeReceived(
214 				const media_source &what,
215 				bigtime_t how_much,
216 				bigtime_t performance_time);
217 virtual	void EnableOutput(
218 				const media_source &what,
219 				bool enabled,
220 				int32 *_deprecated_);
221 virtual	status_t SetPlayRate(
222 				int32 numer,
223 				int32 denom);
224 
225 virtual	void AdditionalBufferRequested(			//	used to be Reserved 0
226 				const media_source & source,
227 				media_buffer_id prev_buffer,
228 				bigtime_t prev_time,
229 				const media_seek_tag *prev_tag);	//	may be NULL
230 
231 virtual	void LatencyChanged(					//	used to be Reserved 1
232 				const media_source & source,
233 				const media_destination & destination,
234 				bigtime_t new_latency,
235 				uint32 flags);
236 
237 
238 	protected:
239 		/* you must override to handle your events! */
240 		/* you should not call HandleEvent directly */
241 		virtual void		HandleEvent(	const media_timed_event *event,
242 											bigtime_t lateness,
243 											bool realTimeEvent = false);
244 
245 		/* override to clean up custom events you have added to your queue */
246 		virtual void		CleanUpEvent(const media_timed_event *event);
247 
248 		/* called from Offline mode to determine the current time of the node */
249 		/* update your internal information whenever it changes */
250 		virtual	bigtime_t	OfflineTime();
251 
252 		/* override only if you know what you are doing! */
253 		/* otherwise much badness could occur */
254 		/* the actual control loop function: */
255 		/* 	waits for messages, Pops events off the queue and calls DispatchEvent */
256 		virtual void		ControlLoop();
257 
258 
259 protected:
260 
261 virtual status_t HandleStart(
262 						const media_timed_event *event,
263 						bigtime_t lateness,
264 						bool realTimeEvent = false);
265 virtual status_t HandleSeek(
266 						const media_timed_event *event,
267 						bigtime_t lateness,
268 						bool realTimeEvent = false);
269 virtual status_t HandleWarp(
270 						const media_timed_event *event,
271 						bigtime_t lateness,
272 						bool realTimeEvent = false);
273 virtual status_t HandleStop(
274 						const media_timed_event *event,
275 						bigtime_t lateness,
276 						bool realTimeEvent = false);
277 virtual status_t HandleBuffer(
278 						const media_timed_event *event,
279 						bigtime_t lateness,
280 						bool realTimeEvent = false);
281 virtual status_t HandleDataStatus(
282 						const media_timed_event *event,
283 						bigtime_t lateness,
284 						bool realTimeEvent = false);
285 virtual status_t HandleParameter(
286 						const media_timed_event *event,
287 						bigtime_t lateness,
288 						bool realTimeEvent = false);
289 
290 protected:
291 
292 //void CreateBufferGroup(MediaOutputInfo *output_info);
293 void ComputeInternalLatency();
294 
295 public:
296 
297 static void GetFlavor(flavor_info *outInfo, int32 id);
298 
299 private:
300 	media_input 	*CreateInput(uint32 inputID);
301 	void			ClearInput(media_input *input);
302 	media_input		*GetInput(const media_source &source);
303 	media_input		*GetInput(const media_destination &destination);
304 	media_input		*GetInput(const int32 id);
305 
306 static void GetInputFormat(media_format *outFormat);
307 static void GetOutputFormat(media_format *outFormat);
308 
309 protected:
310 
311 virtual status_t AddRequirements(media_format *format);
312 
313 private:
314 
315 		status_t 					fInitCheckStatus;
316 
317 		BMediaAddOn 				*fAddOn;
318 
319 		media_input					fInitialInput;
320 		std::vector<media_input *>	fConnectedInputs;
321 		media_output				fOutput;
322 
323 		bigtime_t 					fDownstreamLatency;
324 		bigtime_t 					fInternalLatency;
325 
326 		BufferMixer					bufferMixer;
327 
328 };
329 
330 #endif /* _VIDEO_MIXER_NODE_H */
331