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 22 class MediaDemultiplexerNode : 23 public BBufferConsumer, 24 public BBufferProducer, 25 public BMediaEventLooper 26 { 27 protected: 28 virtual ~MediaDemultiplexerNode(void); 29 30 public: 31 32 explicit MediaDemultiplexerNode( 33 const flavor_info * info = 0, 34 BMessage * config = 0, 35 BMediaAddOn * addOn = 0); 36 37 virtual status_t InitCheck(void) const; 38 39 // see BMediaAddOn::GetConfigurationFor 40 virtual status_t GetConfigurationFor( 41 BMessage * into_message); 42 43 /*************************/ 44 /* begin from BMediaNode */ 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( 73 BTimeSource * time_source); 74 75 public: 76 virtual status_t HandleMessage( 77 int32 message, 78 const void * data, 79 size_t size); 80 81 protected: 82 /* Called when requests have completed, or failed. */ 83 virtual status_t RequestCompleted( /* reserved 0 */ 84 const media_request_info & info); 85 86 protected: 87 virtual status_t DeleteHook(BMediaNode * node); /* reserved 1 */ 88 89 virtual void NodeRegistered(void); /* reserved 2 */ 90 91 public: 92 93 /* fill out your attributes in the provided array, returning however many you have. */ 94 virtual status_t GetNodeAttributes( /* reserved 3 */ 95 media_node_attribute * outAttributes, 96 size_t inMaxCount); 97 98 virtual 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. */ 118 virtual status_t AcceptFormat( 119 const media_destination & dest, 120 media_format * format); 121 virtual status_t GetNextInput( 122 int32 * cookie, 123 media_input * out_input); 124 virtual void DisposeInputCookie( 125 int32 cookie); 126 virtual void BufferReceived( 127 BBuffer * buffer); 128 virtual void ProducerDataStatus( 129 const media_destination & for_whom, 130 int32 status, 131 bigtime_t at_performance_time); 132 virtual status_t GetLatencyFor( 133 const media_destination & for_whom, 134 bigtime_t * out_latency, 135 media_node_id * out_timesource); 136 virtual 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); 141 virtual 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. */ 146 virtual 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. */ 156 virtual 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 */ 169 protected: 170 /* functionality of BBufferProducer */ 171 virtual status_t FormatSuggestionRequested( 172 media_type type, 173 int32 quality, 174 media_format * format); 175 virtual 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. */ 183 virtual status_t FormatChangeRequested( 184 const media_source & source, 185 const media_destination & destination, 186 media_format * io_format, 187 int32 * _deprecated_); 188 virtual status_t GetNextOutput( /* cookie starts as 0 */ 189 int32 * cookie, 190 media_output * out_output); 191 virtual 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. */ 198 virtual 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. */ 209 virtual 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 */ 216 virtual status_t GetLatency( 217 bigtime_t * out_latency); 218 virtual 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); 224 virtual 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); 230 virtual void Disconnect( 231 const media_source & what, 232 const media_destination & where); 233 virtual void LateNoticeReceived( 234 const media_source & what, 235 bigtime_t how_much, 236 bigtime_t performance_time); 237 virtual void EnableOutput( 238 const media_source & what, 239 bool enabled, 240 int32 * _deprecated_); 241 virtual 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 251 virtual 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 257 virtual 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 292 protected: 293 294 virtual status_t HandleStart( 295 const media_timed_event *event, 296 bigtime_t lateness, 297 bool realTimeEvent = false); 298 virtual status_t HandleSeek( 299 const media_timed_event *event, 300 bigtime_t lateness, 301 bool realTimeEvent = false); 302 virtual status_t HandleWarp( 303 const media_timed_event *event, 304 bigtime_t lateness, 305 bool realTimeEvent = false); 306 virtual status_t HandleStop( 307 const media_timed_event *event, 308 bigtime_t lateness, 309 bool realTimeEvent = false); 310 virtual status_t HandleBuffer( 311 const media_timed_event *event, 312 bigtime_t lateness, 313 bool realTimeEvent = false); 314 virtual status_t HandleDataStatus( 315 const media_timed_event *event, 316 bigtime_t lateness, 317 bool realTimeEvent = false); 318 virtual status_t HandleParameter( 319 const media_timed_event *event, 320 bigtime_t lateness, 321 bool realTimeEvent = false); 322 323 protected: 324 325 void CreateBufferGroup(MediaOutputInfo * output_info); 326 void ComputeInternalLatency(); 327 328 public: 329 330 static void GetFlavor(flavor_info * outInfo, int32 id); 331 332 private: 333 334 static void GetInputFormat(media_format * outFormat); 335 static void GetOutputFormat(media_format * outFormat); 336 337 protected: 338 339 virtual status_t AddRequirements(media_format * format); 340 341 private: 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! */ 359 virtual status_t _Reserved_MediaDemultiplexerNode_0(void *); 360 virtual status_t _Reserved_MediaDemultiplexerNode_1(void *); 361 virtual status_t _Reserved_MediaDemultiplexerNode_2(void *); 362 virtual status_t _Reserved_MediaDemultiplexerNode_3(void *); 363 virtual status_t _Reserved_MediaDemultiplexerNode_4(void *); 364 virtual status_t _Reserved_MediaDemultiplexerNode_5(void *); 365 virtual status_t _Reserved_MediaDemultiplexerNode_6(void *); 366 virtual status_t _Reserved_MediaDemultiplexerNode_7(void *); 367 virtual status_t _Reserved_MediaDemultiplexerNode_8(void *); 368 virtual status_t _Reserved_MediaDemultiplexerNode_9(void *); 369 virtual status_t _Reserved_MediaDemultiplexerNode_10(void *); 370 virtual status_t _Reserved_MediaDemultiplexerNode_11(void *); 371 virtual status_t _Reserved_MediaDemultiplexerNode_12(void *); 372 virtual status_t _Reserved_MediaDemultiplexerNode_13(void *); 373 virtual status_t _Reserved_MediaDemultiplexerNode_14(void *); 374 virtual status_t _Reserved_MediaDemultiplexerNode_15(void *); 375 376 uint32 _reserved_media_demultiplexer_node_[16]; 377 378 }; 379 380 #endif /* _MEDIA_DEMULTIPLEXER_NODE_H */ 381