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