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