1 /* 2 * Copyright (C) 2009-2010 David McPaul 3 * 4 * All rights reserved. Distributed under the terms of the MIT License. 5 * VideoMixerNode.cpp 6 * 7 * The VideoMixerNode class 8 * takes in multiple video streams and supplies 9 * a single stream as the output. 10 * each stream is converted to the same colourspace 11 */ 12 13 #include "VideoMixerNode.h" 14 15 // -------------------------------------------------------- // 16 // implementation for BMediaEventLooper 17 // -------------------------------------------------------- // 18 19 void VideoMixerNode::HandleEvent( 20 const media_timed_event *event, 21 bigtime_t lateness, 22 bool realTimeEvent = false) 23 { 24 switch (event->type) { 25 case BTimedEventQueue::B_START: 26 HandleStart(event,lateness,realTimeEvent); 27 break; 28 case BTimedEventQueue::B_SEEK: 29 HandleSeek(event,lateness,realTimeEvent); 30 break; 31 case BTimedEventQueue::B_WARP: 32 HandleWarp(event,lateness,realTimeEvent); 33 break; 34 case BTimedEventQueue::B_STOP: 35 HandleStop(event,lateness,realTimeEvent); 36 break; 37 case BTimedEventQueue::B_HANDLE_BUFFER: 38 if (RunState() == BMediaEventLooper::B_STARTED) { 39 HandleBuffer(event,lateness,realTimeEvent); 40 } 41 break; 42 case BTimedEventQueue::B_DATA_STATUS: 43 HandleDataStatus(event, lateness, realTimeEvent); 44 break; 45 case BTimedEventQueue::B_PARAMETER: 46 HandleParameter(event,lateness,realTimeEvent); 47 break; 48 default: 49 fprintf(stderr," unknown event type: %ld\n",event->type); 50 break; 51 } 52 } 53 54 /* override to clean up custom events you have added to your queue */ 55 void VideoMixerNode::CleanUpEvent( 56 const media_timed_event *event) 57 { 58 BMediaEventLooper::CleanUpEvent(event); 59 } 60 61 /* called from Offline mode to determine the current time of the node */ 62 /* update your internal information whenever it changes */ 63 bigtime_t VideoMixerNode::OfflineTime() 64 { 65 fprintf(stderr,"VideoMixerNode(BMediaEventLooper)::OfflineTime\n"); 66 return BMediaEventLooper::OfflineTime(); 67 // XXX: do something else? 68 } 69 70 /* override only if you know what you are doing! */ 71 /* otherwise much badness could occur */ 72 /* the actual control loop function: */ 73 /* waits for messages, Pops events off the queue and calls DispatchEvent */ 74 void VideoMixerNode::ControlLoop() { 75 BMediaEventLooper::ControlLoop(); 76 } 77 78 // protected: 79 80 status_t VideoMixerNode::HandleStart( 81 const media_timed_event *event, 82 bigtime_t lateness, 83 bool realTimeEvent = false) 84 { 85 fprintf(stderr,"VideoMixerNode(BMediaEventLooper)::HandleStart()\n"); 86 if (RunState() != B_STARTED) { 87 media_timed_event firstBufferEvent(event->event_time, BTimedEventQueue::B_HANDLE_BUFFER); 88 HandleEvent(&firstBufferEvent, 0, false); 89 EventQueue()->AddEvent(firstBufferEvent); 90 } 91 return B_OK; 92 } 93 94 status_t VideoMixerNode::HandleSeek( 95 const media_timed_event *event, 96 bigtime_t lateness, 97 bool realTimeEvent = false) 98 { 99 fprintf(stderr,"VideoMixerNode(BMediaEventLooper)::HandleSeek(t=%lld,d=%ld,bd=%lld)\n",event->event_time, event->data, event->bigdata); 100 return B_OK; 101 } 102 103 status_t VideoMixerNode::HandleWarp( 104 const media_timed_event *event, 105 bigtime_t lateness, 106 bool realTimeEvent = false) 107 { 108 fprintf(stderr,"VideoMixerNode(BMediaEventLooper)::HandleWarp\n"); 109 return B_OK; 110 } 111 112 status_t VideoMixerNode::HandleStop( 113 const media_timed_event *event, 114 bigtime_t lateness, 115 bool realTimeEvent = false) 116 { 117 fprintf(stderr,"VideoMixerNode(BMediaEventLooper)::HandleStop\n"); 118 // flush the queue so downstreamers don't get any more 119 EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER); 120 return B_OK; 121 } 122 123 status_t VideoMixerNode::HandleBuffer( 124 const media_timed_event *event, 125 bigtime_t lateness, 126 bool realTimeEvent = false) 127 { 128 if (event->type != BTimedEventQueue::B_HANDLE_BUFFER) { 129 fprintf(stderr,"HandleBuffer called on non buffer event type\n"); 130 return B_BAD_VALUE; 131 } 132 133 BBuffer *buffer = const_cast<BBuffer*>((BBuffer*)event->pointer); 134 if (buffer == NULL) { 135 fprintf(stderr,"NO BUFFER PASSED\n"); 136 return B_BAD_VALUE; 137 } 138 139 media_input *input = GetInput(buffer->Header()->destination); 140 141 if (input == NULL) { 142 fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n"); 143 return B_MEDIA_BAD_DESTINATION; 144 } 145 146 if (fOutput.format.u.raw_video == media_raw_video_format::wildcard) { 147 fprintf(stderr,"<- B_MEDIA_NOT_CONNECTED\n"); 148 return B_MEDIA_NOT_CONNECTED; 149 } 150 151 status_t status = B_OK; 152 153 if (input == *fConnectedInputs.begin()) { 154 if (bufferMixer.isBufferAvailable()) { 155 status = SendBuffer(bufferMixer.GetOutputBuffer(), fOutput.source, fOutput.destination); 156 } 157 bufferMixer.AddBuffer(input->destination.id, buffer, true); 158 } else { 159 bufferMixer.AddBuffer(input->destination.id, buffer, false); 160 } 161 162 return status; 163 } 164 165 status_t VideoMixerNode::HandleDataStatus( 166 const media_timed_event *event, 167 bigtime_t lateness, 168 bool realTimeEvent = false) 169 { 170 fprintf(stderr,"VideoMixerNode(BMediaEventLooper)::HandleDataStatus"); 171 SendDataStatus(event->data, fOutput.destination, event->event_time); 172 return B_OK; 173 } 174 175 status_t VideoMixerNode::HandleParameter( 176 const media_timed_event *event, 177 bigtime_t lateness, 178 bool realTimeEvent = false) 179 { 180 fprintf(stderr,"VideoMixerNode(BMediaEventLooper)::HandleParameter"); 181 return B_OK; 182 } 183