2 * Copyright (C) 2009-2010 David McPaul
4 * All rights reserved. Distributed under the terms of the MIT License.
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
13 #include "VideoMixerNode.h"
18 // -------------------------------------------------------- //
19 // implemention of BBufferConsumer
20 // -------------------------------------------------------- //
22 // Check to make sure the format is okay, then remove
23 // any wildcards corresponding to our requirements.
24 status_t
VideoMixerNode::AcceptFormat(
25 const media_destination
&dest
,
28 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::AcceptFormat\n");
30 if (fInitialInput
.destination
!= dest
) {
31 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION");
32 return B_MEDIA_BAD_DESTINATION
; // none of our inputs matched the dest
35 media_format myFormat
;
37 GetInputFormat(&myFormat
);
39 AddRequirements(format
);
44 status_t
VideoMixerNode::GetNextInput(
46 media_input
*out_input
)
48 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::GetNextInput (%ld)\n",*cookie
);
50 // Cookie 0 is the connecting input, all others are connected inputs
51 if (uint32(*cookie
) == fConnectedInputs
.size()) {
52 *out_input
= fInitialInput
;
54 out_input
= GetInput(*cookie
);
56 if (out_input
== NULL
) {
57 fprintf(stderr
,"<- B_ERROR (no more inputs)\n");
62 // so next time they won't get the same input again
68 void VideoMixerNode::DisposeInputCookie(
71 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::DisposeInputCookie\n");
72 // nothing to do since our cookies are just integers
75 void VideoMixerNode::BufferReceived(BBuffer
*buffer
)
77 switch (buffer
->Header()->type
) {
78 // case B_MEDIA_PARAMETERS:
80 // status_t status = ApplyParameterData(buffer->Data(),buffer->SizeUsed());
81 // if (status != B_OK) {
82 // fprintf(stderr,"ApplyParameterData in MediaDemultiplexerNode::BufferReceived failed\n");
87 case B_MEDIA_RAW_VIDEO
:
88 if (buffer
->Flags() & BBuffer::B_SMALL_BUFFER
) {
89 fprintf(stderr
,"NOT IMPLEMENTED: B_SMALL_BUFFER in VideoMixerNode::BufferReceived\n");
90 // XXX: implement this part
93 media_timed_event
event(buffer
->Header()->start_time
, BTimedEventQueue::B_HANDLE_BUFFER
,
94 buffer
, BTimedEventQueue::B_RECYCLE_BUFFER
);
95 status_t status
= EventQueue()->AddEvent(event
);
97 fprintf(stderr
,"EventQueue()->AddEvent(event) in VideoMixerNode::BufferReceived failed\n");
103 fprintf(stderr
,"unexpected buffer type in VideoMixerNode::BufferReceived\n");
109 void VideoMixerNode::ProducerDataStatus(
110 const media_destination
&for_whom
,
112 bigtime_t at_performance_time
)
114 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::ProducerDataStatus\n");
115 media_input
*input
= GetInput(for_whom
);
118 fprintf(stderr
,"invalid destination received in VideoMixerNode::ProducerDataStatus\n");
122 media_timed_event
event(at_performance_time
, BTimedEventQueue::B_DATA_STATUS
,
123 &input
, BTimedEventQueue::B_NO_CLEANUP
, status
, 0, NULL
);
124 EventQueue()->AddEvent(event
);
127 status_t
VideoMixerNode::GetLatencyFor(
128 const media_destination
&for_whom
,
129 bigtime_t
*out_latency
,
130 media_node_id
*out_timesource
)
132 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::GetLatencyFor\n");
133 if ((out_latency
== 0) || (out_timesource
== 0)) {
134 fprintf(stderr
,"<- B_BAD_VALUE\n");
138 media_input
*input
= GetInput(for_whom
);
141 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
142 return B_MEDIA_BAD_DESTINATION
;
145 *out_latency
= EventLatency();
146 *out_timesource
= TimeSource()->ID();
151 status_t
VideoMixerNode::Connected(
152 const media_source
&producer
, /* here's a good place to request buffer group usage */
153 const media_destination
&where
,
154 const media_format
&with_format
,
155 media_input
*out_input
)
157 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::Connected\n");
159 if (fInitialInput
.destination
!= where
) {
160 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
161 return B_MEDIA_BAD_DESTINATION
;
164 media_input
*input
= CreateInput(fConnectedInputs
.size());
165 fConnectedInputs
.push_back(input
);
167 // Specialise the output?
169 // compute the latency or just guess
170 fInternalLatency
= 500; // just a guess
171 fprintf(stderr
," internal latency guessed = %lld\n", fInternalLatency
);
173 SetEventLatency(fInternalLatency
);
175 // record the agreed upon values
176 input
->destination
= where
;
177 input
->source
= producer
;
178 input
->format
= with_format
;
182 // Reset the Initial Input
183 ClearInput(&fInitialInput
);
184 fInitialInput
.destination
.id
= fConnectedInputs
.size();
185 fInitialInput
.destination
.port
= ControlPort();
190 void VideoMixerNode::Disconnected(
191 const media_source
&producer
,
192 const media_destination
&where
)
194 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::Disconnected\n");
196 media_input
*input
= GetInput(where
);
199 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
203 if (input
->source
!= producer
) {
204 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
208 bufferMixer
.RemoveBuffer(input
->destination
.id
);
210 // disconnected but not deleted (important)
211 input
->source
= media_source::null
;
212 GetInputFormat(&input
->format
);
215 /* The notification comes from the upstream producer, so he's already cool with */
216 /* the format; you should not ask him about it in here. */
217 status_t
VideoMixerNode::FormatChanged(
218 const media_source
& producer
,
219 const media_destination
& consumer
,
221 const media_format
& format
)
223 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::FormatChanged\n");
225 media_input
*input
= GetInput(producer
);
228 return B_MEDIA_BAD_SOURCE
;
231 if (input
->destination
!= consumer
) {
232 return B_MEDIA_BAD_DESTINATION
;
235 input
->format
= format
;
239 /* Given a performance time of some previous buffer, retrieve the remembered tag */
240 /* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
241 /* idea being that flags can be added later, and the understood flags returned in */
243 status_t
VideoMixerNode::SeekTagRequested(
244 const media_destination
& destination
,
245 bigtime_t in_target_time
,
247 media_seek_tag
* out_seek_tag
,
248 bigtime_t
* out_tagged_time
,
251 fprintf(stderr
,"VideoMixerNode(BBufferConsumer)::SeekTagRequested\n");
252 // XXX: implement this
253 return BBufferConsumer::SeekTagRequested(destination
,in_target_time
, in_flags
,
254 out_seek_tag
, out_tagged_time
, out_flags
);