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