BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / add-ons / media / media-add-ons / dvb / DVBMediaNode.cpp
blob1da2a4cccfdeed7fc13de1a5cfa2d460d5c0bf59
1 /*
2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
26 #include <fcntl.h>
27 #include <malloc.h>
28 #include <math.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/uio.h>
33 #include <unistd.h>
35 #include <MediaRoster.h>
36 #include <Buffer.h>
37 #include <BufferGroup.h>
38 #include <ParameterWeb.h>
39 #include <TimeSource.h>
40 #include <String.h>
41 #include <Autolock.h>
42 #include <Debug.h>
44 #include <Directory.h>
45 #include <Entry.h>
46 #include <Path.h>
48 #include "MediaFormat.h"
49 #include "Packet.h"
50 #include "PacketQueue.h"
51 #include "pes.h"
52 #include "config.h"
54 //#define DUMP_VIDEO
55 //#define DUMP_AUDIO
56 //#define DUMP_RAW_AUDIO
57 //#define DUMP_MPEG_TS
60 #include "DVBMediaNode.h"
62 #define ENABLE_TRACE
63 //#define ENABLE_TRACE_TIMING
65 #undef TRACE
67 #ifdef ENABLE_TRACE
68 #define TRACE printf
69 #else
70 #define TRACE(a...)
71 #endif
73 #ifdef ENABLE_TRACE_TIMING
74 #define TRACE_TIMING printf
75 #else
76 #define TRACE_TIMING(a...)
77 #endif
79 #define RETURN_IF_ERROR(expr) { status_t e = (expr); if (e != B_OK) return e; }
81 #define ID_RAW_VIDEO 0
82 #define ID_RAW_AUDIO 1
83 #define ID_ENC_VIDEO 2
84 #define ID_ENC_AUDIO 3
85 #define ID_TS 4
87 // Timeouts for requesting buffers, if the system is busy,
88 // the output buffer queue is full, requesting a buffer will
89 // timeout, and we need to drop the current data
90 #define VIDEO_BUFFER_REQUEST_TIMEOUT 20000
91 #define AUDIO_BUFFER_REQUEST_TIMEOUT 10000
93 // DVB data arrives early and with a timestamp, this is used to validate
94 // that the timestamp is correct and we don't get stuck
95 #define VIDEO_MAX_EARLY 3000000
96 // up to 3 seconds too early
97 #define VIDEO_MAX_LATE 50000
98 // no more than 50 ms too late
99 #define AUDIO_MAX_EARLY 3000000
100 // up to 3 seconds too early
101 #define AUDIO_MAX_LATE 50000
102 // no more than 50 ms too late
104 #define PROCESSING_LATENCY 1500
105 // assumed latency for sending the buffer
107 #define STOP_CAPTURE_WHILE_TUNING 1
109 #define M_REFRESH_PARAMETER_WEB (BTimedEventQueue::B_USER_EVENT + 1)
112 DVBMediaNode::DVBMediaNode(
113 BMediaAddOn *addon, const char *name,
114 int32 internal_id, DVBCard *card)
115 : BMediaNode(name)
116 , BBufferProducer(B_MEDIA_RAW_VIDEO)
117 , BControllable()
118 , BMediaEventLooper()
119 , fStopDisabled(false)
120 , fOutputEnabledRawVideo(false)
121 , fOutputEnabledRawAudio(false)
122 , fOutputEnabledEncVideo(false)
123 , fOutputEnabledEncAudio(false)
124 , fOutputEnabledTS(false)
125 , fCardDataQueue(new PacketQueue(6))
126 , fRawVideoQueue(new PacketQueue(56))
127 , fRawAudioQueue(new PacketQueue(56))
128 , fEncVideoQueue(new PacketQueue(56))
129 , fEncAudioQueue(new PacketQueue(56))
130 , fMpegTsQueue(new PacketQueue(16))
131 , fCard(card)
132 , fCaptureThreadsActive(false)
133 , fThreadIdCardReader(-1)
134 , fThreadIdMpegDemux(-1)
135 , fThreadIdRawAudio(-1)
136 , fThreadIdRawVideo(-1)
137 , fThreadIdEncAudio(-1)
138 , fThreadIdEncVideo(-1)
139 , fThreadIdMpegTS(-1)
140 , fTerminateThreads(false)
141 , fDemux(new TransportStreamDemux(fRawVideoQueue, fRawAudioQueue,
142 fEncVideoQueue, fEncAudioQueue, fMpegTsQueue))
143 , fBufferGroupRawVideo(0)
144 , fBufferGroupRawAudio(0)
145 , fInterfaceType(DVB_TYPE_UNKNOWN)
146 , fAudioPid(-1)
147 , fVideoPid(-1)
148 , fPcrPid(-1)
149 , fTuningSuccess(false)
150 , fCaptureActive(false)
151 , fVideoDelaySem(create_sem(0, "video delay sem"))
152 , fAudioDelaySem(create_sem(0, "audio delay sem"))
153 , fSelectedState(-1)
154 , fSelectedRegion(-1)
155 , fSelectedChannel(-1)
156 , fSelectedAudio(-1)
157 , fStateList(new StringList)
158 , fRegionList(new StringList)
159 , fChannelList(new StringList)
160 , fAudioList(new StringList)
161 , fVideoDecoder(0)
162 , fAudioDecoder(0)
163 , fCurrentVideoPacket(0)
164 , fCurrentAudioPacket(0)
166 TRACE("DVBMediaNode::DVBMediaNode\n");
168 AddNodeKind(B_PHYSICAL_INPUT);
170 fInternalID = internal_id;
171 fAddOn = addon;
173 fInitStatus = B_OK;
175 InitDefaultFormats();
177 // in the beginning, the required formats are the same as the defaults
178 fRequiredFormatRawVideo = fDefaultFormatRawVideo;
179 fRequiredFormatRawAudio = fDefaultFormatRawAudio;
180 fRequiredFormatEncVideo = fDefaultFormatEncVideo;
181 fRequiredFormatEncAudio = fDefaultFormatEncAudio;
182 fRequiredFormatTS = fDefaultFormatTS;
184 TRACE("current RunMode = %d\n", RunMode());
186 #ifdef DUMP_VIDEO
187 fVideoFile = open("/boot/home/dvb-video.mpg", O_RDWR | O_CREAT | O_TRUNC);
188 #endif
189 #ifdef DUMP_AUDIO
190 fAudioFile = open("/boot/home/dvb-audio.mpg", O_RDWR | O_CREAT | O_TRUNC);
191 #endif
192 #ifdef DUMP_RAW_AUDIO
193 fRawAudioFile = open("/boot/home/dvb-audio.raw",
194 O_RDWR | O_CREAT | O_TRUNC);
195 #endif
196 #ifdef DUMP_MPEG_TS
197 fMpegTsFile = open("/boot/home/dvb-mpeg.ts", O_RDWR | O_CREAT | O_TRUNC);
198 #endif
202 DVBMediaNode::~DVBMediaNode()
204 TRACE("DVBMediaNode::~DVBMediaNode\n");
206 StopCapture();
208 delete_sem(fVideoDelaySem);
209 delete_sem(fAudioDelaySem);
211 // fCard is owned by the media addon
212 delete fCardDataQueue;
213 delete fRawVideoQueue;
214 delete fRawAudioQueue;
215 delete fEncVideoQueue;
216 delete fEncAudioQueue;
217 delete fMpegTsQueue;
219 delete fDemux;
221 delete fBufferGroupRawVideo;
222 delete fBufferGroupRawAudio;
224 delete fStateList;
225 delete fRegionList;
226 delete fChannelList;
227 delete fAudioList;
229 #ifdef DUMP_VIDEO
230 close(fVideoFile);
231 #endif
232 #ifdef DUMP_AUDIO
233 close(fAudioFile);
234 #endif
235 #ifdef DUMP_RAW_AUDIO
236 close(fRawAudioFile);
237 #endif
238 #ifdef DUMP_MPEG_TS
239 close(fMpegTsFile);
240 #endif
245 /* BMediaNode */
248 BMediaAddOn *
249 DVBMediaNode::AddOn(int32 *internal_id) const
251 if (internal_id)
252 *internal_id = fInternalID;
253 return fAddOn;
257 status_t
258 DVBMediaNode::HandleMessage(int32 message, const void *data, size_t size)
260 return B_ERROR;
264 void
265 DVBMediaNode::Preroll()
267 /* This hook may be called before the node is started to give the hardware
268 * a chance to start. */
272 void
273 DVBMediaNode::SetTimeSource(BTimeSource *time_source)
275 TRACE("DVBMediaNode::SetTimeSource\n");
276 //printf("current RunMode = %d\n", RunMode());
277 //printf("_m_recordDelay = %Ld\n", _m_recordDelay);
281 void
282 DVBMediaNode::SetRunMode(run_mode mode)
284 TRACE("DVBMediaNode::SetRunMode: %d\n", mode);
285 TRACE("current RunMode = %d\n", RunMode());
286 //printf("_m_recordDelay = %Ld\n", _m_recordDelay);
290 /* BMediaEventLooper */
293 void
294 DVBMediaNode::NodeRegistered()
296 TRACE("DVBMediaNode::NodeRegistered\n");
298 fOutputRawVideo.node = Node();
299 fOutputRawVideo.source.port = ControlPort();
300 fOutputRawVideo.source.id = ID_RAW_VIDEO;
301 fOutputRawVideo.destination = media_destination::null;
302 fOutputRawVideo.format = fDefaultFormatRawVideo;
303 strcpy(fOutputRawVideo.name, SourceDefaultName(fOutputRawVideo.source));
305 fOutputRawAudio.node = Node();
306 fOutputRawAudio.source.port = ControlPort();
307 fOutputRawAudio.source.id = ID_RAW_AUDIO;
308 fOutputRawAudio.destination = media_destination::null;
309 fOutputRawAudio.format = fDefaultFormatRawAudio;
310 strcpy(fOutputRawAudio.name, SourceDefaultName(fOutputRawAudio.source));
312 fOutputEncVideo.node = Node();
313 fOutputEncVideo.source.port = ControlPort();
314 fOutputEncVideo.source.id = ID_ENC_VIDEO;
315 fOutputEncVideo.destination = media_destination::null;
316 fOutputEncVideo.format = fDefaultFormatEncVideo;
317 strcpy(fOutputEncVideo.name, SourceDefaultName(fOutputEncVideo.source));
319 fOutputEncAudio.node = Node();
320 fOutputEncAudio.source.port = ControlPort();
321 fOutputEncAudio.source.id = ID_ENC_AUDIO;
322 fOutputEncAudio.destination = media_destination::null;
323 fOutputEncAudio.format = fDefaultFormatEncAudio;
324 strcpy(fOutputEncAudio.name, SourceDefaultName(fOutputEncAudio.source));
326 fOutputTS.node = Node();
327 fOutputTS.source.port = ControlPort();
328 fOutputTS.source.id = ID_TS;
329 fOutputTS.destination = media_destination::null;
330 fOutputTS.format = fDefaultFormatTS;
331 strcpy(fOutputTS.name, SourceDefaultName(fOutputTS.source));
333 fCard->GetCardType(&fInterfaceType);
335 // set control thread priority
336 SetPriority(110);
338 LoadSettings();
340 RefreshParameterWeb();
342 // this nodes operates in recording mode, so set it (will be done
343 // asynchronously)
344 BMediaRoster::Roster()->SetRunModeNode(Node(), B_RECORDING);
345 // as it's a notification hook, calling this doesn't work:
346 // SetRunMode(B_RECORDING);
348 //printf("RunMode = %d\n", RunMode());
349 //printf("_m_recordDelay = %Ld\n", _m_recordDelay);
351 Run();
355 void
356 DVBMediaNode::Stop(bigtime_t performance_time, bool immediate)
358 if (fStopDisabled)
359 return;
360 else
361 BMediaEventLooper::Stop(performance_time, immediate);
365 void
366 DVBMediaNode::HandleEvent(const media_timed_event *event,
367 bigtime_t lateness, bool realTimeEvent)
370 switch(event->type)
372 case M_REFRESH_PARAMETER_WEB:
373 RefreshParameterWeb();
374 break;
375 case BTimedEventQueue::B_START:
376 HandleStart(event->event_time);
377 break;
378 case BTimedEventQueue::B_STOP:
379 HandleStop();
380 break;
381 case BTimedEventQueue::B_WARP:
382 HandleTimeWarp(event->bigdata);
383 break;
384 case BTimedEventQueue::B_SEEK:
385 HandleSeek(event->bigdata);
386 break;
387 case BTimedEventQueue::B_HANDLE_BUFFER:
388 case BTimedEventQueue::B_DATA_STATUS:
389 case BTimedEventQueue::B_PARAMETER:
390 default:
391 TRACE("DVBMediaNode::HandleEvent: Unhandled event -- %lx\n",
392 event->type);
393 break;
398 /* BBufferProducer */
401 status_t
402 DVBMediaNode::FormatChangeRequested(const media_source &source,
403 const media_destination &destination, media_format *io_format,
404 int32 *_deprecated_)
406 TRACE("DVBMediaNode::FormatChangeRequested denied: %s\n",
407 SourceDefaultName(source));
408 return B_ERROR;
412 status_t
413 DVBMediaNode::GetNextOutput(int32 *cookie, media_output *out_output)
415 switch (*cookie) {
416 case 0: *out_output = fOutputRawVideo; break;
417 case 1: *out_output = fOutputRawAudio; break;
418 case 2: *out_output = fOutputEncVideo; break;
419 case 3: *out_output = fOutputEncAudio; break;
420 case 4: *out_output = fOutputTS; break;
421 default: return B_BAD_INDEX;
424 (*cookie) += 1;
425 return B_OK;
429 status_t
430 DVBMediaNode::DisposeOutputCookie(int32 cookie)
432 return B_OK;
436 status_t
437 DVBMediaNode::SetBufferGroup(const media_source &source, BBufferGroup *group)
439 TRACE("DVBMediaNode::SetBufferGroup denied: %s\n",
440 SourceDefaultName(source));
441 return B_ERROR;
445 status_t
446 DVBMediaNode::VideoClippingChanged(const media_source &for_source,
447 int16 num_shorts, int16 *clip_data,
448 const media_video_display_info &display, int32 *_deprecated_)
450 return B_ERROR;
454 status_t
455 DVBMediaNode::GetLatency(bigtime_t *out_latency)
457 if (B_OK != BBufferProducer::GetLatency(out_latency))
458 *out_latency = 50000;
460 printf("DVBMediaNode::GetLatency: %Ld\n", *out_latency);
461 *out_latency += PROCESSING_LATENCY;
462 return B_OK;
466 status_t
467 DVBMediaNode::FormatSuggestionRequested(
468 media_type type, int32 quality, media_format *format)
470 TRACE("DVBMediaNode::FormatSuggestionRequested\n");
472 switch (type) {
473 case B_MEDIA_RAW_VIDEO:
474 *format = fDefaultFormatRawVideo;
475 break;
477 case B_MEDIA_RAW_AUDIO:
478 *format = fDefaultFormatRawAudio;
479 break;
481 case B_MEDIA_ENCODED_VIDEO:
482 *format = fDefaultFormatEncVideo;
483 break;
485 case B_MEDIA_ENCODED_AUDIO:
486 *format = fDefaultFormatEncAudio;
487 break;
489 case B_MEDIA_MULTISTREAM:
490 *format = fDefaultFormatTS;
491 break;
493 default:
494 TRACE("Bad type!\n");
495 return B_MEDIA_BAD_FORMAT;
498 #ifdef DEBUG
499 TRACE("suggested format: ");
500 PrintFormat(*format);
501 #endif
503 return B_OK;
507 status_t
508 DVBMediaNode::FormatProposal(const media_source &source, media_format *format)
510 TRACE("DVBMediaNode::FormatProposal: %s\n", SourceDefaultName(source));
512 /* The connection process:
513 * we are here => BBufferProducer::FormatProposal
514 * BBufferConsumer::AcceptFormat
515 * BBufferProducer::PrepareToConnect
516 * BBufferConsumer::Connected
517 * BBufferProducer::Connect
519 * What we need to do:
520 * - if the format contains a wildcard AND we have a requirement for that
521 * field, set it to the value we need.
522 * - if a field has a value that is not wildcard and not supported by us,
523 * we don't change it, and return B_MEDIA_BAD_FORMAT
524 * - after we are done, the format may still contain wildcards.
527 if (source.port != ControlPort())
528 goto _bad_source;
530 #ifdef DEBUG
531 TRACE("proposed format: ");
532 PrintFormat(*format);
533 TRACE("required format: ");
534 switch (source.id) {
535 case ID_RAW_VIDEO:
536 PrintFormat(fRequiredFormatRawVideo);
537 break;
539 case ID_RAW_AUDIO:
540 PrintFormat(fRequiredFormatRawAudio);
541 break;
543 case ID_ENC_VIDEO:
544 PrintFormat(fRequiredFormatEncVideo);
545 break;
547 case ID_ENC_AUDIO:
548 PrintFormat(fRequiredFormatEncAudio);
549 break;
551 case ID_TS:
552 PrintFormat(fRequiredFormatTS);
553 break;
555 #endif
557 switch (source.id) {
558 case ID_RAW_VIDEO:
559 // check if destination still available
560 if (fOutputRawVideo.destination != media_destination::null)
561 goto _bad_source;
562 // set requirements and check if compatible
563 color_space c;
564 c = format->u.raw_video.display.format;
565 format->SpecializeTo(&fRequiredFormatRawVideo);
566 format->u.raw_video.display.format = c;
567 // if (!format->Matches(&fRequiredFormatRawVideo))
568 // goto _bad_format_1;
569 if (!VerifyFormatRawVideo(format->u.raw_video))
570 goto _bad_format_2;
571 break;
573 case ID_RAW_AUDIO:
574 // check if destination still available
575 if (fOutputRawAudio.destination != media_destination::null)
576 goto _bad_source;
577 // set requirements and check if compatible
578 format->SpecializeTo(&fRequiredFormatRawAudio);
579 if (!format->Matches(&fRequiredFormatRawAudio))
580 goto _bad_format_1;
581 if (!VerifyFormatRawAudio(format->u.raw_audio))
582 goto _bad_format_2;
583 break;
585 case ID_ENC_VIDEO:
586 // check if destination still available
587 if (fOutputEncVideo.destination != media_destination::null)
588 goto _bad_source;
589 // set requirements and check if compatible
590 format->SpecializeTo(&fRequiredFormatEncVideo);
591 if (!format->Matches(&fRequiredFormatEncVideo))
592 goto _bad_format_1;
593 break;
595 case ID_ENC_AUDIO:
596 // check if destination still available
597 if (fOutputEncAudio.destination != media_destination::null)
598 goto _bad_source;
599 // set requirements and check if compatible
600 format->SpecializeTo(&fRequiredFormatEncAudio);
601 if (!format->Matches(&fRequiredFormatEncAudio))
602 goto _bad_format_1;
603 break;
605 case ID_TS:
606 // check if destination still available
607 if (fOutputTS.destination != media_destination::null)
608 goto _bad_source;
609 // set requirements and check if compatible
610 format->SpecializeTo(&fRequiredFormatTS);
611 if (!format->Matches(&fRequiredFormatTS))
612 goto _bad_format_1;
613 break;
615 default:
616 goto _bad_source;
619 #ifdef DEBUG
620 TRACE("final format: ");
621 PrintFormat(*format);
622 #endif
624 return B_OK;
626 _bad_source:
627 TRACE("Error: bad source!\n");
628 return B_MEDIA_BAD_SOURCE;
630 _bad_format_1:
631 TRACE("Error, bad format (1): ");
632 goto _bad_format;
634 _bad_format_2:
635 TRACE("Error, bad format (2): ");
636 goto _bad_format;
638 _bad_format:
639 #ifdef DEBUG
640 PrintFormat(*format);
641 #endif
642 return B_MEDIA_BAD_FORMAT;
646 status_t
647 DVBMediaNode::PrepareToConnect(const media_source &source,
648 const media_destination &destination, media_format *format,
649 media_source *out_source, char *out_name)
651 /* The connection process:
652 * BBufferProducer::FormatProposal
653 * BBufferConsumer::AcceptFormat
654 * we are here => BBufferProducer::PrepareToConnect
655 * BBufferConsumer::Connected
656 * BBufferProducer::Connect
658 * At this point, the consumer's AcceptFormat() method has been called,
659 * and that node has potentially changed the proposed format. It may
660 * also have left wildcards in the format. PrepareToConnect()
661 * *must* fully specialize the format before returning!
664 TRACE("DVBMediaNode::PrepareToConnect: %s\n", SourceDefaultName(source));
666 #ifdef DEBUG
667 TRACE("connecting format: ");
668 PrintFormat(*format);
669 TRACE("required format: ");
670 switch (source.id) {
671 case ID_RAW_VIDEO:
672 PrintFormat(fRequiredFormatRawVideo);
673 break;
675 case ID_RAW_AUDIO:
676 PrintFormat(fRequiredFormatRawAudio);
677 break;
679 case ID_ENC_VIDEO:
680 PrintFormat(fRequiredFormatEncVideo);
681 break;
683 case ID_ENC_AUDIO:
684 PrintFormat(fRequiredFormatEncAudio);
685 break;
687 case ID_TS:
688 PrintFormat(fRequiredFormatTS);
689 break;
691 #endif
693 // is the source valid?
694 if (source.port != ControlPort())
695 goto _bad_source;
697 // 1) check if the output is still available,
698 // 2) specialize and verify the format
699 switch (source.id) {
700 case ID_RAW_VIDEO:
701 if (fOutputRawVideo.destination != media_destination::null)
702 goto _already_connected;
703 SpecializeFormatRawVideo(&format->u.raw_video);
704 // if (!format->Matches(&fRequiredFormatRawVideo))
705 // goto _bad_format;
706 if (!VerifyFormatRawVideo(format->u.raw_video))
707 goto _bad_format;
708 break;
710 case ID_RAW_AUDIO:
711 if (fOutputRawAudio.destination != media_destination::null)
712 goto _already_connected;
713 SpecializeFormatRawAudio(&format->u.raw_audio);
714 if (!format->Matches(&fRequiredFormatRawAudio))
715 goto _bad_format;
716 if (!VerifyFormatRawAudio(format->u.raw_audio))
717 goto _bad_format;
718 break;
720 case ID_ENC_VIDEO:
721 if (fOutputEncVideo.destination != media_destination::null)
722 goto _already_connected;
723 SpecializeFormatEncVideo(&format->u.encoded_video);
724 if (!format->Matches(&fRequiredFormatEncVideo))
725 goto _bad_format;
726 break;
728 case ID_ENC_AUDIO:
729 if (fOutputEncAudio.destination != media_destination::null)
730 goto _already_connected;
731 SpecializeFormatEncAudio(&format->u.encoded_audio);
732 if (!format->Matches(&fRequiredFormatRawVideo))
733 goto _bad_format;
734 break;
736 case ID_TS:
737 if (fOutputTS.destination != media_destination::null)
738 goto _already_connected;
739 SpecializeFormatTS(&format->u.multistream);
740 if (!format->Matches(&fRequiredFormatTS))
741 goto _bad_format;
742 break;
744 default:
745 goto _bad_source;
748 #ifdef DEBUG
749 TRACE("final format: ");
750 PrintFormat(*format);
751 #endif
753 // reserve the connection by setting destination
754 // set the output's format to the new format
755 SetOutput(source, destination, *format);
757 // set source and suggest a name
758 *out_source = source;
759 strcpy(out_name, SourceDefaultName(source));
761 return B_OK;
763 _bad_source:
764 TRACE("Error: bad source!\n");
765 return B_MEDIA_BAD_SOURCE;
767 _bad_format:
768 #ifdef DEBUG
769 TRACE("Error, bad format: ");
770 PrintFormat(*format);
771 #endif
772 return B_MEDIA_BAD_FORMAT;
774 _already_connected:
775 TRACE("Error: already connected!\n");
776 return B_MEDIA_ALREADY_CONNECTED;
780 void
781 DVBMediaNode::Connect(status_t error, const media_source &source,
782 const media_destination &destination, const media_format &format,
783 char *io_name)
785 /* The connection process:
786 * BBufferProducer::FormatProposal
787 * BBufferConsumer::AcceptFormat
788 * BBufferProducer::PrepareToConnect
789 * BBufferConsumer::Connected
790 * we are here => BBufferProducer::Connect
793 TRACE("DVBMediaNode::Connect: %s\n", SourceDefaultName(source));
795 if (error != B_OK) {
796 TRACE("Error during connecting\n");
797 // if an error occured, unreserve the connection
798 ResetOutput(source);
799 return;
802 #ifdef DEBUG
803 TRACE("connected format: ");
804 PrintFormat(format);
805 #endif
807 // Since the destination is allowed to be changed by the
808 // consumer, the one we got in PrepareToConnect() is no
809 // longer correct, and must be updated here.
810 SetOutput(source, destination, format);
812 // Set output as connected
813 switch (source.id) {
814 case ID_RAW_VIDEO:
815 fOutputEnabledRawVideo = true;
816 break;
818 case ID_RAW_AUDIO:
819 fOutputEnabledRawAudio = true;
820 break;
822 case ID_ENC_VIDEO:
823 fOutputEnabledEncVideo = true;
824 break;
826 case ID_ENC_AUDIO:
827 fOutputEnabledEncAudio = true;
828 break;
830 case ID_TS:
831 fOutputEnabledTS = true;
832 break;
834 default:
835 break;
838 // if the connection has no name, we set it now
839 if (strlen(io_name) == 0)
840 strcpy(io_name, SourceDefaultName(source));
842 #ifdef DEBUG
843 bigtime_t latency;
844 media_node_id ts;
845 if (B_OK != FindLatencyFor(destination, &latency, &ts))
846 TRACE("FindLatencyFor failed\n");
847 else
848 TRACE("downstream latency %Ld\n", latency);
849 #endif
853 void
854 DVBMediaNode::Disconnect(const media_source &source,
855 const media_destination &destination)
857 TRACE("DVBMediaNode::Disconnect: %s\n", SourceDefaultName(source));
859 // unreserve the connection
860 ResetOutput(source);
862 // Set output to disconnected
863 switch (source.id) {
864 case ID_RAW_VIDEO:
865 fOutputEnabledRawVideo = false;
866 break;
868 case ID_RAW_AUDIO:
869 fOutputEnabledRawAudio = false;
870 break;
872 case ID_ENC_VIDEO:
873 fOutputEnabledEncVideo = false;
874 break;
876 case ID_ENC_AUDIO:
877 fOutputEnabledEncAudio = false;
878 break;
880 case ID_TS:
881 fOutputEnabledTS = false;
882 break;
884 default:
885 break;
890 void
891 DVBMediaNode::LateNoticeReceived(const media_source &source,
892 bigtime_t how_much, bigtime_t performance_time)
894 TRACE("DVBMediaNode::LateNoticeReceived %Ld late at %Ld\n", how_much,
895 performance_time);
899 void
900 DVBMediaNode::EnableOutput(const media_source &source, bool enabled,
901 int32 *_deprecated_)
903 TRACE("DVBMediaNode::EnableOutput id = %ld, enabled = %d\n", source.id,
904 enabled);
905 /* not used yet
906 switch (source.id) {
907 case ID_RAW_VIDEO: fOutputEnabledRawVideo = enabled; break;
908 case ID_RAW_AUDIO: fOutputEnabledRawAudio = enabled; break;
909 case ID_ENC_VIDEO: fOutputEnabledEncVideo = enabled; break;
910 case ID_ENC_AUDIO: fOutputEnabledEncAudio = enabled; break;
911 case ID_TS: fOutputEnabledTS = enabled; break;
912 default: break;
918 status_t
919 DVBMediaNode::SetPlayRate(int32 numer, int32 denom)
922 return B_ERROR;
926 void
927 DVBMediaNode::AdditionalBufferRequested(const media_source &source,
928 media_buffer_id prev_buffer, bigtime_t prev_time,
929 const media_seek_tag *prev_tag)
931 TRACE("DVBMediaNode::AdditionalBufferRequested: %s\n",
932 SourceDefaultName(source));
936 void
937 DVBMediaNode::LatencyChanged(const media_source &source,
938 const media_destination &destination, bigtime_t new_latency,
939 uint32 flags)
941 TRACE("DVBMediaNode::LatencyChanged to %Ld\n", new_latency);
944 /* DVBMediaNode */
947 void
948 DVBMediaNode::HandleTimeWarp(bigtime_t performance_time)
950 TRACE("DVBMediaNode::HandleTimeWarp at %Ld\n", performance_time);
954 void
955 DVBMediaNode::HandleSeek(bigtime_t performance_time)
957 TRACE("DVBMediaNode::HandleSeek at %Ld\n", performance_time);
961 void
962 DVBMediaNode::InitDefaultFormats()
964 // 720 * 576
965 fDefaultFormatRawVideo.type = B_MEDIA_RAW_VIDEO;
966 fDefaultFormatRawVideo.u.raw_video.display.format = B_RGB32;
967 fDefaultFormatRawVideo.u.raw_video.display.line_width = 720;
968 fDefaultFormatRawVideo.u.raw_video.display.line_count = 576;
969 fDefaultFormatRawVideo.u.raw_video.last_active
970 = fDefaultFormatRawVideo.u.raw_video.display.line_count - 1;
971 fDefaultFormatRawVideo.u.raw_video.display.bytes_per_row
972 = fDefaultFormatRawVideo.u.raw_video.display.line_width * 4;
973 fDefaultFormatRawVideo.u.raw_video.field_rate = 0;
974 // wildcard
975 fDefaultFormatRawVideo.u.raw_video.interlace = 1;
976 fDefaultFormatRawVideo.u.raw_video.first_active = 0;
977 fDefaultFormatRawVideo.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT;
978 fDefaultFormatRawVideo.u.raw_video.pixel_width_aspect = 1;
979 fDefaultFormatRawVideo.u.raw_video.pixel_height_aspect = 1;
980 fDefaultFormatRawVideo.u.raw_video.display.pixel_offset = 0;
981 fDefaultFormatRawVideo.u.raw_video.display.line_offset = 0;
982 fDefaultFormatRawVideo.u.raw_video.display.flags = 0;
984 fDefaultFormatRawAudio.type = B_MEDIA_RAW_AUDIO;
985 fDefaultFormatRawAudio.u.raw_audio.frame_rate = 48000;
986 fDefaultFormatRawAudio.u.raw_audio.channel_count = 2;
987 // XXX broken in Haiku...
988 // fDefaultFormatRawAudio.u.raw_audio.format = 0; // wildcard
989 fDefaultFormatRawAudio.u.raw_audio.format
990 = media_raw_audio_format::B_AUDIO_SHORT;
991 // when set to 0, haiku mixer has problems when diung a format change
992 // set to short and debug the buffer_size problem first!
993 fDefaultFormatRawAudio.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
994 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 0; // wildcard
995 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 0x1200;
996 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 0x1000;
997 fDefaultFormatRawAudio.u.raw_audio.buffer_size = 32768;
998 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 333 * 8;
999 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 512;
1000 // when set to anything different from 32768 haiku mixer has problems
1002 fDefaultFormatEncVideo.type = B_MEDIA_ENCODED_VIDEO;
1003 fDefaultFormatEncAudio.type = B_MEDIA_ENCODED_AUDIO;
1004 fDefaultFormatTS.type = B_MEDIA_MULTISTREAM;
1008 bool
1009 DVBMediaNode::VerifyFormatRawVideo(const media_raw_video_format &format)
1011 if (format.display.format != 0 &&
1012 format.display.format != B_RGB32 &&
1013 format.display.format != B_YCbCr422)
1014 return false;
1016 return true;
1020 bool
1021 DVBMediaNode::VerifyFormatRawAudio(const media_multi_audio_format &format)
1023 if (format.format != 0 &&
1024 format.format != media_raw_audio_format::B_AUDIO_FLOAT &&
1025 format.format != media_raw_audio_format::B_AUDIO_SHORT)
1026 return false;
1028 return true;
1032 void
1033 DVBMediaNode::SpecializeFormatRawVideo(media_raw_video_format *format)
1035 // Here we need to specialize *all* remaining wildcard
1036 // fields that the consumer didn't set
1037 if (format->field_rate == 0.0)
1038 format->field_rate = 25;
1040 // XXX a lot is missing here...
1044 void
1045 DVBMediaNode::SpecializeFormatRawAudio(media_multi_audio_format *format)
1047 // Here we need to specialize *all* remaining wildcard
1048 // fields that the consumer didn't set
1049 if (format->format == 0)
1050 format->format = media_raw_audio_format::B_AUDIO_SHORT;
1052 if (format->buffer_size == 0)
1053 format->buffer_size = 333 * 8;
1055 // XXX a lot is missing here...
1059 void
1060 DVBMediaNode::SpecializeFormatEncVideo(media_encoded_video_format *format)
1062 // Here we need to specialize *all* remaining wildcard
1063 // fields that the consumer didn't set
1067 void
1068 DVBMediaNode::SpecializeFormatEncAudio(media_encoded_audio_format *format)
1070 // Here we need to specialize *all* remaining wildcard
1071 // fields that the consumer didn't set
1075 void
1076 DVBMediaNode::SpecializeFormatTS(media_multistream_format *format)
1078 // Here we need to specialize *all* remaining wildcard
1079 // fields that the consumer didn't set
1083 status_t
1084 DVBMediaNode::SetOutput(const media_source &source,
1085 const media_destination &destination, const media_format &format)
1087 switch (source.id) {
1088 case ID_RAW_VIDEO:
1089 fOutputRawVideo.destination = destination;
1090 fOutputRawVideo.format = format;
1091 break;
1093 case ID_RAW_AUDIO:
1094 fOutputRawAudio.destination = destination;
1095 fOutputRawAudio.format = format;
1096 break;
1098 case ID_ENC_VIDEO:
1099 fOutputEncVideo.destination = destination;
1100 fOutputEncVideo.format = format;
1101 break;
1103 case ID_ENC_AUDIO:
1104 fOutputEncAudio.destination = destination;
1105 fOutputEncAudio.format = format;
1106 break;
1108 case ID_TS:
1109 fOutputTS.destination = destination;
1110 fOutputTS.format = format;
1111 break;
1113 default:
1114 return B_MEDIA_BAD_SOURCE;
1116 return B_OK;
1120 status_t
1121 DVBMediaNode::ResetOutput(const media_source &source)
1123 switch (source.id) {
1124 case ID_RAW_VIDEO:
1125 fOutputRawVideo.destination = media_destination::null;
1126 fOutputRawVideo.format = fDefaultFormatRawVideo;
1127 break;
1129 case ID_RAW_AUDIO:
1130 fOutputRawAudio.destination = media_destination::null;
1131 fOutputRawAudio.format = fDefaultFormatRawAudio;
1132 break;
1134 case ID_ENC_VIDEO:
1135 fOutputEncVideo.destination = media_destination::null;
1136 fOutputEncVideo.format = fDefaultFormatEncVideo;
1137 break;
1139 case ID_ENC_AUDIO:
1140 fOutputEncAudio.destination = media_destination::null;
1141 fOutputEncAudio.format = fDefaultFormatEncAudio;
1142 break;
1144 case ID_TS:
1145 fOutputTS.destination = media_destination::null;
1146 fOutputTS.format = fDefaultFormatTS;
1147 break;
1149 default:
1150 return B_MEDIA_BAD_SOURCE;
1152 return B_OK;
1156 const char *
1157 DVBMediaNode::SourceDefaultName(const media_source &source)
1159 switch (source.id) {
1160 case ID_RAW_VIDEO:
1161 return "raw video";
1163 case ID_RAW_AUDIO:
1164 return "raw audio";
1166 case ID_ENC_VIDEO:
1167 return "encoded video";
1169 case ID_ENC_AUDIO:
1170 return "encoded audio";
1172 case ID_TS:
1173 return "MPEG2 TS";
1175 default:
1176 return NULL;
1181 void
1182 DVBMediaNode::HandleStart(bigtime_t performance_time)
1184 TRACE("DVBMediaNode::HandleStart\n");
1185 StartCapture();
1189 void
1190 DVBMediaNode::HandleStop(void)
1192 TRACE("DVBMediaNode::HandleStop\n");
1193 StopCapture();
1197 status_t
1198 DVBMediaNode::Tune()
1200 TRACE("DVBMediaNode::Tune enter\n");
1202 TRACE("state %d, region %d, channel %d, audio %d\n",
1203 fSelectedState, fSelectedRegion, fSelectedChannel, fSelectedAudio);
1205 status_t err;
1206 bool needs_tuning = false;
1208 if (fSelectedChannel < 0 || fSelectedAudio < 0) {
1209 printf("DVBMediaNode::Tune: invalid tuning info\n");
1210 StopCapture();
1211 err = B_ERROR;
1212 goto end;
1213 // return B_ERROR;
1216 const char *desc;
1218 dvb_tuning_parameters_t new_params;
1219 int new_video_pid;
1220 int new_audio_pid;
1221 int new_pcr_pid;
1223 desc = fChannelList->ItemAt(fSelectedChannel);
1224 err = ExtractTuningParams(desc, fSelectedAudio, &new_params,
1225 &new_video_pid, &new_audio_pid, &new_pcr_pid);
1227 if (err != B_OK) {
1228 printf("DVBMediaNode::Tune: getting tuning info failed\n");
1229 StopCapture();
1230 err = B_ERROR;
1231 goto end;
1232 // return B_ERROR;
1235 if (fTuningParam.frequency == new_params.frequency) {
1236 printf("DVBMediaNode::Tune: frequency not changed\n");
1237 fVideoPid = new_video_pid;
1238 fAudioPid = new_audio_pid;
1239 fPcrPid = new_pcr_pid;
1240 fDemux->SetPIDs(fVideoPid, fAudioPid, fPcrPid);
1241 return B_OK;
1244 switch (fInterfaceType) {
1245 case DVB_TYPE_DVB_T:
1246 needs_tuning = (fTuningParam.u.dvb_t.frequency
1247 != new_params.u.dvb_t.frequency) || !fTuningSuccess;
1248 needs_tuning = true;
1249 break;
1251 case DVB_TYPE_DVB_S:
1252 printf("needs_tuning = %d, forcing tuning for DVB-S\n",
1253 needs_tuning);
1254 needs_tuning = true;
1255 break;
1257 default:
1258 needs_tuning = true;
1259 break;
1262 fTuningParam = new_params;
1263 fVideoPid = new_video_pid;
1264 fAudioPid = new_audio_pid;
1265 fPcrPid = new_pcr_pid;
1267 if (needs_tuning) {
1268 printf("about to stop capture 1\n");
1269 #if STOP_CAPTURE_WHILE_TUNING
1270 printf("about to stop capture 2\n");
1271 err = StopCapture();
1272 if (err) {
1273 printf("Tune: StopCapture failed\n");
1274 goto end;
1276 #endif
1277 } else {
1278 #if STOP_CAPTURE_WHILE_TUNING
1279 StopCaptureThreads();
1280 #endif
1283 if (needs_tuning) {
1284 err = fCard->SetTuningParameter(fTuningParam);
1285 fTuningSuccess = err == B_OK;
1288 fDemux->SetPIDs(fVideoPid, fAudioPid, fPcrPid);
1290 if (needs_tuning) {
1291 if (fTuningSuccess) {
1292 fCard->GetTuningParameter(&fTuningParam);
1293 err = StartCapture();
1295 } else {
1296 #if STOP_CAPTURE_WHILE_TUNING
1297 StartCaptureThreads();
1298 #endif
1301 end:
1302 EventQueue()->AddEvent(media_timed_event(0, M_REFRESH_PARAMETER_WEB));
1303 // RefreshParameterWeb();
1305 TRACE("DVBMediaNode::Tune finished\n");
1306 return err;
1310 status_t
1311 DVBMediaNode::StartCapture()
1313 TRACE("DVBMediaNode::StartCapture\n");
1315 if (fCaptureActive)
1316 return B_OK;
1318 RETURN_IF_ERROR(StopCaptureThreads());
1320 if (!fTuningSuccess) {
1321 RETURN_IF_ERROR(Tune());
1324 RETURN_IF_ERROR(StartCaptureThreads());
1326 fCard->CaptureStart();
1328 fCaptureActive = true;
1330 RefreshParameterWeb();
1332 return B_OK;
1336 status_t
1337 DVBMediaNode::StopCapture()
1339 TRACE("DVBMediaNode::StopCapture\n");
1340 if (!fCaptureActive)
1341 return B_OK;
1343 StopCaptureThreads();
1345 fCard->CaptureStop();
1347 fCaptureActive = false;
1348 return B_OK;
1352 status_t
1353 DVBMediaNode::StartCaptureThreads()
1355 TRACE("DVBMediaNode::StartCaptureThreads\n");
1357 if (fCaptureThreadsActive)
1358 return B_OK;
1360 fTerminateThreads = false;
1362 fThreadIdCardReader = spawn_thread(_card_reader_thread_, "DVB card reader",
1363 120, this);
1364 fThreadIdMpegDemux = spawn_thread(_mpeg_demux_thread_, "DVB MPEG demux",
1365 110, this);
1366 fThreadIdEncAudio = spawn_thread(_enc_audio_thread_, "DVB audio streaming",
1367 110, this);
1368 fThreadIdEncVideo = spawn_thread(_enc_video_thread_, "DVB video streaming",
1369 110, this);
1370 fThreadIdMpegTS = spawn_thread(_mpeg_ts_thread_, "DVB MPEG TS streaming",
1371 110, this);
1372 fThreadIdRawAudio = spawn_thread(_raw_audio_thread_, "DVB audio decode",
1373 100, this);
1374 fThreadIdRawVideo = spawn_thread(_raw_video_thread_, "DVB video decode",
1375 85, this);
1376 resume_thread(fThreadIdCardReader);
1377 resume_thread(fThreadIdMpegDemux);
1378 resume_thread(fThreadIdEncAudio);
1379 resume_thread(fThreadIdEncVideo);
1380 resume_thread(fThreadIdMpegTS);
1381 resume_thread(fThreadIdRawAudio);
1382 resume_thread(fThreadIdRawVideo);
1384 fCaptureThreadsActive = true;
1385 return B_OK;
1389 status_t
1390 DVBMediaNode::StopCaptureThreads()
1392 TRACE("DVBMediaNode::StopCaptureThreads\n");
1394 if (!fCaptureThreadsActive)
1395 return B_OK;
1397 fTerminateThreads = true;
1399 fCardDataQueue->Terminate();
1400 fEncVideoQueue->Terminate();
1401 fEncAudioQueue->Terminate();
1402 fMpegTsQueue->Terminate();
1403 fRawVideoQueue->Terminate();
1404 fRawAudioQueue->Terminate();
1406 status_t dummy; // NULL as parameter does not work
1407 wait_for_thread(fThreadIdCardReader, &dummy);
1408 wait_for_thread(fThreadIdMpegDemux, &dummy);
1409 wait_for_thread(fThreadIdEncAudio, &dummy);
1410 wait_for_thread(fThreadIdEncVideo, &dummy);
1411 wait_for_thread(fThreadIdMpegTS, &dummy);
1412 wait_for_thread(fThreadIdRawAudio, &dummy);
1413 wait_for_thread(fThreadIdRawVideo, &dummy);
1415 fCardDataQueue->Restart();
1416 fEncVideoQueue->Restart();
1417 fEncAudioQueue->Restart();
1418 fMpegTsQueue->Restart();
1419 fRawVideoQueue->Restart();
1420 fRawAudioQueue->Restart();
1422 fCaptureThreadsActive = false;
1423 return B_OK;
1427 int32
1428 DVBMediaNode::_card_reader_thread_(void *arg)
1430 static_cast<DVBMediaNode *>(arg)->card_reader_thread();
1431 return 0;
1435 int32
1436 DVBMediaNode::_mpeg_demux_thread_(void *arg)
1438 static_cast<DVBMediaNode *>(arg)->mpeg_demux_thread();
1439 return 0;
1443 int32
1444 DVBMediaNode::_raw_audio_thread_(void *arg)
1446 static_cast<DVBMediaNode *>(arg)->raw_audio_thread();
1447 return 0;
1451 int32
1452 DVBMediaNode::_raw_video_thread_(void *arg)
1454 static_cast<DVBMediaNode *>(arg)->raw_video_thread();
1455 return 0;
1459 int32
1460 DVBMediaNode::_enc_audio_thread_(void *arg)
1462 static_cast<DVBMediaNode *>(arg)->enc_audio_thread();
1463 return 0;
1467 int32
1468 DVBMediaNode::_enc_video_thread_(void *arg)
1470 static_cast<DVBMediaNode *>(arg)->enc_video_thread();
1471 return 0;
1475 int32
1476 DVBMediaNode::_mpeg_ts_thread_(void *arg)
1478 static_cast<DVBMediaNode *>(arg)->mpeg_ts_thread();
1479 return 0;
1483 void
1484 DVBMediaNode::card_reader_thread()
1486 while (!fTerminateThreads) {
1487 void *data;
1488 size_t size;
1489 status_t err;
1490 bigtime_t end_time;
1491 err = fCard->Capture(&data, &size, &end_time);
1492 if (err != B_OK) {
1493 TRACE("fCard->Capture failed, error %lx (%s)\n", err,
1494 strerror(err));
1495 continue;
1498 // TRACE("captured %ld bytes\n", size);
1500 Packet *packet = new Packet(data, size, end_time);
1502 err = fCardDataQueue->Insert(packet);
1503 if (err != B_OK) {
1504 delete packet;
1505 TRACE("fCardDataQueue->Insert failed, error %lx\n", err);
1506 continue;
1512 void
1513 DVBMediaNode::mpeg_demux_thread()
1515 while (!fTerminateThreads) {
1516 status_t err;
1517 Packet *packet;
1518 err = fCardDataQueue->Remove(&packet);
1519 if (err != B_OK) {
1520 TRACE("fCardDataQueue->Remove failed, error %lx\n", err);
1521 continue;
1524 // packet->TimeStamp() is the end time of the capture
1525 fDemux->AddData(packet);
1530 void
1531 DVBMediaNode::mpeg_ts_thread()
1533 while (!fTerminateThreads) {
1534 status_t err;
1535 Packet *packet;
1536 err = fMpegTsQueue->Remove(&packet);
1537 if (err != B_OK) {
1538 TRACE("fMpegTsQueue->Remove failed, error %lx\n", err);
1539 continue;
1542 // TRACE("mpeg ts packet, size %6ld, start_time %14Ld\n",
1543 // packet->Size(), packet->TimeStamp());
1545 #ifdef DUMP_MPEG_TS
1546 lock.Lock();
1547 write(fMpegTsFile, packet->Data(), packet->Size());
1548 lock.Unlock();
1549 #endif
1551 delete packet;
1556 void
1557 DVBMediaNode::enc_audio_thread()
1559 while (!fTerminateThreads) {
1560 status_t err;
1561 Packet *packet;
1562 err = fEncAudioQueue->Remove(&packet);
1563 if (err != B_OK) {
1564 TRACE("fEncAudioQueue->Remove failed, error %lx\n", err);
1565 continue;
1567 // TRACE("enc audio packet, size %6ld, start_time %14Ld\n",
1568 // packet->Size(), packet->TimeStamp());
1570 #ifdef DUMP_AUDIO
1571 const uint8 *data;
1572 size_t size;
1573 if (B_OK != pes_extract(packet->Data(), packet->Size(), &data,
1574 &size)) {
1575 TRACE("audio pes_extract failed\n");
1576 delete packet;
1577 return;
1579 lock.Lock();
1580 write(fAudioFile, data, size);
1581 lock.Unlock();
1582 #endif
1584 if (!fOutputEnabledEncAudio) {
1585 delete packet;
1586 continue;
1589 // send encoded audio buffer
1592 delete packet;
1597 void
1598 DVBMediaNode::enc_video_thread()
1600 while (!fTerminateThreads) {
1601 status_t err;
1602 Packet *packet;
1603 err = fEncVideoQueue->Remove(&packet);
1604 if (err != B_OK) {
1605 TRACE("fEncVideoQueue->Remove failed, error %lx\n", err);
1606 continue;
1609 // TRACE("enc video packet, size %6ld, start_time %14Ld\n",
1610 // packet->Size(), packet->TimeStamp());
1613 #ifdef DUMP_VIDEO
1614 int8 *data;
1615 size_t size;
1616 if (B_OK != pes_extract(packet->Data(), packet->Size(), &data,
1617 &size)) {
1618 TRACE("video pes_extract failed\n");
1619 delete packet;
1620 return;
1622 lock.Lock();
1623 write(fVideoFile, data, size);
1624 lock.Unlock();
1625 #endif
1627 if (!fOutputEnabledEncVideo) {
1628 delete packet;
1629 continue;
1632 // send encoded video buffer
1634 delete packet;
1639 void
1640 DVBMediaNode::raw_audio_thread()
1642 media_format format;
1643 status_t err;
1644 err = GetStreamFormat(fRawAudioQueue, &format);
1645 if (err) {
1646 printf("fAudioDecoder init error %s\n", strerror(err));
1647 return;
1650 // create decoder interface
1652 fAudioDecoder = new MediaStreamDecoder(&_GetNextAudioChunk, this);
1654 err = fAudioDecoder->SetInputFormat(format);
1655 if (err) {
1656 printf("fAudioDecoder SetInputFormat error %s\n", strerror(err));
1657 return;
1660 TRACE("requested audio decoder format: ");
1661 PrintFormat(fOutputRawAudio);
1663 media_format fmt = fOutputRawAudio.format;
1664 err = fAudioDecoder->SetOutputFormat(&fmt);
1665 if (err) {
1666 printf("fAudioDecoder SetOutputFormat error %s\n", strerror(err));
1667 return;
1670 TRACE("final audio decoder format: ");
1671 PrintFormat(fmt);
1673 // change format of connection
1674 if (format_is_compatible(fmt, fOutputRawAudio.format)) {
1675 printf("audio formats are compatible\n");
1676 fOutputRawAudio.format = fmt;
1677 } else {
1678 printf("audio formats NOT compatible\n");
1679 lock.Lock();
1680 err = ChangeFormat(fOutputRawAudio.source,
1681 fOutputRawAudio.destination,
1682 &fmt);
1683 lock.Unlock();
1684 printf("format change result %lx (%s)\n", err, strerror(err));
1685 PrintFormat(fmt);
1686 fOutputRawAudio.format = fmt;
1687 if (err)
1688 return;
1691 // decode data and send buffers
1693 delete fBufferGroupRawAudio;
1694 fBufferGroupRawAudio = new BBufferGroup(
1695 fOutputRawAudio.format.u.raw_audio.buffer_size * 3, 25);
1697 while (!fTerminateThreads) {
1698 int64 frameCount;
1699 media_header mh;
1701 if (!fOutputEnabledRawAudio) {
1702 fRawAudioQueue->Flush(40000);
1703 continue;
1706 BBuffer* buf;
1707 buf = fBufferGroupRawAudio->RequestBuffer(
1708 fOutputRawAudio.format.u.raw_audio.buffer_size,
1709 AUDIO_BUFFER_REQUEST_TIMEOUT);
1710 if (!buf) {
1711 TRACE("audio: request buffer timout\n");
1712 continue;
1715 err = fAudioDecoder->Decode(buf->Data(), &frameCount, &mh, NULL);
1716 if (err) {
1717 buf->Recycle();
1718 printf("fAudioDecoder Decode error %s\n", strerror(err));
1719 continue;
1722 #ifdef DUMP_RAW_AUDIO
1723 lock.Lock();
1724 write(fRawAudioFile, buf->Data(), mh.size_used);
1725 lock.Unlock();
1726 #endif
1728 if (fOutputRawAudio.format.u.raw_audio.buffer_size != mh.size_used
1729 || int(fOutputRawAudio.format.u.raw_audio.frame_rate)
1730 != mh.u.raw_audio.frame_rate
1731 || fOutputRawAudio.format.u.raw_audio.channel_count
1732 != mh.u.raw_audio.channel_count) {
1733 TRACE("audio: decode format change: changed buffer_size from %ld"
1734 " to %ld\n", fOutputRawAudio.format.u.raw_audio.buffer_size,
1735 mh.size_used);
1736 TRACE("audio: decode format change: changed channel_count from %ld"
1737 " to %ld\n", fOutputRawAudio.format.u.raw_audio.channel_count,
1738 mh.u.raw_audio.channel_count);
1739 TRACE("audio: decode format change: changed frame_rate from %.0f"
1740 " to %.0f\n", fOutputRawAudio.format.u.raw_audio.frame_rate,
1741 mh.u.raw_audio.frame_rate);
1742 fOutputRawAudio.format.u.raw_audio.buffer_size = mh.size_used;
1743 fOutputRawAudio.format.u.raw_audio.frame_rate
1744 = mh.u.raw_audio.frame_rate;
1745 fOutputRawAudio.format.u.raw_audio.channel_count
1746 = mh.u.raw_audio.channel_count;
1747 lock.Lock();
1748 err = ChangeFormat(fOutputRawAudio.source,
1749 fOutputRawAudio.destination, &fOutputRawAudio.format);
1750 lock.Unlock();
1751 printf("format change result %lx (%s)\n", err, strerror(err));
1752 PrintFormat(fOutputRawAudio.format);
1753 if (err) {
1754 buf->Recycle();
1755 return; // we are dead!
1759 bigtime_t ts_perf_time;
1760 bigtime_t ts_sys_time;
1761 bigtime_t ts_offset;
1762 bigtime_t aud_time;
1763 bigtime_t start_time;
1765 // calculate start time of audio data
1767 fDemux->TimesourceInfo(&ts_perf_time, &ts_sys_time);
1768 ts_offset = ts_sys_time - ts_perf_time;
1769 aud_time = mh.start_time; // measured in PCR time base
1770 start_time = TimeSource()->PerformanceTimeFor(aud_time + ts_offset);
1772 // calculate delay and wait
1774 bigtime_t delay;
1775 delay = start_time - TimeSource()->Now();
1776 TRACE_TIMING("audio delay is %Ld\n", delay);
1777 if (delay < -AUDIO_MAX_LATE) {
1778 printf("audio: decoded packet is %Ldms too late, dropped\n",
1779 -delay / 1000);
1780 buf->Recycle();
1781 continue;
1783 if (delay < 0)
1784 // printf("audio: decoded packet is %Ldms too late\n", -delay / 1000);
1786 if (delay > AUDIO_MAX_EARLY) {
1787 printf("audio: decoded packet is %Ldms too early, dropped\n",
1788 delay / 1000);
1789 buf->Recycle();
1790 continue;
1792 if (delay > 0)
1793 // printf("audio: decoded packet is %Ldms too early\n", delay / 1000);
1795 delay -= PROCESSING_LATENCY;
1796 if (delay > 0) {
1797 if (acquire_sem_etc(fAudioDelaySem, 1, B_RELATIVE_TIMEOUT, delay)
1798 != B_TIMED_OUT) {
1799 printf("audio: delay sem not timed out, dropped packet\n");
1800 buf->Recycle();
1801 continue;
1805 TRACE_TIMING("audio playback delay %Ld\n",
1806 start_time - TimeSource()->Now());
1808 media_header* hdr;
1809 hdr = buf->Header();
1810 hdr->type = B_MEDIA_RAW_AUDIO;
1811 hdr->size_used = mh.size_used;
1812 hdr->time_source = TimeSource()->ID();
1813 hdr->start_time = start_time;
1814 lock.Lock();
1815 if (SendBuffer(buf, fOutputRawAudio.source,
1816 fOutputRawAudio.destination) != B_OK) {
1817 TRACE("audio: sending buffer failed\n");
1818 buf->Recycle();
1820 lock.Unlock();
1823 delete fCurrentAudioPacket;
1824 fCurrentAudioPacket = 0;
1828 void
1829 DVBMediaNode::raw_video_thread()
1831 media_format format;
1832 status_t err;
1833 err = GetStreamFormat(fRawVideoQueue, &format);
1834 if (err) {
1835 printf("fVideoDecoder init error %s\n", strerror(err));
1836 return;
1839 // create decoder interface
1841 fVideoDecoder = new MediaStreamDecoder(&_GetNextVideoChunk, this);
1843 err = fVideoDecoder->SetInputFormat(format);
1844 if (err) {
1845 printf("fVideoDecoder SetInputFormat error %s\n", strerror(err));
1846 return;
1849 TRACE("requested video decoder format: ");
1850 PrintFormat(fOutputRawVideo);
1852 media_format fmt = fOutputRawVideo.format;
1853 err = fVideoDecoder->SetOutputFormat(&fmt);
1854 if (err) {
1855 printf("fVideoDecoder SetOutputFormat error %s\n", strerror(err));
1856 return;
1859 TRACE("final video decoder format: ");
1860 PrintFormat(fmt);
1862 // change format of connection
1863 if (format_is_compatible(fmt, fOutputRawVideo.format)) {
1864 printf("video formats are compatible\n");
1865 fOutputRawVideo.format = fmt;
1866 } else {
1867 printf("video formats NOT compatible\n");
1868 lock.Lock();
1869 err = ChangeFormat(fOutputRawVideo.source,
1870 fOutputRawVideo.destination,
1871 &fmt);
1872 lock.Unlock();
1873 printf("format change result %lx (%s)\n", err, strerror(err));
1874 PrintFormat(fmt);
1875 fOutputRawVideo.format = fmt;
1876 if (err) {
1877 printf("video format change failed\n");
1878 return;
1882 // decode data and send buffers
1884 uint32 video_buffer_size_max = 720 * 576 * 4;
1885 uint32 video_buffer_size
1886 = fOutputRawVideo.format.u.raw_video.display.line_count
1887 * fOutputRawVideo.format.u.raw_video.display.bytes_per_row;
1889 delete fBufferGroupRawVideo;
1890 fBufferGroupRawVideo = new BBufferGroup(video_buffer_size_max, 4);
1892 while (!fTerminateThreads) {
1893 int64 frameCount;
1894 media_header mh;
1896 if (!fOutputEnabledRawVideo) {
1897 fRawVideoQueue->Flush(40000);
1898 continue;
1901 // fetch a new buffer (always of maximum size as the stream may change)
1902 BBuffer* buf;
1903 buf = fBufferGroupRawVideo->RequestBuffer(video_buffer_size_max,
1904 VIDEO_BUFFER_REQUEST_TIMEOUT);
1905 if (!buf) {
1906 TRACE("video: request buffer timout\n");
1907 continue;
1910 // decode one video frame into buffer
1911 err = fVideoDecoder->Decode(buf->Data(), &frameCount, &mh, NULL);
1912 if (err) {
1913 buf->Recycle();
1914 printf("fVideoDecoder Decode error %s\n", strerror(err));
1915 continue;
1918 // check if the format of the stream has changed
1919 if (mh.u.raw_video.display_line_width
1920 != fOutputRawVideo.format.u.raw_video.display.line_width
1921 || mh.u.raw_video.display_line_count
1922 != fOutputRawVideo.format.u.raw_video.display.line_count
1923 || mh.u.raw_video.bytes_per_row
1924 != fOutputRawVideo.format.u.raw_video.display.bytes_per_row
1925 || mh.u.raw_video.pixel_width_aspect
1926 != fOutputRawVideo.format.u.raw_video.pixel_width_aspect
1927 || mh.u.raw_video.pixel_height_aspect
1928 != fOutputRawVideo.format.u.raw_video.pixel_height_aspect
1929 || mh.size_used != video_buffer_size) {
1930 printf("video format changed:\n");
1931 printf(" line_width %ld => %ld\n",
1932 fOutputRawVideo.format.u.raw_video.display.line_width,
1933 mh.u.raw_video.display_line_width);
1934 printf(" line_count %ld => %ld\n",
1935 fOutputRawVideo.format.u.raw_video.display.line_count,
1936 mh.u.raw_video.display_line_count);
1937 printf(" bytes_per_row %ld => %ld\n",
1938 fOutputRawVideo.format.u.raw_video.display.bytes_per_row,
1939 mh.u.raw_video.bytes_per_row);
1940 printf(" pixel_width_aspect %d => %d\n",
1941 fOutputRawVideo.format.u.raw_video.pixel_width_aspect,
1942 mh.u.raw_video.pixel_width_aspect);
1943 printf(" pixel_height_aspect %d => %d\n",
1944 fOutputRawVideo.format.u.raw_video.pixel_height_aspect,
1945 mh.u.raw_video.pixel_height_aspect);
1946 printf(" video_buffer_size %ld => %ld\n", video_buffer_size,
1947 mh.size_used);
1949 // recalculate video buffer size
1950 video_buffer_size
1951 = fOutputRawVideo.format.u.raw_video.display.line_count
1952 * fOutputRawVideo.format.u.raw_video.display.bytes_per_row;
1954 // perform a video format change
1955 fOutputRawVideo.format.u.raw_video.display.line_width
1956 = mh.u.raw_video.display_line_width;
1957 fOutputRawVideo.format.u.raw_video.display.line_count
1958 = mh.u.raw_video.display_line_count;
1959 fOutputRawVideo.format.u.raw_video.display.bytes_per_row
1960 = mh.u.raw_video.bytes_per_row;
1961 fOutputRawVideo.format.u.raw_video.pixel_width_aspect
1962 = mh.u.raw_video.pixel_width_aspect;
1963 fOutputRawVideo.format.u.raw_video.pixel_height_aspect
1964 = mh.u.raw_video.pixel_height_aspect;
1965 fOutputRawVideo.format.u.raw_video.last_active
1966 = mh.u.raw_video.display_line_count - 1;
1967 lock.Lock();
1968 err = ChangeFormat(fOutputRawVideo.source,
1969 fOutputRawVideo.destination, &fOutputRawVideo.format);
1970 lock.Unlock();
1971 printf("format change result %lx (%s)\n", err, strerror(err));
1972 PrintFormat(fOutputRawVideo.format);
1973 if (err) {
1974 buf->Recycle();
1975 printf("video format change failed\n");
1976 return; // we are dead
1980 // calculate start time for video
1981 bigtime_t ts_perf_time;
1982 bigtime_t ts_sys_time;
1983 bigtime_t ts_offset;
1984 bigtime_t pic_time;
1985 bigtime_t start_time;
1987 fDemux->TimesourceInfo(&ts_perf_time, &ts_sys_time);
1988 ts_offset = ts_sys_time - ts_perf_time;
1989 pic_time = mh.start_time; // measured in PCR time base
1990 start_time = TimeSource()->PerformanceTimeFor(pic_time + ts_offset);
1992 // calculate delay and wait
1994 bigtime_t delay;
1995 delay = start_time - TimeSource()->Now();
1996 TRACE_TIMING("video delay %Ld\n", delay);
1997 if (delay < -VIDEO_MAX_LATE) {
1998 printf("video: decoded packet is %Ldms too late, dropped\n",
1999 -delay / 1000);
2000 buf->Recycle();
2001 continue;
2003 if (delay > VIDEO_MAX_EARLY) {
2004 printf("video: decoded packet is %Ldms too early, dropped\n",
2005 delay / 1000);
2006 buf->Recycle();
2007 continue;
2009 delay -= PROCESSING_LATENCY;
2010 if (delay > 0) {
2011 if (acquire_sem_etc(fVideoDelaySem, 1, B_RELATIVE_TIMEOUT, delay)
2012 != B_TIMED_OUT) {
2013 printf("video: delay sem not timed out, dropped packet\n");
2014 buf->Recycle();
2015 continue;
2019 TRACE_TIMING("video playback delay %Ld\n", start_time
2020 - TimeSource()->Now());
2022 media_header* hdr;
2023 hdr = buf->Header();
2024 hdr->type = B_MEDIA_RAW_VIDEO;
2025 hdr->size_used = video_buffer_size;
2026 hdr->time_source = TimeSource()->ID();
2027 hdr->start_time = start_time;
2028 lock.Lock();
2029 if (SendBuffer(buf, fOutputRawVideo.source,
2030 fOutputRawVideo.destination) != B_OK) {
2031 TRACE("video: sending buffer failed\n");
2032 buf->Recycle();
2034 lock.Unlock();
2037 delete fCurrentVideoPacket;
2038 fCurrentVideoPacket = 0;
2042 inline status_t
2043 DVBMediaNode::GetNextVideoChunk(const void **chunkData, size_t *chunkLen,
2044 media_header *mh)
2046 // TRACE("DVBMediaNode::GetNextVideoChunk\n");
2048 delete fCurrentVideoPacket;
2050 status_t err;
2051 err = fRawVideoQueue->Remove(&fCurrentVideoPacket);
2052 if (err != B_OK) {
2053 TRACE("fRawVideoQueue->Remove failed, error %lx\n", err);
2054 fCurrentVideoPacket = 0;
2055 return B_ERROR;
2058 const uint8 *data;
2059 size_t size;
2061 if (B_OK != pes_extract(fCurrentVideoPacket->Data(),
2062 fCurrentVideoPacket->Size(), &data, &size)) {
2063 TRACE("video pes_extract failed\n");
2064 return B_ERROR;
2067 *chunkData = data;
2068 *chunkLen = size;
2069 // measured in PCR time base
2070 mh->start_time = fCurrentVideoPacket->TimeStamp();
2072 return B_OK;
2076 inline status_t
2077 DVBMediaNode::GetNextAudioChunk(const void **chunkData, size_t *chunkLen,
2078 media_header *mh)
2080 // TRACE("DVBMediaNode::GetNextAudioChunk\n");
2082 delete fCurrentAudioPacket;
2084 status_t err;
2085 err = fRawAudioQueue->Remove(&fCurrentAudioPacket);
2086 if (err != B_OK) {
2087 TRACE("fRawAudioQueue->Remove failed, error %lx\n", err);
2088 fCurrentAudioPacket = 0;
2089 return B_ERROR;
2092 const uint8 *data;
2093 size_t size;
2095 if (B_OK != pes_extract(fCurrentAudioPacket->Data(),
2096 fCurrentAudioPacket->Size(), &data, &size)) {
2097 TRACE("audio pes_extract failed\n");
2098 return B_ERROR;
2101 *chunkData = data;
2102 *chunkLen = size;
2103 // measured in PCR time base
2104 mh->start_time = fCurrentAudioPacket->TimeStamp();
2106 // printf("GetNextAudioChunk: done start_time %Ld\n", mh->start_time);
2108 return B_OK;
2112 status_t
2113 DVBMediaNode::_GetNextVideoChunk(const void **chunkData, size_t *chunkLen,
2114 media_header *mh, void *cookie)
2116 return static_cast<DVBMediaNode *>(cookie)->GetNextVideoChunk(chunkData,
2117 chunkLen, mh);
2121 status_t
2122 DVBMediaNode::_GetNextAudioChunk(const void **chunkData, size_t *chunkLen,
2123 media_header *mh, void *cookie)
2125 return static_cast<DVBMediaNode *>(cookie)->GetNextAudioChunk(chunkData,
2126 chunkLen, mh);
2130 status_t
2131 DVBMediaNode::GetStreamFormat(PacketQueue *queue, media_format *format)
2133 status_t status;
2134 Packet *packet;
2135 const uint8 *data;
2136 size_t size;
2137 int stream_id;
2139 // get copy of the first packet from queue, and determine format
2140 status = queue->Peek(&packet);
2141 if (status != B_OK) {
2142 TRACE("queue->Peek failed, error %lx\n", status);
2143 return status;
2145 status = pes_extract(packet->Data(), packet->Size(), &data, &size);
2146 if (status != B_OK) {
2147 TRACE("pes_extract failed\n");
2148 goto done;
2150 status = pes_stream_id(packet->Data(), packet->Size(), &stream_id);
2151 if (status != B_OK) {
2152 TRACE("pes_stream_id failed\n");
2153 goto done;
2155 status = GetHeaderFormat(format, data, size, stream_id);
2156 if (status != B_OK) {
2157 TRACE("GetHeaderFormat failed, error %lx\n", status);
2158 goto done;
2161 done:
2162 delete packet;
2163 return status;
2167 enum {
2168 ID_STATE = 11,
2169 ID_REGION = 12,
2170 ID_CHANNEL = 13,
2171 ID_AUDIO = 14,
2175 void
2176 DVBMediaNode::RefreshParameterWeb()
2178 TRACE("DVBMediaNode::RefreshParameterWeb enter\n");
2179 fWeb = CreateParameterWeb();
2180 SetParameterWeb(fWeb);
2181 TRACE("DVBMediaNode::RefreshParameterWeb finished\n");
2185 void
2186 DVBMediaNode::SetAboutInfo(BParameterGroup *about)
2188 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "DVB media_addon info:",
2189 B_GENERIC);
2190 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Version " VERSION,
2191 B_GENERIC);
2192 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Revision " REVISION,
2193 B_GENERIC);
2194 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Build " BUILD, B_GENERIC);
2196 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "", B_GENERIC);
2197 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Driver info:", B_GENERIC);
2199 dvb_type_t type;
2200 char name[200];
2201 char info[200];
2203 fCard->GetCardType(&type);
2204 fCard->GetCardInfo(name, sizeof(name), info, sizeof(info));
2206 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, name, B_GENERIC);
2207 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, info, B_GENERIC);
2211 BParameterWeb *
2212 DVBMediaNode::CreateParameterWeb()
2214 /* Set up the parameter web */
2215 BParameterWeb *web = new BParameterWeb();
2217 char n[200], i[200];
2218 fCard->GetCardInfo(n, sizeof(n), i, sizeof(i));
2220 BString name;
2221 name << Name() << " - " << i;
2223 BParameterGroup *main = web->MakeGroup(name.String());
2225 BParameterGroup *ctrl = main->MakeGroup("Channel Selection");
2226 ctrl->MakeNullParameter(0, B_MEDIA_NO_TYPE, ctrl->Name(), B_GENERIC);
2228 BParameterGroup *pref = main->MakeGroup("Preferences");
2229 pref->MakeNullParameter(0, B_MEDIA_NO_TYPE, pref->Name(), B_GENERIC);
2231 BDiscreteParameter *state = pref->MakeDiscreteParameter(
2232 ID_STATE, B_MEDIA_RAW_VIDEO, "State", B_GENERIC);
2234 BDiscreteParameter *region = pref->MakeDiscreteParameter(
2235 ID_REGION, B_MEDIA_RAW_VIDEO, "Region", B_GENERIC);
2237 BDiscreteParameter *chan = ctrl->MakeDiscreteParameter(
2238 ID_CHANNEL, B_MEDIA_RAW_VIDEO, "Channel",
2239 /* B_TUNER_CHANNEL */ B_GENERIC);
2241 BDiscreteParameter *aud = ctrl->MakeDiscreteParameter(
2242 ID_AUDIO, B_MEDIA_RAW_VIDEO, "Audio", B_GENERIC);
2244 AddStateItems(state);
2245 AddRegionItems(region);
2246 AddChannelItems(chan);
2247 AddAudioItems(aud);
2250 if (!fTuningSuccess || !fCaptureActive) {
2251 BParameterGroup *info = main->MakeGroup("Info");
2252 info->MakeNullParameter(0, B_MEDIA_NO_TYPE, info->Name(), B_GENERIC);
2253 BParameterGroup *about = main->MakeGroup("About");
2254 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, about->Name(), B_GENERIC);
2255 SetAboutInfo(about);
2256 // info->MakeNullParameter(0, B_MEDIA_NO_TYPE,
2257 // fCaptureActive ? "Tuning failed" : "Node stopped", B_GENERIC);
2258 info->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Node is stopped",
2259 B_GENERIC);
2260 info->MakeNullParameter(0, B_MEDIA_NO_TYPE, "or tuning failed.",
2261 B_GENERIC);
2262 return web;
2265 BParameterGroup *info1 = main->MakeGroup("Info");
2266 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, info1->Name(), B_GENERIC);
2267 BParameterGroup *info2 = main->MakeGroup("Info");
2268 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, info2->Name(), B_GENERIC);
2269 BParameterGroup *about = main->MakeGroup("About");
2270 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, about->Name(), B_GENERIC);
2271 SetAboutInfo(about);
2273 BString sInterfaceType = "Interface Type: ";
2274 BString sFrequency = "Frequency: ";
2275 BString sAudioPid = "Audio PID: ";
2276 BString sVideoPid = "Video PID: ";
2277 BString sPcrPid = "PCR PID: ";
2278 BString sInversion = "Inversion: ";
2279 BString sBandwidth = "Bandwith: ";
2280 BString sModulation = "Modulation: ";
2281 BString sHierarchy = "Hierarchy: ";
2282 BString sCodeRateHP = "Code Rate HP: ";
2283 BString sCodeRateLP = "Code Rate LP: ";
2284 BString sTransmissionMode = "Transmission Mode: ";
2285 BString sGuardInterval = "Guard Interval: ";
2287 BString sSymbolRate = "Symbol Rate: ";
2288 BString sPolarity = "Polarity: ";
2289 BString sAgcInversion = "AGC Inversion: ";
2291 switch (fInterfaceType) {
2292 case DVB_TYPE_DVB_C:
2293 sInterfaceType << "DVB-C";
2294 break;
2296 case DVB_TYPE_DVB_H:
2297 sInterfaceType << "DVB-H";
2298 break;
2300 case DVB_TYPE_DVB_S:
2301 sInterfaceType << "DVB-S";
2302 break;
2304 case DVB_TYPE_DVB_T:
2305 sInterfaceType << "DVB-T";
2306 break;
2308 default:
2309 sInterfaceType << "unknown";
2310 break;
2313 sAudioPid << fAudioPid;
2314 sVideoPid << fVideoPid;
2315 sPcrPid << fPcrPid;
2317 if (fInterfaceType == DVB_TYPE_DVB_T) {
2319 sFrequency << fTuningParam.u.dvb_t.frequency / 1000000 << " MHz";
2321 switch (fTuningParam.u.dvb_t.inversion) {
2322 case DVB_INVERSION_AUTO:
2323 sInversion << "auto";
2324 break;
2326 case DVB_INVERSION_ON:
2327 sInversion << "on";
2328 break;
2330 case DVB_INVERSION_OFF:
2331 sInversion << "off";
2332 break;
2334 default:
2335 sInversion << "unknown";
2336 break;
2339 switch (fTuningParam.u.dvb_t.bandwidth) {
2340 case DVB_BANDWIDTH_AUTO:
2341 sBandwidth << "auto";
2342 break;
2344 case DVB_BANDWIDTH_6_MHZ:
2345 sBandwidth << "6 MHz";
2346 break;
2348 case DVB_BANDWIDTH_7_MHZ:
2349 sBandwidth << "7 MHz";
2350 break;
2352 case DVB_BANDWIDTH_8_MHZ:
2353 sBandwidth << "8 MHz";
2354 break;
2356 default:
2357 sBandwidth << "unknown";
2358 break;
2361 switch (fTuningParam.u.dvb_t.modulation) {
2362 case DVB_MODULATION_AUTO:
2363 sModulation << "auto";
2364 break;
2366 case DVB_MODULATION_QPSK:
2367 sModulation << "QPSK";
2368 break;
2370 case DVB_MODULATION_16_QAM:
2371 sModulation << "16 QAM";
2372 break;
2374 case DVB_MODULATION_32_QAM:
2375 sModulation << "32 QAM";
2376 break;
2378 case DVB_MODULATION_64_QAM:
2379 sModulation << "64 QAM";
2380 break;
2382 case DVB_MODULATION_128_QAM:
2383 sModulation << "128 QAM";
2384 break;
2386 case DVB_MODULATION_256_QAM:
2387 sModulation << "256 QAM";
2388 break;
2390 default:
2391 sModulation << "unknown";
2392 break;
2395 switch (fTuningParam.u.dvb_t.hierarchy) {
2396 case DVB_HIERARCHY_AUTO:
2397 sHierarchy << "auto";
2398 break;
2400 case DVB_HIERARCHY_NONE:
2401 sHierarchy << "none";
2402 break;
2404 case DVB_HIERARCHY_1:
2405 sHierarchy << "1";
2406 break;
2408 case DVB_HIERARCHY_2:
2409 sHierarchy << "2";
2410 break;
2412 case DVB_HIERARCHY_4:
2413 sHierarchy << "4";
2414 break;
2416 default:
2417 sHierarchy << "unknown";
2418 break;
2421 switch (fTuningParam.u.dvb_t.code_rate_hp) {
2422 case DVB_FEC_AUTO:
2423 sCodeRateHP << "auto";
2424 break;
2426 case DVB_FEC_NONE:
2427 sCodeRateHP << "none";
2428 break;
2430 case DVB_FEC_1_2:
2431 sCodeRateHP << "FEC 1/2";
2432 break;
2434 case DVB_FEC_2_3:
2435 sCodeRateHP << "FEC 2/3";
2436 break;
2438 case DVB_FEC_3_4:
2439 sCodeRateHP << "FEC 3/4";
2440 break;
2442 case DVB_FEC_4_5:
2443 sCodeRateHP << "FEC 4/5";
2444 break;
2446 case DVB_FEC_5_6:
2447 sCodeRateHP << "FEC 5/6";
2448 break;
2450 case DVB_FEC_6_7:
2451 sCodeRateHP << "FEC 6/7";
2452 break;
2454 case DVB_FEC_7_8:
2455 sCodeRateHP << "FEC 7/8";
2456 break;
2458 case DVB_FEC_8_9:
2459 sCodeRateHP << "FEC 8/9";
2460 break;
2462 default:
2463 sCodeRateHP << "unknown";
2464 break;
2467 switch (fTuningParam.u.dvb_t.code_rate_lp) {
2468 case DVB_FEC_AUTO:
2469 sCodeRateLP << "auto";
2470 break;
2472 case DVB_FEC_NONE:
2473 sCodeRateLP << "none";
2474 break;
2476 case DVB_FEC_1_2:
2477 sCodeRateLP << "FEC 1/2";
2478 break;
2480 case DVB_FEC_2_3:
2481 sCodeRateLP << "FEC 2/3";
2482 break;
2484 case DVB_FEC_3_4:
2485 sCodeRateLP << "FEC 3/4";
2486 break;
2488 case DVB_FEC_4_5:
2489 sCodeRateLP << "FEC 4/5";
2490 break;
2492 case DVB_FEC_5_6:
2493 sCodeRateLP << "FEC 5/6";
2494 break;
2496 case DVB_FEC_6_7:
2497 sCodeRateLP << "FEC 6/7";
2498 break;
2500 case DVB_FEC_7_8:
2501 sCodeRateLP << "FEC 7/8";
2502 break;
2504 case DVB_FEC_8_9:
2505 sCodeRateLP << "FEC 8/9";
2506 break;
2508 default:
2509 sCodeRateLP << "unknown";
2510 break;
2513 switch (fTuningParam.u.dvb_t.transmission_mode) {
2514 case DVB_TRANSMISSION_MODE_AUTO:
2515 sTransmissionMode << "auto";
2516 break;
2518 case DVB_TRANSMISSION_MODE_2K:
2519 sTransmissionMode << "2K";
2520 break;
2522 case DVB_TRANSMISSION_MODE_4K:
2523 sTransmissionMode << "4K";
2524 break;
2526 case DVB_TRANSMISSION_MODE_8K:
2527 sTransmissionMode << "8K";
2528 break;
2530 default:
2531 sTransmissionMode << "unknown";
2532 break;
2535 switch (fTuningParam.u.dvb_t.guard_interval) {
2536 case DVB_GUARD_INTERVAL_AUTO:
2537 sGuardInterval << "auto";
2538 break;
2540 case DVB_GUARD_INTERVAL_1_4:
2541 sGuardInterval << "1/4";
2542 break;
2544 case DVB_GUARD_INTERVAL_1_8:
2545 sGuardInterval << "1/8";
2546 break;
2548 case DVB_GUARD_INTERVAL_1_16:
2549 sGuardInterval << "1/16";
2550 break;
2552 case DVB_GUARD_INTERVAL_1_32:
2553 sGuardInterval << "1/32";
2554 break;
2556 default:
2557 sGuardInterval << "unknown";
2558 break;
2561 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInterfaceType.String(),
2562 B_GENERIC);
2563 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sFrequency.String(),
2564 B_GENERIC);
2565 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sBandwidth.String(),
2566 B_GENERIC);
2567 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sVideoPid.String(),
2568 B_GENERIC);
2569 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sAudioPid.String(),
2570 B_GENERIC);
2571 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sPcrPid.String(),
2572 B_GENERIC);
2574 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sModulation.String(),
2575 B_GENERIC);
2576 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE,
2577 sTransmissionMode.String(), B_GENERIC);
2578 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sGuardInterval.String(),
2579 B_GENERIC);
2580 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sCodeRateHP.String(),
2581 B_GENERIC);
2582 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sCodeRateLP.String(),
2583 B_GENERIC);
2584 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInversion.String(),
2585 B_GENERIC);
2586 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sHierarchy.String(),
2587 B_GENERIC);
2590 if (fInterfaceType == DVB_TYPE_DVB_S) {
2592 sFrequency << fTuningParam.u.dvb_s.frequency / 1000000 << " MHz";
2593 sSymbolRate << fTuningParam.u.dvb_s.symbolrate;
2595 switch (fTuningParam.u.dvb_s.inversion) {
2596 case DVB_INVERSION_AUTO:
2597 sInversion << "auto";
2598 break;
2600 case DVB_INVERSION_ON:
2601 sInversion << "on";
2602 break;
2604 case DVB_INVERSION_OFF:
2605 sInversion << "off";
2606 break;
2608 default:
2609 sInversion << "unknown";
2610 break;
2613 switch (fTuningParam.u.dvb_s.polarity) {
2614 case DVB_POLARITY_VERTICAL:
2615 sPolarity << "vertical";
2616 break;
2618 case DVB_POLARITY_HORIZONTAL:
2619 sPolarity << "horizontal";
2620 break;
2622 default:
2623 sPolarity << "unknown";
2624 break;
2627 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInterfaceType.String(),
2628 B_GENERIC);
2629 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sVideoPid.String(),
2630 B_GENERIC);
2631 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sAudioPid.String(),
2632 B_GENERIC);
2633 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sPcrPid.String(),
2634 B_GENERIC);
2636 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sFrequency.String(),
2637 B_GENERIC);
2638 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sPolarity.String(),
2639 B_GENERIC);
2640 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sSymbolRate.String(),
2641 B_GENERIC);
2642 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInversion.String(),
2643 B_GENERIC);
2644 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sAgcInversion.String(),
2645 B_GENERIC);
2648 return web;
2652 void
2653 DVBMediaNode::LoadSettings()
2655 TRACE("DVBMediaNode::LoadSettings\n");
2656 RefreshStateList();
2657 fSelectedState = 0;
2658 RefreshRegionList();
2659 fSelectedRegion = 0;
2660 RefreshChannelList();
2661 fSelectedChannel = 0;
2662 RefreshAudioList();
2663 fSelectedAudio = 0;
2667 void
2668 DVBMediaNode::RefreshStateList()
2670 TRACE("DVBMediaNode::RefreshStateList\n");
2672 fStateList->MakeEmpty();
2673 fSelectedState = -1;
2675 const char *dir;
2676 switch (fInterfaceType) {
2677 case DVB_TYPE_DVB_C:
2678 dir = "/boot/home/config/settings/Media/dvb/dvb-c channels";
2679 break;
2681 case DVB_TYPE_DVB_H:
2682 dir = "/boot/home/config/settings/Media/dvb/dvb-h channels";
2683 break;
2685 case DVB_TYPE_DVB_S:
2686 dir = "/boot/home/config/settings/Media/dvb/dvb-s channels";
2687 break;
2689 case DVB_TYPE_DVB_T:
2690 dir = "/boot/home/config/settings/Media/dvb/dvb-t channels";
2691 break;
2693 default:
2694 printf("DVBMediaNode::RefreshStateList unknown interface type\n");
2695 return;
2698 TRACE("loading channel lists from dir = %s\n", dir);
2700 BDirectory d(dir);
2701 BEntry e;
2702 BPath p;
2703 while (B_OK == d.GetNextEntry(&e, false)) {
2704 if (B_OK != e.GetPath(&p))
2705 continue;
2706 fStateList->AddItem(p.Path());
2709 if (fStateList->ItemAt(0))
2710 fSelectedState = 0;
2714 void
2715 DVBMediaNode::RefreshRegionList()
2717 TRACE("DVBMediaNode::RefreshRegionList\n");
2719 fRegionList->MakeEmpty();
2720 fSelectedRegion = -1;
2722 const char *dir = fStateList->ItemAt(fSelectedState);
2723 if (!dir)
2724 return;
2726 BDirectory d(dir);
2727 BEntry e;
2728 BPath p;
2729 while (B_OK == d.GetNextEntry(&e, false)) {
2730 if (B_OK != e.GetPath(&p))
2731 continue;
2732 fRegionList->AddItem(p.Path());
2735 if (fRegionList->ItemAt(0))
2736 fSelectedRegion = 0;
2740 void
2741 DVBMediaNode::RefreshChannelList()
2743 TRACE("DVBMediaNode::RefreshChannelList\n");
2745 fChannelList->MakeEmpty();
2746 fSelectedChannel = -1;
2748 const char *path = fRegionList->ItemAt(fSelectedRegion);
2749 if (!path)
2750 return;
2752 TRACE("opening channel list file = %s\n", path);
2754 FILE *f = fopen(path, "r");
2755 if (!f)
2756 return;
2758 char line[1024];
2759 while (fgets(line, sizeof(line), f)) {
2760 if (line[0] == ':') // skip comments
2761 continue;
2762 if (strchr(line, ':') == NULL) // skip empty lines
2763 continue;
2764 fChannelList->AddItem(line);
2767 fclose(f);
2769 if (fChannelList->ItemAt(0))
2770 fSelectedChannel = 0;
2774 void
2775 DVBMediaNode::RefreshAudioList()
2777 TRACE("DVBMediaNode::RefreshAudioList\n");
2779 fAudioList->MakeEmpty();
2780 fSelectedAudio = -1;
2782 fAudioList->AddItem("default"); // XXX test
2784 if (fAudioList->ItemAt(0))
2785 fSelectedAudio = 0;
2789 void
2790 DVBMediaNode::AddStateItems(BDiscreteParameter *param)
2792 TRACE("DVBMediaNode::AddStateItems\n");
2794 const char *str;
2795 for (int i = 0; (str = fStateList->ItemAt(i)); i++) {
2796 str = strrchr(str, '/');
2797 if (!str)
2798 continue;
2799 str++;
2800 param->AddItem(i, str);
2802 if (param->CountItems() == 0)
2803 param->AddItem(-1, "none");
2807 void
2808 DVBMediaNode::AddRegionItems(BDiscreteParameter *param)
2810 TRACE("DVBMediaNode::AddRegionItems\n");
2812 const char *str;
2813 for (int i = 0; (str = fRegionList->ItemAt(i)); i++) {
2814 str = strrchr(str, '/');
2815 if (!str)
2816 continue;
2817 str++;
2818 param->AddItem(i, str);
2820 if (param->CountItems() == 0)
2821 param->AddItem(-1, "none");
2825 void
2826 DVBMediaNode::AddChannelItems(BDiscreteParameter *param)
2828 TRACE("DVBMediaNode::AddChannelItems\n");
2830 const char *str;
2831 for (int i = 0; (str = fChannelList->ItemAt(i)); i++) {
2832 char name[256];
2833 // sscanf(str, "%s:", name);
2834 sscanf(str, "%[^:]", name);
2835 param->AddItem(i, name);
2838 if (param->CountItems() == 0)
2839 param->AddItem(-1, "none");
2843 void
2844 DVBMediaNode::AddAudioItems(BDiscreteParameter *param)
2846 TRACE("DVBMediaNode::AddAudioItems\n");
2848 if (param->CountItems() == 0)
2849 param->AddItem(-1, "default");
2853 status_t
2854 DVBMediaNode::GetParameterValue(int32 id, bigtime_t *last_change, void *value,
2855 size_t *size)
2857 // TRACE("DVBMediaNode::GetParameterValue, id 0x%lx\n", id);
2859 switch (id) {
2860 case ID_STATE:
2861 *size = 4;
2862 *(int32 *)value = fSelectedState;
2863 break;
2865 case ID_REGION:
2866 *size = 4;
2867 *(int32 *)value = fSelectedRegion;
2868 break;
2870 case ID_CHANNEL:
2871 *size = 4;
2872 *(int32 *)value = fSelectedChannel;
2873 break;
2875 case ID_AUDIO:
2876 *size = 4;
2877 *(int32 *)value = fSelectedAudio;
2878 break;
2880 default:
2881 return B_ERROR;
2883 return B_OK;
2887 void
2888 DVBMediaNode::SetParameterValue(int32 id, bigtime_t when, const void *value,
2889 size_t size)
2891 TRACE("DVBMediaNode::SetParameterValue, id 0x%lx, size %ld, value 0x%lx\n",
2892 id, size, *(const int32 *)value);
2894 switch (id) {
2895 case ID_STATE:
2896 fSelectedState = *(const int32 *)value;
2897 StopCapture();
2898 RefreshRegionList();
2899 RefreshChannelList();
2900 RefreshAudioList();
2901 EventQueue()->AddEvent(media_timed_event(0,
2902 M_REFRESH_PARAMETER_WEB));
2903 // Tune();
2904 break;
2906 case ID_REGION:
2907 fSelectedRegion = *(const int32 *)value;
2908 StopCapture();
2909 RefreshChannelList();
2910 RefreshAudioList();
2911 EventQueue()->AddEvent(media_timed_event(0,
2912 M_REFRESH_PARAMETER_WEB));
2913 // Tune();
2914 break;
2916 case ID_CHANNEL:
2917 fSelectedChannel = *(const int32 *)value;
2918 RefreshAudioList();
2919 // EventQueue()->AddEvent(media_timed_event(0,
2920 // M_REFRESH_PARAMETER_WEB));
2921 Tune();
2922 break;
2924 case ID_AUDIO:
2925 fSelectedAudio = *(const int32 *)value;
2926 Tune();
2927 break;
2929 default:
2930 break;
2932 TRACE("DVBMediaNode::SetParameterValue finished\n");
2936 status_t
2937 DVBMediaNode::ExtractTuningParams(const char *description, int audio_pid_index,
2938 dvb_tuning_parameters_t *tuning_param, int *video_pid, int *audio_pid,
2939 int *pcr_pid)
2941 if (!description)
2942 return B_ERROR;
2944 printf("ExtractTuningParams: \"%s\"\n", description);
2946 char name[50];
2947 char freq[50];
2948 char para[100];
2949 char src[50];
2950 char srate[50];
2951 char vpid[50];
2952 char apid[50];
2953 char tpid[50];
2954 char ca[50];
2955 char sid[50];
2956 char nid[50];
2957 char tid[50];
2958 char rid[50];
2960 sscanf(description, " %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:]"
2961 " : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] ", name, freq, para,
2962 src, srate, vpid, apid, tpid, ca, sid, nid, tid, rid);
2964 char *cpid = strchr(vpid, '+');
2965 if (cpid) cpid++;
2967 int _vpid = strtol(vpid, 0, 0);
2968 int _apid = strtol(apid, 0, 0);
2969 // int _tpid = strtol(tpid, 0, 0);
2970 int _cpid = cpid ? strtol(cpid, 0, 0) : _vpid;
2971 int _srate = strtol(srate, 0, 0);
2972 int64 _freq = strtol(freq, 0, 0);
2973 while (_freq && _freq <= 1000000)
2974 _freq *= 1000;
2976 if (fInterfaceType == DVB_TYPE_DVB_S && _freq < 950000000) {
2977 TRACE("workaround activated: type is DVB_S and frequency < 950 MHz,"
2978 " multiplying by 1000!\n");
2979 _freq *= 1000;
2983 *video_pid = _vpid;
2984 *audio_pid = _apid;
2985 *pcr_pid = _cpid;
2987 TRACE("parsing result: params: '%s'\n", para);
2989 TRACE("parsing result: video pid %d\n", _vpid);
2990 TRACE("parsing result: audio pid %d\n", _apid);
2991 TRACE("parsing result: PCR pid %d\n", _cpid);
2992 TRACE("parsing result: symbol rate %d\n", _srate);
2993 TRACE("parsing result: Frequency %Ld Hz, %Ld MHz\n", _freq, _freq / 1000000);
2995 if (fInterfaceType == DVB_TYPE_DVB_T) {
2997 dvb_t_tuning_parameters_t *param = &tuning_param->u.dvb_t;
2999 TRACE("Interface is DVB-T\n");
3000 param->frequency = _freq;
3001 param->inversion = DVB_INVERSION_OFF;
3002 param->bandwidth = DVB_BANDWIDTH_8_MHZ;
3003 param->modulation = DVB_MODULATION_16_QAM;
3004 param->hierarchy = DVB_HIERARCHY_NONE;
3005 param->code_rate_hp = DVB_FEC_2_3;
3006 param->code_rate_lp = DVB_FEC_2_3;
3007 param->transmission_mode = DVB_TRANSMISSION_MODE_8K;
3008 param->guard_interval = DVB_GUARD_INTERVAL_1_4;
3011 if (fInterfaceType == DVB_TYPE_DVB_S) {
3012 dvb_s_tuning_parameters_t *param = &tuning_param->u.dvb_s;
3014 TRACE("Interface is DVB-S\n");
3016 const char *pInv = strchr(para, 'I');
3017 if (pInv == NULL)
3018 pInv = strchr(para, 'i');
3019 if (pInv != NULL && pInv[1] == '0') {
3020 TRACE("DVB_INVERSION_OFF\n");
3021 param->inversion = DVB_INVERSION_OFF;
3022 } else if (pInv != NULL && pInv[1] == '1') {
3023 TRACE("DVB_INVERSION_ON\n");
3024 param->inversion = DVB_INVERSION_ON;
3025 } else {
3026 TRACE("parse error, assuming DVB_INVERSION_OFF\n");
3027 param->inversion = DVB_INVERSION_OFF;
3030 const char *pPolH = strchr(para, 'H');
3031 if (pPolH == NULL)
3032 pPolH = strchr(para, 'h');
3033 const char *pPolV = strchr(para, 'V');
3034 if (pPolV == NULL)
3035 pPolV = strchr(para, 'v');
3036 if (pPolH != NULL && pPolV == NULL) {
3037 TRACE("DVB_POLARITY_HORIZONTAL\n");
3038 param->polarity = DVB_POLARITY_HORIZONTAL;
3039 } else if (pPolH == NULL && pPolV != NULL) {
3040 TRACE("DVB_POLARITY_VERTICAL\n");
3041 param->polarity = DVB_POLARITY_VERTICAL;
3042 } else {
3043 TRACE("parse error, assuming DVB_POLARITY_HORIZONTAL\n");
3044 param->polarity = DVB_POLARITY_HORIZONTAL;
3047 param->frequency = _freq;
3048 param->symbolrate = _srate;
3051 return B_OK;