xref: /haiku/src/add-ons/media/media-add-ons/video_mixer/VideoMixerNodeEventLooper.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
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