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 22void 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 */ 58void 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 */ 66bigtime_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 */ 77void VideoMixerNode::ControlLoop() { 78 BMediaEventLooper::ControlLoop(); 79} 80 81// protected: 82 83status_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 97status_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 106status_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 115status_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 126status_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 168status_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 178status_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