BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / add-ons / media / media-add-ons / video_mixer / VideoMixerNodeProducer.cpp
blob8fa016b4628cc8379fc5f6b05f2d699e83b27ed0
1 /*
2 * Copyright (C) 2009-2010 David McPaul
4 * All rights reserved. Distributed under the terms of the MIT License.
5 * VideoMixerNode.cpp
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"
15 #include <stdio.h>
16 #include <string.h>
19 // -------------------------------------------------------- //
20 // implemention of BBufferProducer
21 // -------------------------------------------------------- //
23 // They are asking us to make the first offering.
24 // So, we get a fresh format and then add requirements
25 status_t VideoMixerNode::FormatSuggestionRequested(
26 media_type type,
27 int32 quality,
28 media_format * format)
30 fprintf(stderr,"VideoMixerNode(BBufferProducer)::FormatSuggestionRequested\n");
32 if (format->type == B_MEDIA_NO_TYPE) {
33 format->type = B_MEDIA_RAW_VIDEO;
36 if (format->type != B_MEDIA_RAW_VIDEO) {
37 return B_MEDIA_BAD_FORMAT;
40 GetOutputFormat(format);
42 return B_OK;
45 // They made an offer to us. We should make sure that the offer is
46 // acceptable, and then we can add any requirements we have on top of
47 // that. We leave wildcards for anything that we don't care about.
48 status_t VideoMixerNode::FormatProposal(
49 const media_source &output_source,
50 media_format *format)
52 fprintf(stderr,"VideoMixerNode(BBufferProducer)::FormatProposal\n");
54 fOutput.source = output_source;
56 // If we have an input then set our output as the same except for color_space
57 if (fConnectedInputs.size() > 0) {
58 if (fOutput.format.u.raw_video == media_raw_video_format::wildcard) {
59 // First proposal
60 fOutput.format = fConnectedInputs[0]->format;
61 fOutput.format.u.raw_video.display.format = B_NO_COLOR_SPACE;
62 } else {
63 // Second proposal
64 fOutput.format = fConnectedInputs[0]->format;
65 fOutput.format.u.raw_video.display.format = B_RGBA32;
69 *format = fOutput.format;
71 return B_OK;
74 // Presumably we have already agreed with them that this format is
75 // okay. But just in case, we check the offer. (and complain if it
76 // is invalid) Then as the last thing we do, we get rid of any
77 // remaining wilcards.
78 status_t VideoMixerNode::FormatChangeRequested(
79 const media_source &source,
80 const media_destination &destination,
81 media_format *io_format,
82 int32 * _deprecated_)
84 fprintf(stderr,"VideoMixerNode(BBufferProducer)::FormatChangeRequested\n");
86 if (fOutput.source != source) {
87 // we don't have that output
88 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
89 return B_MEDIA_BAD_SOURCE;
92 fOutput.destination = destination;
93 fOutput.format = *io_format;
95 return B_OK;
98 status_t VideoMixerNode::GetNextOutput( /* cookie starts as 0 */
99 int32 *cookie,
100 media_output *out_output)
102 fprintf(stderr,"VideoMixerNode(BBufferProducer)::GetNextOutput (%ld)\n",*cookie);
104 // only 1 output
105 if (*cookie != 0) {
106 fprintf(stderr,"<- B_ERROR (no more outputs)\n");
107 return B_ERROR;
110 *out_output = fOutput;
111 *cookie = 1;
113 return B_OK;
116 status_t VideoMixerNode::DisposeOutputCookie(int32 cookie)
118 fprintf(stderr,"VideoMixerNode(BBufferProducer)::DisposeOutputCookie\n");
119 // nothing to do since our cookies are part of the vector iterator
120 return B_OK;
123 status_t VideoMixerNode::SetBufferGroup(
124 const media_source & for_source,
125 BBufferGroup * group)
127 fprintf(stderr,"VideoMixerNode(BBufferProducer)::SetBufferGroup\n");
129 if (fOutput.source != for_source) {
130 // we don't have that output
131 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
132 return B_MEDIA_BAD_SOURCE;
135 return B_OK;
138 /* Format of clipping is (as int16-s): <from line> <npairs> <startclip> <endclip>. */
139 /* Repeat for each line where the clipping is different from the previous line. */
140 /* If <npairs> is negative, use the data from line -<npairs> (there are 0 pairs after */
141 /* a negative <npairs>. Yes, we only support 32k*32k frame buffers for clipping. */
142 /* Any non-0 field of 'display' means that that field changed, and if you don't support */
143 /* that change, you should return an error and ignore the request. Note that the buffer */
144 /* offset values do not have wildcards; 0 (or -1, or whatever) are real values and must */
145 /* be adhered to. */
146 status_t VideoMixerNode::VideoClippingChanged(
147 const media_source & for_source,
148 int16 num_shorts,
149 int16 * clip_data,
150 const media_video_display_info & display,
151 int32 * _deprecated_)
153 return BBufferProducer::VideoClippingChanged(for_source, num_shorts, clip_data, display, _deprecated_);
156 status_t VideoMixerNode::GetLatency(
157 bigtime_t *out_latency)
159 fprintf(stderr,"VideoMixerNode(BBufferProducer)::GetLatency\n");
160 if (out_latency == NULL) {
161 fprintf(stderr,"<- B_BAD_VALUE\n");
162 return B_BAD_VALUE;
165 *out_latency = EventLatency() + SchedulingLatency();
166 return B_OK;
169 status_t VideoMixerNode::PrepareToConnect(
170 const media_source &what,
171 const media_destination &where,
172 media_format *format,
173 media_source *out_source,
174 char *out_name)
176 fprintf(stderr,"VideoMixerNode(BBufferProducer)::PrepareToConnect\n");
178 if (fOutput.source != what) {
179 // we don't have that output
180 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
181 return B_MEDIA_BAD_SOURCE;
184 *out_source = fOutput.source;
185 strcpy(out_name, fOutput.name);
187 fOutput.destination = where;
189 return B_OK;
192 void VideoMixerNode::Connect(
193 status_t error,
194 const media_source &source,
195 const media_destination &destination,
196 const media_format &format,
197 char *io_name)
199 fprintf(stderr,"VideoMixerNode(BBufferProducer)::Connect\n");
201 if (fOutput.source != source) {
202 // we don't have that output
203 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
204 return;
207 if (error != B_OK) {
208 fprintf(stderr,"<- error already\n");
209 fOutput.destination = media_destination::null;
210 fOutput.format.u.raw_video = media_raw_video_format::wildcard;
211 return;
214 // calculate the downstream latency
215 // must happen before itr->Connect
216 bigtime_t downstreamLatency;
217 media_node_id id;
218 FindLatencyFor(fOutput.destination, &downstreamLatency, &id);
220 // record the agreed upon values
221 fOutput.format = format;
222 fOutput.destination = destination;
223 strcpy(io_name, fOutput.name);
225 // compute the internal latency
226 // must happen after itr->Connect
227 if (fInternalLatency == 0) {
228 fInternalLatency = 100; // temporary until we finish computing it
229 ComputeInternalLatency();
232 // If the downstream latency for this output is larger
233 // than our current downstream latency, we have to increase
234 // our current downstream latency to be the larger value.
235 if (downstreamLatency > fDownstreamLatency) {
236 SetEventLatency(fDownstreamLatency + fInternalLatency);
240 void VideoMixerNode::ComputeInternalLatency() {
241 fprintf(stderr,"VideoMixerNode(BBufferProducer)::ComputeInternalLatency\n");
242 fInternalLatency = 100; // just guess
243 fprintf(stderr," internal latency guessed = %lld\n",fInternalLatency);
246 void VideoMixerNode::Disconnect(
247 const media_source & what,
248 const media_destination & where)
250 fprintf(stderr,"VideoMixerNode(BBufferProducer)::Disconnect\n");
252 if (fOutput.source != what) {
253 // we don't have that output
254 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
255 return;
258 if (fOutput.destination != where) {
259 fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
260 return;
263 fOutput.destination = media_destination::null;
264 GetOutputFormat(&fOutput.format);
267 void VideoMixerNode::LateNoticeReceived(
268 const media_source & what,
269 bigtime_t how_much,
270 bigtime_t performance_time)
272 fprintf(stderr,"VideoMixerNode(BBufferProducer)::LateNoticeReceived\n");
274 if (fOutput.source != what) {
275 // we don't have that output
276 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
277 return;
280 switch (RunMode()) {
281 case B_OFFLINE:
282 // nothing to do
283 break;
284 case B_RECORDING:
285 // nothing to do
286 break;
287 case B_INCREASE_LATENCY:
288 fInternalLatency += how_much;
289 SetEventLatency(fDownstreamLatency + fInternalLatency);
290 break;
291 case B_DECREASE_PRECISION:
292 // XXX: try to catch up by producing buffers faster
293 break;
294 case B_DROP_DATA:
295 // XXX: should we really drop buffers? just for that output?
296 break;
297 default:
298 fprintf(stderr,"VideoMixerNode::LateNoticeReceived with unexpected run mode.\n");
299 break;
303 void VideoMixerNode::EnableOutput(
304 const media_source &what,
305 bool enabled,
306 int32 *_deprecated_)
308 fprintf(stderr,"VideoMixerNode(BBufferProducer)::EnableOutput\n");
310 if (fOutput.source != what) {
311 // we don't have that output
312 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
313 return;
316 status_t status = B_OK;
317 if (status != B_OK) {
318 fprintf(stderr," error in itr->EnableOutput\n");
322 status_t VideoMixerNode::SetPlayRate(
323 int32 numer,
324 int32 denom)
326 BBufferProducer::SetPlayRate(numer, denom); // XXX: do something intelligent later
327 return B_OK;
330 void VideoMixerNode::AdditionalBufferRequested( // used to be Reserved 0
331 const media_source & source,
332 media_buffer_id prev_buffer,
333 bigtime_t prev_time,
334 const media_seek_tag * prev_tag)
336 fprintf(stderr,"VideoMixerNode(BBufferProducer)::AdditionalBufferRequested\n");
338 if (fOutput.source != source) {
339 // we don't have that output
340 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
341 return;
344 // BBuffer * buffer;
345 // status_t status = itr->AdditionalBufferRequested(prev_buffer, prev_time, prev_tag);
346 // if (status != B_OK) {
347 // fprintf(stderr," itr->AdditionalBufferRequested returned an error.\n");
348 // }
351 void VideoMixerNode::LatencyChanged(
352 const media_source & source,
353 const media_destination & destination,
354 bigtime_t new_latency,
355 uint32 flags)
357 fprintf(stderr,"VideoMixerNode(BBufferProducer)::LatencyChanged\n");
359 if (fOutput.source != source) {
360 // we don't have that output
361 fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
362 return;
365 if (fOutput.destination != destination) {
366 fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
367 return;
370 fDownstreamLatency = new_latency;
371 SetEventLatency(fDownstreamLatency + fInternalLatency);
373 // XXX: we may have to recompute the number of buffers that we are using
374 // see SetBufferGroup