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 19void 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 */ 55void 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 */ 63bigtime_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 */ 74void VideoMixerNode::ControlLoop() { 75 BMediaEventLooper::ControlLoop(); 76} 77 78// protected: 79 80status_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 94status_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 103status_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 112status_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 123status_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 165status_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 175status_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