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