1 // MediaDemultiplexerNode.cpp
3 // Andrew Bachmann, 2002
5 // The MediaDemultiplexerNode class
6 // takes a multistream input and supplies
7 // the individual constituent streams as
10 #include <MediaDefs.h>
11 #include <MediaNode.h>
12 #include <MediaAddOn.h>
13 #include <BufferConsumer.h>
14 #include <BufferProducer.h>
15 #include <MediaEventLooper.h>
17 #include <BufferGroup.h>
18 #include <TimeSource.h>
22 #include "MediaDemultiplexerNode.h"
28 // -------------------------------------------------------- //
30 // -------------------------------------------------------- //
32 MediaDemultiplexerNode::~MediaDemultiplexerNode(void)
34 fprintf(stderr
,"MediaDemultiplexerNode::~MediaDemultiplexerNode\n");
35 // Stop the BMediaEventLooper thread
39 MediaDemultiplexerNode::MediaDemultiplexerNode(
40 const flavor_info
* info
= 0,
41 BMessage
* config
= 0,
42 BMediaAddOn
* addOn
= 0)
43 : BMediaNode("MediaDemultiplexerNode"),
45 BBufferConsumer(B_MEDIA_MULTISTREAM
),
46 BBufferProducer(B_MEDIA_UNKNOWN_TYPE
) // no B_MEDIA_ANY
48 fprintf(stderr
,"MediaDemultiplexerNode::MediaDemultiplexerNode\n");
49 // keep our creator around for AddOn calls later
51 // null out our latency estimates
52 fDownstreamLatency
= 0;
54 // don't overwrite available space, and be sure to terminate
55 strncpy(input
.name
,"Demultiplexer Input",B_MEDIA_NAME_LENGTH
-1);
56 input
.name
[B_MEDIA_NAME_LENGTH
-1] = '\0';
57 // initialize the input
58 input
.node
= media_node::null
; // until registration
59 input
.source
= media_source::null
;
60 input
.destination
= media_destination::null
; // until registration
61 GetInputFormat(&input
.format
);
64 // outputs initialized after we connect,
65 // find a suitable extractor,
66 // and it tells us the ouputs
68 fInitCheckStatus
= B_OK
;
71 status_t
MediaDemultiplexerNode::InitCheck(void) const
73 fprintf(stderr
,"MediaDemultiplexerNode::InitCheck\n");
74 return fInitCheckStatus
;
77 status_t
MediaDemultiplexerNode::GetConfigurationFor(
78 BMessage
* into_message
)
80 fprintf(stderr
,"MediaDemultiplexerNode::GetConfigurationFor\n");
84 // -------------------------------------------------------- //
85 // implementation of BMediaNode
86 // -------------------------------------------------------- //
88 BMediaAddOn
* MediaDemultiplexerNode::AddOn(
89 int32
* internal_id
) const
91 fprintf(stderr
,"MediaDemultiplexerNode::AddOn\n");
92 // BeBook says this only gets called if we were in an add-on.
94 // If we get a null pointer then we just won't write.
95 if (internal_id
!= 0) {
102 void MediaDemultiplexerNode::Start(
103 bigtime_t performance_time
)
105 fprintf(stderr
,"MediaDemultiplexerNode::Start(pt=%lld)\n",performance_time
);
106 BMediaEventLooper::Start(performance_time
);
109 void MediaDemultiplexerNode::Stop(
110 bigtime_t performance_time
,
114 fprintf(stderr
,"MediaDemultiplexerNode::Stop(pt=%lld,<immediate>)\n",performance_time
);
116 fprintf(stderr
,"MediaDemultiplexerNode::Stop(pt=%lld,<scheduled>)\n",performance_time
);
118 BMediaEventLooper::Stop(performance_time
,immediate
);
121 void MediaDemultiplexerNode::Seek(
122 bigtime_t media_time
,
123 bigtime_t performance_time
)
125 fprintf(stderr
,"MediaDemultiplexerNode::Seek(mt=%lld,pt=%lld)\n",media_time
,performance_time
);
126 BMediaEventLooper::Seek(media_time
,performance_time
);
129 void MediaDemultiplexerNode::SetRunMode(
132 fprintf(stderr
,"MediaDemultiplexerNode::SetRunMode(%i)\n",mode
);
133 BMediaEventLooper::SetRunMode(mode
);
136 void MediaDemultiplexerNode::TimeWarp(
137 bigtime_t at_real_time
,
138 bigtime_t to_performance_time
)
140 fprintf(stderr
,"MediaDemultiplexerNode::TimeWarp(rt=%lld,pt=%lld)\n",at_real_time
,to_performance_time
);
141 BMediaEventLooper::TimeWarp(at_real_time
,to_performance_time
);
144 void MediaDemultiplexerNode::Preroll(void)
146 fprintf(stderr
,"MediaDemultiplexerNode::Preroll\n");
147 // XXX:Performance opportunity
148 BMediaNode::Preroll();
151 void MediaDemultiplexerNode::SetTimeSource(
152 BTimeSource
* time_source
)
154 fprintf(stderr
,"MediaDemultiplexerNode::SetTimeSource\n");
155 BMediaNode::SetTimeSource(time_source
);
158 status_t
MediaDemultiplexerNode::HandleMessage(
163 fprintf(stderr
,"MediaDemultiplexerNode::HandleMessage\n");
164 status_t status
= B_OK
;
166 // no special messages for now
168 status
= BBufferConsumer::HandleMessage(message
,data
,size
);
169 if (status
== B_OK
) {
172 status
= BBufferProducer::HandleMessage(message
,data
,size
);
173 if (status
== B_OK
) {
176 status
= BMediaNode::HandleMessage(message
,data
,size
);
177 if (status
== B_OK
) {
180 BMediaNode::HandleBadMessage(message
,data
,size
);
187 status_t
MediaDemultiplexerNode::RequestCompleted(
188 const media_request_info
& info
)
190 fprintf(stderr
,"MediaDemultiplexerNode::RequestCompleted\n");
191 return BMediaNode::RequestCompleted(info
);
194 status_t
MediaDemultiplexerNode::DeleteHook(
197 fprintf(stderr
,"MediaDemultiplexerNode::DeleteHook\n");
198 return BMediaEventLooper::DeleteHook(node
);
201 void MediaDemultiplexerNode::NodeRegistered(void)
203 fprintf(stderr
,"MediaDemultiplexerNode::NodeRegistered\n");
205 // now we can do this
207 input
.destination
.id
= 0;
208 input
.destination
.port
= input
.node
.port
; // same as ControlPort()
210 // outputs initialized after we connect,
211 // find a suitable extractor,
212 // and it tells us the ouputs
214 // start the BMediaEventLooper thread
215 SetPriority(B_REAL_TIME_PRIORITY
);
219 status_t
MediaDemultiplexerNode::GetNodeAttributes(
220 media_node_attribute
* outAttributes
,
223 fprintf(stderr
,"MediaDemultiplexerNode::GetNodeAttributes\n");
224 return BMediaNode::GetNodeAttributes(outAttributes
,inMaxCount
);
227 status_t
MediaDemultiplexerNode::AddTimer(
228 bigtime_t at_performance_time
,
231 fprintf(stderr
,"MediaDemultiplexerNode::AddTimer\n");
232 return BMediaEventLooper::AddTimer(at_performance_time
,cookie
);
235 // -------------------------------------------------------- //
236 // implemention of BBufferConsumer
237 // -------------------------------------------------------- //
239 // Check to make sure the format is okay, then remove
240 // any wildcards corresponding to our requirements.
241 status_t
MediaDemultiplexerNode::AcceptFormat(
242 const media_destination
& dest
,
243 media_format
* format
)
245 fprintf(stderr
,"MediaDemultiplexerNode::AcceptFormat\n");
246 if (input
.destination
!= dest
) {
247 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION");
248 return B_MEDIA_BAD_DESTINATION
; // we only have one input so that better be it
250 media_format myFormat
;
251 GetInputFormat(&myFormat
);
252 // Be's format_is_compatible doesn't work,
253 // so use our format_is_acceptible instead
254 if (!format_is_acceptible(*format
,myFormat
)) {
255 fprintf(stderr
,"<- B_MEDIA_BAD_FORMAT\n");
256 return B_MEDIA_BAD_FORMAT
;
258 AddRequirements(format
);
262 status_t
MediaDemultiplexerNode::GetNextInput(
264 media_input
* out_input
)
266 fprintf(stderr
,"MediaDemultiplexerNode::GetNextInput\n");
268 fprintf(stderr
,"<- B_ERROR (no more inputs)\n");
272 // so next time they won't get the same input again
278 void MediaDemultiplexerNode::DisposeInputCookie(
281 fprintf(stderr
,"MediaDemultiplexerNode::DisposeInputCookie\n");
282 // nothing to do since our cookies are just integers
286 void MediaDemultiplexerNode::BufferReceived(
289 fprintf(stderr
,"MediaDemultiplexerNode::BufferReceived\n");
290 switch (buffer
->Header()->type
) {
291 // case B_MEDIA_PARAMETERS:
293 // status_t status = ApplyParameterData(buffer->Data(),buffer->SizeUsed());
294 // if (status != B_OK) {
295 // fprintf(stderr,"ApplyParameterData in MediaDemultiplexerNode::BufferReceived failed\n");
297 // buffer->Recycle();
300 case B_MEDIA_MULTISTREAM
:
301 if (buffer
->Flags() & BBuffer::B_SMALL_BUFFER
) {
302 fprintf(stderr
,"NOT IMPLEMENTED: B_SMALL_BUFFER in MediaDemultiplexerNode::BufferReceived\n");
303 // XXX: implement this part
306 media_timed_event
event(buffer
->Header()->start_time
, BTimedEventQueue::B_HANDLE_BUFFER
,
307 buffer
, BTimedEventQueue::B_RECYCLE_BUFFER
);
308 status_t status
= EventQueue()->AddEvent(event
);
309 if (status
!= B_OK
) {
310 fprintf(stderr
,"EventQueue()->AddEvent(event) in MediaDemultiplexerNode::BufferReceived failed\n");
316 fprintf(stderr
,"unexpected buffer type in MediaDemultiplexerNode::BufferReceived\n");
322 void MediaDemultiplexerNode::ProducerDataStatus(
323 const media_destination
& for_whom
,
325 bigtime_t at_performance_time
)
327 fprintf(stderr
,"MediaDemultiplexerNode::ProducerDataStatus\n");
328 if (input
.destination
!= for_whom
) {
329 fprintf(stderr
,"invalid destination received in MediaDemultiplexerNode::ProducerDataStatus\n");
332 media_timed_event
event(at_performance_time
, BTimedEventQueue::B_DATA_STATUS
,
333 &input
, BTimedEventQueue::B_NO_CLEANUP
, status
, 0, NULL
);
334 EventQueue()->AddEvent(event
);
337 status_t
MediaDemultiplexerNode::GetLatencyFor(
338 const media_destination
& for_whom
,
339 bigtime_t
* out_latency
,
340 media_node_id
* out_timesource
)
342 fprintf(stderr
,"MediaDemultiplexerNode::GetLatencyFor\n");
343 if ((out_latency
== 0) || (out_timesource
== 0)) {
344 fprintf(stderr
,"<- B_BAD_VALUE\n");
347 if (input
.destination
!= for_whom
) {
348 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
349 return B_MEDIA_BAD_DESTINATION
;
351 *out_latency
= EventLatency();
352 *out_timesource
= TimeSource()->ID();
356 status_t
MediaDemultiplexerNode::Connected(
357 const media_source
& producer
, /* here's a good place to request buffer group usage */
358 const media_destination
& where
,
359 const media_format
& with_format
,
360 media_input
* out_input
)
362 fprintf(stderr
,"MediaDemultiplexerNode::Connected\n");
363 if (input
.destination
!= where
) {
364 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
365 return B_MEDIA_BAD_DESTINATION
;
368 // find an appropriate extractor to handle this type
369 fprintf(stderr
," XXX: no extractors yet\n");
371 // initialize the outputs here
372 // provide all the types that the extractor claims
375 // compute the latency or just guess
376 fInternalLatency
= 500; // just guess
377 fprintf(stderr
," internal latency guessed = %lld\n",fInternalLatency
);
379 SetEventLatency(fInternalLatency
);
381 // record the agreed upon values
382 input
.source
= producer
;
383 input
.format
= with_format
;
388 void MediaDemultiplexerNode::Disconnected(
389 const media_source
& producer
,
390 const media_destination
& where
)
392 fprintf(stderr
,"MediaDemultiplexerNode::Disconnected\n");
393 if (input
.destination
!= where
) {
394 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
397 if (input
.source
!= producer
) {
398 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
401 input
.source
= media_source::null
;
402 GetInputFormat(&input
.format
);
407 /* The notification comes from the upstream producer, so he's already cool with */
408 /* the format; you should not ask him about it in here. */
409 status_t
MediaDemultiplexerNode::FormatChanged(
410 const media_source
& producer
,
411 const media_destination
& consumer
,
413 const media_format
& format
)
415 fprintf(stderr
,"MediaDemultiplexerNode::FormatChanged\n");
416 if (input
.source
!= producer
) {
417 return B_MEDIA_BAD_SOURCE
;
419 if (input
.destination
!= consumer
) {
420 return B_MEDIA_BAD_DESTINATION
;
423 fprintf(stderr
," This is because we asked to have the format changed.\n"
424 " Therefore we must switch to the other extractor that\n"
425 " we presumably have ready.");
426 input
.format
= format
;
430 /* Given a performance time of some previous buffer, retrieve the remembered tag */
431 /* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
432 /* idea being that flags can be added later, and the understood flags returned in */
434 status_t
MediaDemultiplexerNode::SeekTagRequested(
435 const media_destination
& destination
,
436 bigtime_t in_target_time
,
438 media_seek_tag
* out_seek_tag
,
439 bigtime_t
* out_tagged_time
,
442 fprintf(stderr
,"MediaDemultiplexerNode::SeekTagRequested\n");
443 // XXX: implement this
444 return BBufferConsumer::SeekTagRequested(destination
,in_target_time
,in_flags
,
445 out_seek_tag
,out_tagged_time
,out_flags
);
448 // -------------------------------------------------------- //
449 // implemention of BBufferProducer
450 // -------------------------------------------------------- //
452 // They are asking us to make the first offering.
453 // So, we get a fresh format and then add requirements
454 status_t
MediaDemultiplexerNode::FormatSuggestionRequested(
457 media_format
* format
)
459 fprintf(stderr
,"MediaDemultiplexerNode::FormatSuggestionRequested\n");
460 // XXX: how do I pick which stream to supply here?....
461 // answer?: get the first compatible stream that is available
462 fprintf(stderr
," format suggestion requested not implemented\n");
463 // if ((type != B_MEDIA_MULTISTREAM) && (type != B_MEDIA_UNKNOWN_TYPE)) {
464 // fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n");
465 // return B_MEDIA_BAD_FORMAT;
467 GetOutputFormat(format
);
468 // AddRequirements(format);
473 // They made an offer to us. We should make sure that the offer is
474 // acceptable, and then we can add any requirements we have on top of
475 // that. We leave wildcards for anything that we don't care about.
476 status_t
MediaDemultiplexerNode::FormatProposal(
477 const media_source
& output_source
,
478 media_format
* format
)
480 fprintf(stderr
,"MediaDemultiplexerNode::FormatProposal\n");
481 // find the information for this output
482 vector
<MediaOutputInfo
>::iterator itr
;
483 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
484 if (itr
->output
.source
== output_source
) {
488 if (itr
== outputs
.end()) {
489 // we don't have that output
490 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
491 return B_MEDIA_BAD_SOURCE
;
493 return itr
->FormatProposal(format
);
496 // Presumably we have already agreed with them that this format is
497 // okay. But just in case, we check the offer. (and complain if it
498 // is invalid) Then as the last thing we do, we get rid of any
499 // remaining wilcards.
500 status_t
MediaDemultiplexerNode::FormatChangeRequested(
501 const media_source
& source
,
502 const media_destination
& destination
,
503 media_format
* io_format
,
504 int32
* _deprecated_
)
506 fprintf(stderr
,"MediaDemultiplexerNode::FormatChangeRequested\n");
507 // find the information for this output
508 vector
<MediaOutputInfo
>::iterator itr
;
509 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
510 if (itr
->output
.source
== source
) {
514 if (itr
== outputs
.end()) {
515 // we don't have that output
516 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
517 return B_MEDIA_BAD_SOURCE
;
519 return itr
->FormatChangeRequested(destination
,io_format
);
522 status_t
MediaDemultiplexerNode::GetNextOutput( /* cookie starts as 0 */
524 media_output
* out_output
)
526 fprintf(stderr
,"MediaDemultiplexerNode::GetNextOutput\n");
527 // they want a clean start
529 *cookie
= (int32
)outputs
.begin();
531 vector
<MediaOutputInfo
>::iterator itr
532 = (vector
<MediaOutputInfo
>::iterator
)(*cookie
);
533 // XXX: check here if the vector has been modified.
534 // if the iterator is invalid, return an error code??
536 // they already got our 1 output
537 if (itr
== outputs
.end()) {
538 fprintf(stderr
,"<- B_ERROR (no more outputs)\n");
541 // return this output
542 *out_output
= itr
->output
;
543 // so next time they won't get the same output again
544 *cookie
= (int32
)++itr
;
548 status_t
MediaDemultiplexerNode::DisposeOutputCookie(
551 fprintf(stderr
,"MediaDemultiplexerNode::DisposeOutputCookie\n");
552 // nothing to do since our cookies are part of the vector iterator
556 status_t
MediaDemultiplexerNode::SetBufferGroup(
557 const media_source
& for_source
,
558 BBufferGroup
* group
)
560 fprintf(stderr
,"MediaDemultiplexerNode::SetBufferGroup\n");
561 // find the information for this output
562 vector
<MediaOutputInfo
>::iterator itr
;
563 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
564 if (itr
->output
.source
== for_source
) {
568 if (itr
== outputs
.end()) {
569 // we don't have that output
570 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
571 return B_MEDIA_BAD_SOURCE
;
573 return itr
->SetBufferGroup(group
);
576 /* Format of clipping is (as int16-s): <from line> <npairs> <startclip> <endclip>. */
577 /* Repeat for each line where the clipping is different from the previous line. */
578 /* If <npairs> is negative, use the data from line -<npairs> (there are 0 pairs after */
579 /* a negative <npairs>. Yes, we only support 32k*32k frame buffers for clipping. */
580 /* Any non-0 field of 'display' means that that field changed, and if you don't support */
581 /* that change, you should return an error and ignore the request. Note that the buffer */
582 /* offset values do not have wildcards; 0 (or -1, or whatever) are real values and must */
584 status_t
MediaDemultiplexerNode::VideoClippingChanged(
585 const media_source
& for_source
,
588 const media_video_display_info
& display
,
589 int32
* _deprecated_
)
591 return BBufferProducer::VideoClippingChanged(for_source
,num_shorts
,clip_data
,display
,_deprecated_
);
594 status_t
MediaDemultiplexerNode::GetLatency(
595 bigtime_t
* out_latency
)
597 fprintf(stderr
,"MediaDemultiplexerNode::GetLatency\n");
598 if (out_latency
== 0) {
599 fprintf(stderr
,"<- B_BAD_VALUE\n");
602 *out_latency
= EventLatency() + SchedulingLatency();
606 status_t
MediaDemultiplexerNode::PrepareToConnect(
607 const media_source
& what
,
608 const media_destination
& where
,
609 media_format
* format
,
610 media_source
* out_source
,
613 fprintf(stderr
,"MediaDemultiplexerNode::PrepareToConnect\n");
614 // find the information for this output
615 vector
<MediaOutputInfo
>::iterator itr
;
616 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
617 if (itr
->output
.source
== what
) {
621 if (itr
== outputs
.end()) {
622 // we don't have that output
623 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
624 return B_MEDIA_BAD_SOURCE
;
626 return itr
->PrepareToConnect(where
,format
,out_source
,out_name
);
629 void MediaDemultiplexerNode::Connect(
631 const media_source
& source
,
632 const media_destination
& destination
,
633 const media_format
& format
,
636 fprintf(stderr
,"MediaDemultiplexerNode::Connect\n");
637 // find the information for this output
638 vector
<MediaOutputInfo
>::iterator itr
;
639 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
640 if (itr
->output
.source
== source
) {
644 if (itr
== outputs
.end()) {
645 // we don't have that output
646 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
650 fprintf(stderr
,"<- error already\n");
651 itr
->output
.destination
= media_destination::null
;
652 itr
->output
.format
= itr
->generalFormat
;
656 // calculate the downstream latency
657 // must happen before itr->Connect
658 bigtime_t downstreamLatency
;
660 FindLatencyFor(itr
->output
.destination
, &downstreamLatency
, &id
);
662 // record the agreed upon values
664 status
= itr
->Connect(destination
,format
,io_name
,downstreamLatency
);
665 if (status
!= B_OK
) {
666 fprintf(stderr
," itr->Connect returned an error\n");
670 // compute the internal latency
671 // must happen after itr->Connect
672 if (fInternalLatency
== 0) {
673 fInternalLatency
= 100; // temporary until we finish computing it
674 ComputeInternalLatency();
677 // If the downstream latency for this output is larger
678 // than our current downstream latency, we have to increase
679 // our current downstream latency to be the larger value.
680 if (downstreamLatency
> fDownstreamLatency
) {
681 SetEventLatency(fDownstreamLatency
+ fInternalLatency
);
684 // XXX: what do I set the buffer duration to?
685 // it depends on which output is sending!!
686 // SetBufferDuration(bufferPeriod);
688 // XXX: do anything else?
692 void MediaDemultiplexerNode::ComputeInternalLatency() {
693 fprintf(stderr
,"MediaDemultiplexerNode::ComputeInternalLatency\n");
694 // if (GetCurrentFile() != 0) {
695 // bigtime_t start, end;
696 // uint8 * data = new uint8[output.format.u.multistream.max_chunk_size]; // <- buffer group buffer size
697 // BBuffer * buffer = 0;
698 // ssize_t bytesRead = 0;
699 // { // timed section
700 // start = TimeSource()->RealTime();
701 // // first we try to use a real BBuffer
702 // buffer = fBufferGroup->RequestBuffer(output.format.u.multistream.max_chunk_size,fBufferPeriod);
703 // if (buffer != 0) {
704 // FillFileBuffer(buffer);
706 // // didn't get a real BBuffer, try simulation by just a read from the disk
707 // bytesRead = GetCurrentFile()->Read(data,output.format.u.multistream.max_chunk_size);
709 // end = TimeSource()->RealTime();
711 // bytesRead = buffer->SizeUsed();
713 // if (buffer != 0) {
714 // buffer->Recycle();
716 // GetCurrentFile()->Seek(-bytesRead,SEEK_CUR); // put it back where we found it
718 // fInternalLatency = end - start;
720 // fprintf(stderr," internal latency from disk read = %lld\n",fInternalLatency);
722 fInternalLatency
= 100; // just guess
723 fprintf(stderr
," internal latency guessed = %lld\n",fInternalLatency
);
727 void MediaDemultiplexerNode::Disconnect(
728 const media_source
& what
,
729 const media_destination
& where
)
731 fprintf(stderr
,"MediaDemultiplexerNode::Disconnect\n");
732 // find the information for this output
733 vector
<MediaOutputInfo
>::iterator itr
;
734 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
735 if (itr
->output
.source
== what
) {
739 if (itr
== outputs
.end()) {
740 // we don't have that output
741 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
744 if (itr
->output
.destination
!= where
) {
745 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
748 // if this output has an equal (or higher!) latency than
749 // our current believed downstream latency, we may have to
750 // update our downstream latency.
751 bool updateDownstreamLatency
= (itr
->downstreamLatency
>= fDownstreamLatency
);
752 // disconnect this output
754 // update the downstream latency if necessary
755 if (updateDownstreamLatency
) {
756 bigtime_t newDownstreamLatency
= 0;
757 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
758 if (itr
->downstreamLatency
> newDownstreamLatency
) {
759 newDownstreamLatency
= itr
->downstreamLatency
;
762 fDownstreamLatency
= newDownstreamLatency
;
766 void MediaDemultiplexerNode::LateNoticeReceived(
767 const media_source
& what
,
769 bigtime_t performance_time
)
771 fprintf(stderr
,"MediaDemultiplexerNode::LateNoticeReceived\n");
772 vector
<MediaOutputInfo
>::iterator itr
;
773 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
774 if (itr
->output
.source
== what
) {
778 if (itr
== outputs
.end()) {
779 // we don't have that output
780 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
790 case B_INCREASE_LATENCY
:
791 fInternalLatency
+= how_much
;
792 SetEventLatency(fDownstreamLatency
+ fInternalLatency
);
794 case B_DECREASE_PRECISION
:
795 // XXX: try to catch up by producing buffers faster
798 // XXX: should we really drop buffers? just for that output?
801 // huh?? there aren't any more run modes.
802 fprintf(stderr
,"MediaDemultiplexerNode::LateNoticeReceived with unexpected run mode.\n");
807 void MediaDemultiplexerNode::EnableOutput(
808 const media_source
& what
,
810 int32
* _deprecated_
)
812 fprintf(stderr
,"MediaDemultiplexerNode::EnableOutput\n");
813 // find the information for this output
814 vector
<MediaOutputInfo
>::iterator itr
;
815 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
816 if (itr
->output
.source
== what
) {
820 if (itr
== outputs
.end()) {
821 // we don't have that output
822 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
825 status_t status
= itr
->EnableOutput(enabled
);
826 if (status
!= B_OK
) {
827 fprintf(stderr
," error in itr->EnableOutput\n");
833 status_t
MediaDemultiplexerNode::SetPlayRate(
837 BBufferProducer::SetPlayRate(numer
,denom
); // XXX: do something intelligent later
840 void MediaDemultiplexerNode::AdditionalBufferRequested( // used to be Reserved 0
841 const media_source
& source
,
842 media_buffer_id prev_buffer
,
844 const media_seek_tag
* prev_tag
)
846 fprintf(stderr
,"MediaDemultiplexerNode::AdditionalBufferRequested\n");
847 // find the information for this output
848 vector
<MediaOutputInfo
>::iterator itr
;
849 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
850 if (itr
->output
.source
== source
) {
854 if (itr
== outputs
.end()) {
855 // we don't have that output
856 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
860 status_t status
= itr
->AdditionalBufferRequested(prev_buffer
,prev_time
,prev_tag
);
861 if (status
!= B_OK
) {
862 fprintf(stderr
," itr->AdditionalBufferRequested returned an error.\n");
868 void MediaDemultiplexerNode::LatencyChanged(
869 const media_source
& source
,
870 const media_destination
& destination
,
871 bigtime_t new_latency
,
874 fprintf(stderr
,"MediaDemultiplexerNode::LatencyChanged\n");
875 // find the information for this output
876 vector
<MediaOutputInfo
>::iterator itr
;
877 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
878 if (itr
->output
.source
== source
) {
882 if (itr
== outputs
.end()) {
883 // we don't have that output
884 fprintf(stderr
,"<- B_MEDIA_BAD_SOURCE\n");
887 if (itr
->output
.destination
!= destination
) {
888 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
891 fDownstreamLatency
= new_latency
;
892 SetEventLatency(fDownstreamLatency
+ fInternalLatency
);
893 // XXX: we may have to recompute the number of buffers that we are using
894 // see SetBufferGroup
897 // -------------------------------------------------------- //
898 // implementation for BMediaEventLooper
899 // -------------------------------------------------------- //
901 void MediaDemultiplexerNode::HandleEvent(
902 const media_timed_event
*event
,
904 bool realTimeEvent
= false)
906 fprintf(stderr
,"MediaDemultiplexerNode::HandleEvent\n");
907 switch (event
->type
) {
908 case BTimedEventQueue::B_START
:
909 HandleStart(event
,lateness
,realTimeEvent
);
911 case BTimedEventQueue::B_SEEK
:
912 HandleSeek(event
,lateness
,realTimeEvent
);
914 case BTimedEventQueue::B_WARP
:
915 HandleWarp(event
,lateness
,realTimeEvent
);
917 case BTimedEventQueue::B_STOP
:
918 HandleStop(event
,lateness
,realTimeEvent
);
920 case BTimedEventQueue::B_HANDLE_BUFFER
:
921 if (RunState() == BMediaEventLooper::B_STARTED
) {
922 HandleBuffer(event
,lateness
,realTimeEvent
);
925 case BTimedEventQueue::B_DATA_STATUS
:
926 HandleDataStatus(event
,lateness
,realTimeEvent
);
928 case BTimedEventQueue::B_PARAMETER
:
929 HandleParameter(event
,lateness
,realTimeEvent
);
932 fprintf(stderr
," unknown event type: %i\n",event
->type
);
937 /* override to clean up custom events you have added to your queue */
938 void MediaDemultiplexerNode::CleanUpEvent(
939 const media_timed_event
*event
)
941 BMediaEventLooper::CleanUpEvent(event
);
944 /* called from Offline mode to determine the current time of the node */
945 /* update your internal information whenever it changes */
946 bigtime_t
MediaDemultiplexerNode::OfflineTime()
948 fprintf(stderr
,"MediaDemultiplexerNode::OfflineTime\n");
949 return BMediaEventLooper::OfflineTime();
950 // XXX: do something else?
953 /* override only if you know what you are doing! */
954 /* otherwise much badness could occur */
955 /* the actual control loop function: */
956 /* waits for messages, Pops events off the queue and calls DispatchEvent */
957 void MediaDemultiplexerNode::ControlLoop() {
958 BMediaEventLooper::ControlLoop();
963 status_t
MediaDemultiplexerNode::HandleStart(
964 const media_timed_event
*event
,
966 bool realTimeEvent
= false)
968 fprintf(stderr
,"MediaDemultiplexerNode::HandleStart()\n");
969 if (RunState() != B_STARTED
) {
970 // XXX: Either use the following line or the lines that are not commented.
971 // There doesn't seem to be a practical difference that i can tell.
972 // HandleBuffer(event,lateness,realTimeEvent);
973 media_timed_event
firstBufferEvent(event
->event_time
, BTimedEventQueue::B_HANDLE_BUFFER
);
974 HandleEvent(&firstBufferEvent
, 0, false);
975 EventQueue()->AddEvent(firstBufferEvent
);
980 status_t
MediaDemultiplexerNode::HandleSeek(
981 const media_timed_event
*event
,
983 bool realTimeEvent
= false)
985 fprintf(stderr
,"MediaDemultiplexerNode::HandleSeek(t=%lld,d=%i,bd=%lld)\n",event
->event_time
,event
->data
,event
->bigdata
);
989 status_t
MediaDemultiplexerNode::HandleWarp(
990 const media_timed_event
*event
,
992 bool realTimeEvent
= false)
994 fprintf(stderr
,"MediaDemultiplexerNode::HandleWarp\n");
998 status_t
MediaDemultiplexerNode::HandleStop(
999 const media_timed_event
*event
,
1001 bool realTimeEvent
= false)
1003 fprintf(stderr
,"MediaDemultiplexerNode::HandleStop\n");
1004 // flush the queue so downstreamers don't get any more
1005 EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS
, true, BTimedEventQueue::B_HANDLE_BUFFER
);
1009 status_t
MediaDemultiplexerNode::HandleBuffer(
1010 const media_timed_event
*event
,
1012 bool realTimeEvent
= false)
1014 fprintf(stderr
,"MediaDemultiplexerNode::HandleBuffer\n");
1015 BBuffer
* buffer
= const_cast<BBuffer
*>((BBuffer
*)event
->pointer
);
1017 fprintf(stderr
,"<- B_BAD_VALUE\n");
1020 if (buffer
->Header()->destination
!= input
.destination
.id
) {
1021 fprintf(stderr
,"<- B_MEDIA_BAD_DESTINATION\n");
1022 return B_MEDIA_BAD_DESTINATION
;
1024 if (outputs
.begin() == outputs
.end()) {
1025 fprintf(stderr
,"<- B_MEDIA_NOT_CONNECTED\n");
1026 return B_MEDIA_NOT_CONNECTED
;
1028 status_t status
= B_OK
;
1029 fprintf(stderr
," XXX: HandleBuffer not yet implemented.\n");
1030 // we have to hand the buffer to the extractor
1031 // and then whenever we get a buffer for an output send it
1032 // to that particular output (assuming it exists and is enabled)
1033 // BBuffer * buffer = fBufferGroup->RequestBuffer(output.format.u.multistream.max_chunk_size,fBufferPeriod);
1034 // if (buffer != 0) {
1035 // status = FillFileBuffer(buffer);
1036 // if (status != B_OK) {
1037 // fprintf(stderr,"MediaDemultiplexerNode::HandleEvent got an error from FillFileBuffer.\n");
1038 // buffer->Recycle();
1040 // if (fOutputEnabled) {
1041 // status = SendBuffer(buffer,output.destination);
1042 // if (status != B_OK) {
1043 // fprintf(stderr,"MediaDemultiplexerNode::HandleEvent got an error from SendBuffer.\n");
1044 // buffer->Recycle();
1051 bigtime_t nextEventTime
= event
->event_time
+10000; // fBufferPeriod; // XXX : should multiply
1052 media_timed_event
nextBufferEvent(nextEventTime
, BTimedEventQueue::B_HANDLE_BUFFER
);
1053 EventQueue()->AddEvent(nextBufferEvent
);
1057 status_t
MediaDemultiplexerNode::HandleDataStatus(
1058 const media_timed_event
*event
,
1060 bool realTimeEvent
= false)
1062 fprintf(stderr
,"MediaDemultiplexerNode::HandleDataStatus");
1063 // find the information for this output
1064 vector
<MediaOutputInfo
>::iterator itr
;
1065 for(itr
= outputs
.begin() ; (itr
!= outputs
.end()) ; itr
++) {
1066 SendDataStatus(event
->data
,itr
->output
.destination
,event
->event_time
);
1071 status_t
MediaDemultiplexerNode::HandleParameter(
1072 const media_timed_event
*event
,
1074 bool realTimeEvent
= false)
1076 fprintf(stderr
,"MediaDemultiplexerNode::HandleParameter");
1080 // -------------------------------------------------------- //
1081 // MediaDemultiplexerNode specific functions
1082 // -------------------------------------------------------- //
1086 void MediaDemultiplexerNode::GetFlavor(flavor_info
* outInfo
, int32 id
)
1088 fprintf(stderr
,"MediaDemultiplexerNode::GetFlavor\n");
1092 outInfo
->name
= "OpenBeOS Demultiplexer";
1093 outInfo
->info
= "A MediaDemultiplexerNode node demultiplexes a multistream into its constituent streams.";
1094 outInfo
->kinds
= B_BUFFER_CONSUMER
| B_BUFFER_PRODUCER
;
1095 outInfo
->flavor_flags
= B_FLAVOR_IS_LOCAL
;
1096 outInfo
->possible_count
= INT_MAX
;
1097 outInfo
->in_format_count
= 1; // 1 input
1098 media_format
* inFormats
= new media_format
[outInfo
->in_format_count
];
1099 GetInputFormat(&inFormats
[0]);
1100 outInfo
->in_formats
= inFormats
;
1101 outInfo
->out_format_count
= 1; // 1 output
1102 media_format
* outFormats
= new media_format
[outInfo
->out_format_count
];
1103 GetOutputFormat(&outFormats
[0]);
1104 outInfo
->out_formats
= outFormats
;
1105 outInfo
->internal_id
= id
;
1109 void MediaDemultiplexerNode::GetInputFormat(media_format
* outFormat
)
1111 fprintf(stderr
,"MediaDemultiplexerNode::GetInputFormat\n");
1112 if (outFormat
== 0) {
1115 outFormat
->type
= B_MEDIA_MULTISTREAM
;
1116 outFormat
->require_flags
= B_MEDIA_MAUI_UNDEFINED_FLAGS
;
1117 outFormat
->deny_flags
= B_MEDIA_MAUI_UNDEFINED_FLAGS
;
1118 outFormat
->u
.multistream
= media_multistream_format::wildcard
;
1121 void MediaDemultiplexerNode::GetOutputFormat(media_format
* outFormat
)
1123 fprintf(stderr
,"MediaDemultiplexerNode::GetOutputFormat\n");
1124 if (outFormat
== 0) {
1127 outFormat
->type
= B_MEDIA_UNKNOWN_TYPE
; // more like ANY_TYPE than unknown
1128 outFormat
->require_flags
= B_MEDIA_MAUI_UNDEFINED_FLAGS
;
1129 outFormat
->deny_flags
= B_MEDIA_MAUI_UNDEFINED_FLAGS
;
1134 status_t
MediaDemultiplexerNode::AddRequirements(media_format
* format
)
1136 fprintf(stderr
,"MediaDemultiplexerNode::AddRequirements\n");
1140 // -------------------------------------------------------- //
1142 // -------------------------------------------------------- //
1144 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_0(void *) {}
1145 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_1(void *) {}
1146 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_2(void *) {}
1147 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_3(void *) {}
1148 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_4(void *) {}
1149 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_5(void *) {}
1150 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_6(void *) {}
1151 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_7(void *) {}
1152 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_8(void *) {}
1153 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_9(void *) {}
1154 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_10(void *) {}
1155 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_11(void *) {}
1156 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_12(void *) {}
1157 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_13(void *) {}
1158 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_14(void *) {}
1159 status_t
MediaDemultiplexerNode::_Reserved_MediaDemultiplexerNode_15(void *) {}