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.
35 #include <MediaRoster.h>
37 #include <BufferGroup.h>
38 #include <ParameterWeb.h>
39 #include <TimeSource.h>
44 #include <Directory.h>
48 #include "MediaFormat.h"
50 #include "PacketQueue.h"
56 //#define DUMP_RAW_AUDIO
57 //#define DUMP_MPEG_TS
60 #include "DVBMediaNode.h"
63 //#define ENABLE_TRACE_TIMING
73 #ifdef ENABLE_TRACE_TIMING
74 #define TRACE_TIMING printf
76 #define TRACE_TIMING(a...)
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
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
)
116 , BBufferProducer(B_MEDIA_RAW_VIDEO
)
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))
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
)
149 , fTuningSuccess(false)
150 , fCaptureActive(false)
151 , fVideoDelaySem(create_sem(0, "video delay sem"))
152 , fAudioDelaySem(create_sem(0, "audio delay sem"))
154 , fSelectedRegion(-1)
155 , fSelectedChannel(-1)
157 , fStateList(new StringList
)
158 , fRegionList(new StringList
)
159 , fChannelList(new StringList
)
160 , fAudioList(new StringList
)
163 , fCurrentVideoPacket(0)
164 , fCurrentAudioPacket(0)
166 TRACE("DVBMediaNode::DVBMediaNode\n");
168 AddNodeKind(B_PHYSICAL_INPUT
);
170 fInternalID
= internal_id
;
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());
187 fVideoFile
= open("/boot/home/dvb-video.mpg", O_RDWR
| O_CREAT
| O_TRUNC
);
190 fAudioFile
= open("/boot/home/dvb-audio.mpg", O_RDWR
| O_CREAT
| O_TRUNC
);
192 #ifdef DUMP_RAW_AUDIO
193 fRawAudioFile
= open("/boot/home/dvb-audio.raw",
194 O_RDWR
| O_CREAT
| O_TRUNC
);
197 fMpegTsFile
= open("/boot/home/dvb-mpeg.ts", O_RDWR
| O_CREAT
| O_TRUNC
);
202 DVBMediaNode::~DVBMediaNode()
204 TRACE("DVBMediaNode::~DVBMediaNode\n");
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
;
221 delete fBufferGroupRawVideo
;
222 delete fBufferGroupRawAudio
;
235 #ifdef DUMP_RAW_AUDIO
236 close(fRawAudioFile
);
249 DVBMediaNode::AddOn(int32
*internal_id
) const
252 *internal_id
= fInternalID
;
258 DVBMediaNode::HandleMessage(int32 message
, const void *data
, size_t size
)
265 DVBMediaNode::Preroll()
267 /* This hook may be called before the node is started to give the hardware
268 * a chance to start. */
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);
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 */
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
340 RefreshParameterWeb();
342 // this nodes operates in recording mode, so set it (will be done
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);
356 DVBMediaNode::Stop(bigtime_t performance_time
, bool immediate
)
361 BMediaEventLooper::Stop(performance_time
, immediate
);
366 DVBMediaNode::HandleEvent(const media_timed_event
*event
,
367 bigtime_t lateness
, bool realTimeEvent
)
372 case M_REFRESH_PARAMETER_WEB
:
373 RefreshParameterWeb();
375 case BTimedEventQueue::B_START
:
376 HandleStart(event
->event_time
);
378 case BTimedEventQueue::B_STOP
:
381 case BTimedEventQueue::B_WARP
:
382 HandleTimeWarp(event
->bigdata
);
384 case BTimedEventQueue::B_SEEK
:
385 HandleSeek(event
->bigdata
);
387 case BTimedEventQueue::B_HANDLE_BUFFER
:
388 case BTimedEventQueue::B_DATA_STATUS
:
389 case BTimedEventQueue::B_PARAMETER
:
391 TRACE("DVBMediaNode::HandleEvent: Unhandled event -- %lx\n",
398 /* BBufferProducer */
402 DVBMediaNode::FormatChangeRequested(const media_source
&source
,
403 const media_destination
&destination
, media_format
*io_format
,
406 TRACE("DVBMediaNode::FormatChangeRequested denied: %s\n",
407 SourceDefaultName(source
));
413 DVBMediaNode::GetNextOutput(int32
*cookie
, media_output
*out_output
)
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
;
430 DVBMediaNode::DisposeOutputCookie(int32 cookie
)
437 DVBMediaNode::SetBufferGroup(const media_source
&source
, BBufferGroup
*group
)
439 TRACE("DVBMediaNode::SetBufferGroup denied: %s\n",
440 SourceDefaultName(source
));
446 DVBMediaNode::VideoClippingChanged(const media_source
&for_source
,
447 int16 num_shorts
, int16
*clip_data
,
448 const media_video_display_info
&display
, int32
*_deprecated_
)
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
;
467 DVBMediaNode::FormatSuggestionRequested(
468 media_type type
, int32 quality
, media_format
*format
)
470 TRACE("DVBMediaNode::FormatSuggestionRequested\n");
473 case B_MEDIA_RAW_VIDEO
:
474 *format
= fDefaultFormatRawVideo
;
477 case B_MEDIA_RAW_AUDIO
:
478 *format
= fDefaultFormatRawAudio
;
481 case B_MEDIA_ENCODED_VIDEO
:
482 *format
= fDefaultFormatEncVideo
;
485 case B_MEDIA_ENCODED_AUDIO
:
486 *format
= fDefaultFormatEncAudio
;
489 case B_MEDIA_MULTISTREAM
:
490 *format
= fDefaultFormatTS
;
494 TRACE("Bad type!\n");
495 return B_MEDIA_BAD_FORMAT
;
499 TRACE("suggested format: ");
500 PrintFormat(*format
);
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())
531 TRACE("proposed format: ");
532 PrintFormat(*format
);
533 TRACE("required format: ");
536 PrintFormat(fRequiredFormatRawVideo
);
540 PrintFormat(fRequiredFormatRawAudio
);
544 PrintFormat(fRequiredFormatEncVideo
);
548 PrintFormat(fRequiredFormatEncAudio
);
552 PrintFormat(fRequiredFormatTS
);
559 // check if destination still available
560 if (fOutputRawVideo
.destination
!= media_destination::null
)
562 // set requirements and check if compatible
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
))
574 // check if destination still available
575 if (fOutputRawAudio
.destination
!= media_destination::null
)
577 // set requirements and check if compatible
578 format
->SpecializeTo(&fRequiredFormatRawAudio
);
579 if (!format
->Matches(&fRequiredFormatRawAudio
))
581 if (!VerifyFormatRawAudio(format
->u
.raw_audio
))
586 // check if destination still available
587 if (fOutputEncVideo
.destination
!= media_destination::null
)
589 // set requirements and check if compatible
590 format
->SpecializeTo(&fRequiredFormatEncVideo
);
591 if (!format
->Matches(&fRequiredFormatEncVideo
))
596 // check if destination still available
597 if (fOutputEncAudio
.destination
!= media_destination::null
)
599 // set requirements and check if compatible
600 format
->SpecializeTo(&fRequiredFormatEncAudio
);
601 if (!format
->Matches(&fRequiredFormatEncAudio
))
606 // check if destination still available
607 if (fOutputTS
.destination
!= media_destination::null
)
609 // set requirements and check if compatible
610 format
->SpecializeTo(&fRequiredFormatTS
);
611 if (!format
->Matches(&fRequiredFormatTS
))
620 TRACE("final format: ");
621 PrintFormat(*format
);
627 TRACE("Error: bad source!\n");
628 return B_MEDIA_BAD_SOURCE
;
631 TRACE("Error, bad format (1): ");
635 TRACE("Error, bad format (2): ");
640 PrintFormat(*format
);
642 return B_MEDIA_BAD_FORMAT
;
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
));
667 TRACE("connecting format: ");
668 PrintFormat(*format
);
669 TRACE("required format: ");
672 PrintFormat(fRequiredFormatRawVideo
);
676 PrintFormat(fRequiredFormatRawAudio
);
680 PrintFormat(fRequiredFormatEncVideo
);
684 PrintFormat(fRequiredFormatEncAudio
);
688 PrintFormat(fRequiredFormatTS
);
693 // is the source valid?
694 if (source
.port
!= ControlPort())
697 // 1) check if the output is still available,
698 // 2) specialize and verify the format
701 if (fOutputRawVideo
.destination
!= media_destination::null
)
702 goto _already_connected
;
703 SpecializeFormatRawVideo(&format
->u
.raw_video
);
704 // if (!format->Matches(&fRequiredFormatRawVideo))
706 if (!VerifyFormatRawVideo(format
->u
.raw_video
))
711 if (fOutputRawAudio
.destination
!= media_destination::null
)
712 goto _already_connected
;
713 SpecializeFormatRawAudio(&format
->u
.raw_audio
);
714 if (!format
->Matches(&fRequiredFormatRawAudio
))
716 if (!VerifyFormatRawAudio(format
->u
.raw_audio
))
721 if (fOutputEncVideo
.destination
!= media_destination::null
)
722 goto _already_connected
;
723 SpecializeFormatEncVideo(&format
->u
.encoded_video
);
724 if (!format
->Matches(&fRequiredFormatEncVideo
))
729 if (fOutputEncAudio
.destination
!= media_destination::null
)
730 goto _already_connected
;
731 SpecializeFormatEncAudio(&format
->u
.encoded_audio
);
732 if (!format
->Matches(&fRequiredFormatRawVideo
))
737 if (fOutputTS
.destination
!= media_destination::null
)
738 goto _already_connected
;
739 SpecializeFormatTS(&format
->u
.multistream
);
740 if (!format
->Matches(&fRequiredFormatTS
))
749 TRACE("final format: ");
750 PrintFormat(*format
);
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
));
764 TRACE("Error: bad source!\n");
765 return B_MEDIA_BAD_SOURCE
;
769 TRACE("Error, bad format: ");
770 PrintFormat(*format
);
772 return B_MEDIA_BAD_FORMAT
;
775 TRACE("Error: already connected!\n");
776 return B_MEDIA_ALREADY_CONNECTED
;
781 DVBMediaNode::Connect(status_t error
, const media_source
&source
,
782 const media_destination
&destination
, const media_format
&format
,
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
));
796 TRACE("Error during connecting\n");
797 // if an error occured, unreserve the connection
803 TRACE("connected format: ");
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
815 fOutputEnabledRawVideo
= true;
819 fOutputEnabledRawAudio
= true;
823 fOutputEnabledEncVideo
= true;
827 fOutputEnabledEncAudio
= true;
831 fOutputEnabledTS
= true;
838 // if the connection has no name, we set it now
839 if (strlen(io_name
) == 0)
840 strcpy(io_name
, SourceDefaultName(source
));
845 if (B_OK
!= FindLatencyFor(destination
, &latency
, &ts
))
846 TRACE("FindLatencyFor failed\n");
848 TRACE("downstream latency %Ld\n", latency
);
854 DVBMediaNode::Disconnect(const media_source
&source
,
855 const media_destination
&destination
)
857 TRACE("DVBMediaNode::Disconnect: %s\n", SourceDefaultName(source
));
859 // unreserve the connection
862 // Set output to disconnected
865 fOutputEnabledRawVideo
= false;
869 fOutputEnabledRawAudio
= false;
873 fOutputEnabledEncVideo
= false;
877 fOutputEnabledEncAudio
= false;
881 fOutputEnabledTS
= false;
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
,
900 DVBMediaNode::EnableOutput(const media_source
&source
, bool enabled
,
903 TRACE("DVBMediaNode::EnableOutput id = %ld, enabled = %d\n", 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;
919 DVBMediaNode::SetPlayRate(int32 numer
, int32 denom
)
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
));
937 DVBMediaNode::LatencyChanged(const media_source
&source
,
938 const media_destination
&destination
, bigtime_t new_latency
,
941 TRACE("DVBMediaNode::LatencyChanged to %Ld\n", new_latency
);
948 DVBMediaNode::HandleTimeWarp(bigtime_t performance_time
)
950 TRACE("DVBMediaNode::HandleTimeWarp at %Ld\n", performance_time
);
955 DVBMediaNode::HandleSeek(bigtime_t performance_time
)
957 TRACE("DVBMediaNode::HandleSeek at %Ld\n", performance_time
);
962 DVBMediaNode::InitDefaultFormats()
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;
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
;
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
)
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
)
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...
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...
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
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
1076 DVBMediaNode::SpecializeFormatTS(media_multistream_format
*format
)
1078 // Here we need to specialize *all* remaining wildcard
1079 // fields that the consumer didn't set
1084 DVBMediaNode::SetOutput(const media_source
&source
,
1085 const media_destination
&destination
, const media_format
&format
)
1087 switch (source
.id
) {
1089 fOutputRawVideo
.destination
= destination
;
1090 fOutputRawVideo
.format
= format
;
1094 fOutputRawAudio
.destination
= destination
;
1095 fOutputRawAudio
.format
= format
;
1099 fOutputEncVideo
.destination
= destination
;
1100 fOutputEncVideo
.format
= format
;
1104 fOutputEncAudio
.destination
= destination
;
1105 fOutputEncAudio
.format
= format
;
1109 fOutputTS
.destination
= destination
;
1110 fOutputTS
.format
= format
;
1114 return B_MEDIA_BAD_SOURCE
;
1121 DVBMediaNode::ResetOutput(const media_source
&source
)
1123 switch (source
.id
) {
1125 fOutputRawVideo
.destination
= media_destination::null
;
1126 fOutputRawVideo
.format
= fDefaultFormatRawVideo
;
1130 fOutputRawAudio
.destination
= media_destination::null
;
1131 fOutputRawAudio
.format
= fDefaultFormatRawAudio
;
1135 fOutputEncVideo
.destination
= media_destination::null
;
1136 fOutputEncVideo
.format
= fDefaultFormatEncVideo
;
1140 fOutputEncAudio
.destination
= media_destination::null
;
1141 fOutputEncAudio
.format
= fDefaultFormatEncAudio
;
1145 fOutputTS
.destination
= media_destination::null
;
1146 fOutputTS
.format
= fDefaultFormatTS
;
1150 return B_MEDIA_BAD_SOURCE
;
1157 DVBMediaNode::SourceDefaultName(const media_source
&source
)
1159 switch (source
.id
) {
1167 return "encoded video";
1170 return "encoded audio";
1182 DVBMediaNode::HandleStart(bigtime_t performance_time
)
1184 TRACE("DVBMediaNode::HandleStart\n");
1190 DVBMediaNode::HandleStop(void)
1192 TRACE("DVBMediaNode::HandleStop\n");
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
);
1206 bool needs_tuning
= false;
1208 if (fSelectedChannel
< 0 || fSelectedAudio
< 0) {
1209 printf("DVBMediaNode::Tune: invalid tuning info\n");
1218 dvb_tuning_parameters_t new_params
;
1223 desc
= fChannelList
->ItemAt(fSelectedChannel
);
1224 err
= ExtractTuningParams(desc
, fSelectedAudio
, &new_params
,
1225 &new_video_pid
, &new_audio_pid
, &new_pcr_pid
);
1228 printf("DVBMediaNode::Tune: getting tuning info failed\n");
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);
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;
1251 case DVB_TYPE_DVB_S
:
1252 printf("needs_tuning = %d, forcing tuning for DVB-S\n",
1254 needs_tuning
= true;
1258 needs_tuning
= true;
1262 fTuningParam
= new_params
;
1263 fVideoPid
= new_video_pid
;
1264 fAudioPid
= new_audio_pid
;
1265 fPcrPid
= new_pcr_pid
;
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();
1273 printf("Tune: StopCapture failed\n");
1278 #if STOP_CAPTURE_WHILE_TUNING
1279 StopCaptureThreads();
1284 err
= fCard
->SetTuningParameter(fTuningParam
);
1285 fTuningSuccess
= err
== B_OK
;
1288 fDemux
->SetPIDs(fVideoPid
, fAudioPid
, fPcrPid
);
1291 if (fTuningSuccess
) {
1292 fCard
->GetTuningParameter(&fTuningParam
);
1293 err
= StartCapture();
1296 #if STOP_CAPTURE_WHILE_TUNING
1297 StartCaptureThreads();
1302 EventQueue()->AddEvent(media_timed_event(0, M_REFRESH_PARAMETER_WEB
));
1303 // RefreshParameterWeb();
1305 TRACE("DVBMediaNode::Tune finished\n");
1311 DVBMediaNode::StartCapture()
1313 TRACE("DVBMediaNode::StartCapture\n");
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();
1337 DVBMediaNode::StopCapture()
1339 TRACE("DVBMediaNode::StopCapture\n");
1340 if (!fCaptureActive
)
1343 StopCaptureThreads();
1345 fCard
->CaptureStop();
1347 fCaptureActive
= false;
1353 DVBMediaNode::StartCaptureThreads()
1355 TRACE("DVBMediaNode::StartCaptureThreads\n");
1357 if (fCaptureThreadsActive
)
1360 fTerminateThreads
= false;
1362 fThreadIdCardReader
= spawn_thread(_card_reader_thread_
, "DVB card reader",
1364 fThreadIdMpegDemux
= spawn_thread(_mpeg_demux_thread_
, "DVB MPEG demux",
1366 fThreadIdEncAudio
= spawn_thread(_enc_audio_thread_
, "DVB audio streaming",
1368 fThreadIdEncVideo
= spawn_thread(_enc_video_thread_
, "DVB video streaming",
1370 fThreadIdMpegTS
= spawn_thread(_mpeg_ts_thread_
, "DVB MPEG TS streaming",
1372 fThreadIdRawAudio
= spawn_thread(_raw_audio_thread_
, "DVB audio decode",
1374 fThreadIdRawVideo
= spawn_thread(_raw_video_thread_
, "DVB video decode",
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;
1390 DVBMediaNode::StopCaptureThreads()
1392 TRACE("DVBMediaNode::StopCaptureThreads\n");
1394 if (!fCaptureThreadsActive
)
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;
1428 DVBMediaNode::_card_reader_thread_(void *arg
)
1430 static_cast<DVBMediaNode
*>(arg
)->card_reader_thread();
1436 DVBMediaNode::_mpeg_demux_thread_(void *arg
)
1438 static_cast<DVBMediaNode
*>(arg
)->mpeg_demux_thread();
1444 DVBMediaNode::_raw_audio_thread_(void *arg
)
1446 static_cast<DVBMediaNode
*>(arg
)->raw_audio_thread();
1452 DVBMediaNode::_raw_video_thread_(void *arg
)
1454 static_cast<DVBMediaNode
*>(arg
)->raw_video_thread();
1460 DVBMediaNode::_enc_audio_thread_(void *arg
)
1462 static_cast<DVBMediaNode
*>(arg
)->enc_audio_thread();
1468 DVBMediaNode::_enc_video_thread_(void *arg
)
1470 static_cast<DVBMediaNode
*>(arg
)->enc_video_thread();
1476 DVBMediaNode::_mpeg_ts_thread_(void *arg
)
1478 static_cast<DVBMediaNode
*>(arg
)->mpeg_ts_thread();
1484 DVBMediaNode::card_reader_thread()
1486 while (!fTerminateThreads
) {
1491 err
= fCard
->Capture(&data
, &size
, &end_time
);
1493 TRACE("fCard->Capture failed, error %lx (%s)\n", err
,
1498 // TRACE("captured %ld bytes\n", size);
1500 Packet
*packet
= new Packet(data
, size
, end_time
);
1502 err
= fCardDataQueue
->Insert(packet
);
1505 TRACE("fCardDataQueue->Insert failed, error %lx\n", err
);
1513 DVBMediaNode::mpeg_demux_thread()
1515 while (!fTerminateThreads
) {
1518 err
= fCardDataQueue
->Remove(&packet
);
1520 TRACE("fCardDataQueue->Remove failed, error %lx\n", err
);
1524 // packet->TimeStamp() is the end time of the capture
1525 fDemux
->AddData(packet
);
1531 DVBMediaNode::mpeg_ts_thread()
1533 while (!fTerminateThreads
) {
1536 err
= fMpegTsQueue
->Remove(&packet
);
1538 TRACE("fMpegTsQueue->Remove failed, error %lx\n", err
);
1542 // TRACE("mpeg ts packet, size %6ld, start_time %14Ld\n",
1543 // packet->Size(), packet->TimeStamp());
1547 write(fMpegTsFile
, packet
->Data(), packet
->Size());
1557 DVBMediaNode::enc_audio_thread()
1559 while (!fTerminateThreads
) {
1562 err
= fEncAudioQueue
->Remove(&packet
);
1564 TRACE("fEncAudioQueue->Remove failed, error %lx\n", err
);
1567 // TRACE("enc audio packet, size %6ld, start_time %14Ld\n",
1568 // packet->Size(), packet->TimeStamp());
1573 if (B_OK
!= pes_extract(packet
->Data(), packet
->Size(), &data
,
1575 TRACE("audio pes_extract failed\n");
1580 write(fAudioFile
, data
, size
);
1584 if (!fOutputEnabledEncAudio
) {
1589 // send encoded audio buffer
1598 DVBMediaNode::enc_video_thread()
1600 while (!fTerminateThreads
) {
1603 err
= fEncVideoQueue
->Remove(&packet
);
1605 TRACE("fEncVideoQueue->Remove failed, error %lx\n", err
);
1609 // TRACE("enc video packet, size %6ld, start_time %14Ld\n",
1610 // packet->Size(), packet->TimeStamp());
1616 if (B_OK
!= pes_extract(packet
->Data(), packet
->Size(), &data
,
1618 TRACE("video pes_extract failed\n");
1623 write(fVideoFile
, data
, size
);
1627 if (!fOutputEnabledEncVideo
) {
1632 // send encoded video buffer
1640 DVBMediaNode::raw_audio_thread()
1642 media_format format
;
1644 err
= GetStreamFormat(fRawAudioQueue
, &format
);
1646 printf("fAudioDecoder init error %s\n", strerror(err
));
1650 // create decoder interface
1652 fAudioDecoder
= new MediaStreamDecoder(&_GetNextAudioChunk
, this);
1654 err
= fAudioDecoder
->SetInputFormat(format
);
1656 printf("fAudioDecoder SetInputFormat error %s\n", strerror(err
));
1660 TRACE("requested audio decoder format: ");
1661 PrintFormat(fOutputRawAudio
);
1663 media_format fmt
= fOutputRawAudio
.format
;
1664 err
= fAudioDecoder
->SetOutputFormat(&fmt
);
1666 printf("fAudioDecoder SetOutputFormat error %s\n", strerror(err
));
1670 TRACE("final audio decoder format: ");
1673 // change format of connection
1674 if (format_is_compatible(fmt
, fOutputRawAudio
.format
)) {
1675 printf("audio formats are compatible\n");
1676 fOutputRawAudio
.format
= fmt
;
1678 printf("audio formats NOT compatible\n");
1680 err
= ChangeFormat(fOutputRawAudio
.source
,
1681 fOutputRawAudio
.destination
,
1684 printf("format change result %lx (%s)\n", err
, strerror(err
));
1686 fOutputRawAudio
.format
= fmt
;
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
) {
1701 if (!fOutputEnabledRawAudio
) {
1702 fRawAudioQueue
->Flush(40000);
1707 buf
= fBufferGroupRawAudio
->RequestBuffer(
1708 fOutputRawAudio
.format
.u
.raw_audio
.buffer_size
,
1709 AUDIO_BUFFER_REQUEST_TIMEOUT
);
1711 TRACE("audio: request buffer timout\n");
1715 err
= fAudioDecoder
->Decode(buf
->Data(), &frameCount
, &mh
, NULL
);
1718 printf("fAudioDecoder Decode error %s\n", strerror(err
));
1722 #ifdef DUMP_RAW_AUDIO
1724 write(fRawAudioFile
, buf
->Data(), mh
.size_used
);
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
,
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
;
1748 err
= ChangeFormat(fOutputRawAudio
.source
,
1749 fOutputRawAudio
.destination
, &fOutputRawAudio
.format
);
1751 printf("format change result %lx (%s)\n", err
, strerror(err
));
1752 PrintFormat(fOutputRawAudio
.format
);
1755 return; // we are dead!
1759 bigtime_t ts_perf_time
;
1760 bigtime_t ts_sys_time
;
1761 bigtime_t ts_offset
;
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
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",
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",
1793 // printf("audio: decoded packet is %Ldms too early\n", delay / 1000);
1795 delay
-= PROCESSING_LATENCY
;
1797 if (acquire_sem_etc(fAudioDelaySem
, 1, B_RELATIVE_TIMEOUT
, delay
)
1799 printf("audio: delay sem not timed out, dropped packet\n");
1805 TRACE_TIMING("audio playback delay %Ld\n",
1806 start_time
- TimeSource()->Now());
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
;
1815 if (SendBuffer(buf
, fOutputRawAudio
.source
,
1816 fOutputRawAudio
.destination
) != B_OK
) {
1817 TRACE("audio: sending buffer failed\n");
1823 delete fCurrentAudioPacket
;
1824 fCurrentAudioPacket
= 0;
1829 DVBMediaNode::raw_video_thread()
1831 media_format format
;
1833 err
= GetStreamFormat(fRawVideoQueue
, &format
);
1835 printf("fVideoDecoder init error %s\n", strerror(err
));
1839 // create decoder interface
1841 fVideoDecoder
= new MediaStreamDecoder(&_GetNextVideoChunk
, this);
1843 err
= fVideoDecoder
->SetInputFormat(format
);
1845 printf("fVideoDecoder SetInputFormat error %s\n", strerror(err
));
1849 TRACE("requested video decoder format: ");
1850 PrintFormat(fOutputRawVideo
);
1852 media_format fmt
= fOutputRawVideo
.format
;
1853 err
= fVideoDecoder
->SetOutputFormat(&fmt
);
1855 printf("fVideoDecoder SetOutputFormat error %s\n", strerror(err
));
1859 TRACE("final video decoder format: ");
1862 // change format of connection
1863 if (format_is_compatible(fmt
, fOutputRawVideo
.format
)) {
1864 printf("video formats are compatible\n");
1865 fOutputRawVideo
.format
= fmt
;
1867 printf("video formats NOT compatible\n");
1869 err
= ChangeFormat(fOutputRawVideo
.source
,
1870 fOutputRawVideo
.destination
,
1873 printf("format change result %lx (%s)\n", err
, strerror(err
));
1875 fOutputRawVideo
.format
= fmt
;
1877 printf("video format change failed\n");
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
) {
1896 if (!fOutputEnabledRawVideo
) {
1897 fRawVideoQueue
->Flush(40000);
1901 // fetch a new buffer (always of maximum size as the stream may change)
1903 buf
= fBufferGroupRawVideo
->RequestBuffer(video_buffer_size_max
,
1904 VIDEO_BUFFER_REQUEST_TIMEOUT
);
1906 TRACE("video: request buffer timout\n");
1910 // decode one video frame into buffer
1911 err
= fVideoDecoder
->Decode(buf
->Data(), &frameCount
, &mh
, NULL
);
1914 printf("fVideoDecoder Decode error %s\n", strerror(err
));
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
,
1949 // recalculate 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;
1968 err
= ChangeFormat(fOutputRawVideo
.source
,
1969 fOutputRawVideo
.destination
, &fOutputRawVideo
.format
);
1971 printf("format change result %lx (%s)\n", err
, strerror(err
));
1972 PrintFormat(fOutputRawVideo
.format
);
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
;
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
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",
2003 if (delay
> VIDEO_MAX_EARLY
) {
2004 printf("video: decoded packet is %Ldms too early, dropped\n",
2009 delay
-= PROCESSING_LATENCY
;
2011 if (acquire_sem_etc(fVideoDelaySem
, 1, B_RELATIVE_TIMEOUT
, delay
)
2013 printf("video: delay sem not timed out, dropped packet\n");
2019 TRACE_TIMING("video playback delay %Ld\n", start_time
2020 - TimeSource()->Now());
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
;
2029 if (SendBuffer(buf
, fOutputRawVideo
.source
,
2030 fOutputRawVideo
.destination
) != B_OK
) {
2031 TRACE("video: sending buffer failed\n");
2037 delete fCurrentVideoPacket
;
2038 fCurrentVideoPacket
= 0;
2043 DVBMediaNode::GetNextVideoChunk(const void **chunkData
, size_t *chunkLen
,
2046 // TRACE("DVBMediaNode::GetNextVideoChunk\n");
2048 delete fCurrentVideoPacket
;
2051 err
= fRawVideoQueue
->Remove(&fCurrentVideoPacket
);
2053 TRACE("fRawVideoQueue->Remove failed, error %lx\n", err
);
2054 fCurrentVideoPacket
= 0;
2061 if (B_OK
!= pes_extract(fCurrentVideoPacket
->Data(),
2062 fCurrentVideoPacket
->Size(), &data
, &size
)) {
2063 TRACE("video pes_extract failed\n");
2069 // measured in PCR time base
2070 mh
->start_time
= fCurrentVideoPacket
->TimeStamp();
2077 DVBMediaNode::GetNextAudioChunk(const void **chunkData
, size_t *chunkLen
,
2080 // TRACE("DVBMediaNode::GetNextAudioChunk\n");
2082 delete fCurrentAudioPacket
;
2085 err
= fRawAudioQueue
->Remove(&fCurrentAudioPacket
);
2087 TRACE("fRawAudioQueue->Remove failed, error %lx\n", err
);
2088 fCurrentAudioPacket
= 0;
2095 if (B_OK
!= pes_extract(fCurrentAudioPacket
->Data(),
2096 fCurrentAudioPacket
->Size(), &data
, &size
)) {
2097 TRACE("audio pes_extract failed\n");
2103 // measured in PCR time base
2104 mh
->start_time
= fCurrentAudioPacket
->TimeStamp();
2106 // printf("GetNextAudioChunk: done start_time %Ld\n", mh->start_time);
2113 DVBMediaNode::_GetNextVideoChunk(const void **chunkData
, size_t *chunkLen
,
2114 media_header
*mh
, void *cookie
)
2116 return static_cast<DVBMediaNode
*>(cookie
)->GetNextVideoChunk(chunkData
,
2122 DVBMediaNode::_GetNextAudioChunk(const void **chunkData
, size_t *chunkLen
,
2123 media_header
*mh
, void *cookie
)
2125 return static_cast<DVBMediaNode
*>(cookie
)->GetNextAudioChunk(chunkData
,
2131 DVBMediaNode::GetStreamFormat(PacketQueue
*queue
, media_format
*format
)
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
);
2145 status
= pes_extract(packet
->Data(), packet
->Size(), &data
, &size
);
2146 if (status
!= B_OK
) {
2147 TRACE("pes_extract failed\n");
2150 status
= pes_stream_id(packet
->Data(), packet
->Size(), &stream_id
);
2151 if (status
!= B_OK
) {
2152 TRACE("pes_stream_id failed\n");
2155 status
= GetHeaderFormat(format
, data
, size
, stream_id
);
2156 if (status
!= B_OK
) {
2157 TRACE("GetHeaderFormat failed, error %lx\n", status
);
2176 DVBMediaNode::RefreshParameterWeb()
2178 TRACE("DVBMediaNode::RefreshParameterWeb enter\n");
2179 fWeb
= CreateParameterWeb();
2180 SetParameterWeb(fWeb
);
2181 TRACE("DVBMediaNode::RefreshParameterWeb finished\n");
2186 DVBMediaNode::SetAboutInfo(BParameterGroup
*about
)
2188 about
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, "DVB media_addon info:",
2190 about
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, "Version " VERSION
,
2192 about
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, "Revision " REVISION
,
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
);
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
);
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
));
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
);
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",
2260 info
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, "or tuning failed.",
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";
2296 case DVB_TYPE_DVB_H
:
2297 sInterfaceType
<< "DVB-H";
2300 case DVB_TYPE_DVB_S
:
2301 sInterfaceType
<< "DVB-S";
2304 case DVB_TYPE_DVB_T
:
2305 sInterfaceType
<< "DVB-T";
2309 sInterfaceType
<< "unknown";
2313 sAudioPid
<< fAudioPid
;
2314 sVideoPid
<< fVideoPid
;
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";
2326 case DVB_INVERSION_ON
:
2330 case DVB_INVERSION_OFF
:
2331 sInversion
<< "off";
2335 sInversion
<< "unknown";
2339 switch (fTuningParam
.u
.dvb_t
.bandwidth
) {
2340 case DVB_BANDWIDTH_AUTO
:
2341 sBandwidth
<< "auto";
2344 case DVB_BANDWIDTH_6_MHZ
:
2345 sBandwidth
<< "6 MHz";
2348 case DVB_BANDWIDTH_7_MHZ
:
2349 sBandwidth
<< "7 MHz";
2352 case DVB_BANDWIDTH_8_MHZ
:
2353 sBandwidth
<< "8 MHz";
2357 sBandwidth
<< "unknown";
2361 switch (fTuningParam
.u
.dvb_t
.modulation
) {
2362 case DVB_MODULATION_AUTO
:
2363 sModulation
<< "auto";
2366 case DVB_MODULATION_QPSK
:
2367 sModulation
<< "QPSK";
2370 case DVB_MODULATION_16_QAM
:
2371 sModulation
<< "16 QAM";
2374 case DVB_MODULATION_32_QAM
:
2375 sModulation
<< "32 QAM";
2378 case DVB_MODULATION_64_QAM
:
2379 sModulation
<< "64 QAM";
2382 case DVB_MODULATION_128_QAM
:
2383 sModulation
<< "128 QAM";
2386 case DVB_MODULATION_256_QAM
:
2387 sModulation
<< "256 QAM";
2391 sModulation
<< "unknown";
2395 switch (fTuningParam
.u
.dvb_t
.hierarchy
) {
2396 case DVB_HIERARCHY_AUTO
:
2397 sHierarchy
<< "auto";
2400 case DVB_HIERARCHY_NONE
:
2401 sHierarchy
<< "none";
2404 case DVB_HIERARCHY_1
:
2408 case DVB_HIERARCHY_2
:
2412 case DVB_HIERARCHY_4
:
2417 sHierarchy
<< "unknown";
2421 switch (fTuningParam
.u
.dvb_t
.code_rate_hp
) {
2423 sCodeRateHP
<< "auto";
2427 sCodeRateHP
<< "none";
2431 sCodeRateHP
<< "FEC 1/2";
2435 sCodeRateHP
<< "FEC 2/3";
2439 sCodeRateHP
<< "FEC 3/4";
2443 sCodeRateHP
<< "FEC 4/5";
2447 sCodeRateHP
<< "FEC 5/6";
2451 sCodeRateHP
<< "FEC 6/7";
2455 sCodeRateHP
<< "FEC 7/8";
2459 sCodeRateHP
<< "FEC 8/9";
2463 sCodeRateHP
<< "unknown";
2467 switch (fTuningParam
.u
.dvb_t
.code_rate_lp
) {
2469 sCodeRateLP
<< "auto";
2473 sCodeRateLP
<< "none";
2477 sCodeRateLP
<< "FEC 1/2";
2481 sCodeRateLP
<< "FEC 2/3";
2485 sCodeRateLP
<< "FEC 3/4";
2489 sCodeRateLP
<< "FEC 4/5";
2493 sCodeRateLP
<< "FEC 5/6";
2497 sCodeRateLP
<< "FEC 6/7";
2501 sCodeRateLP
<< "FEC 7/8";
2505 sCodeRateLP
<< "FEC 8/9";
2509 sCodeRateLP
<< "unknown";
2513 switch (fTuningParam
.u
.dvb_t
.transmission_mode
) {
2514 case DVB_TRANSMISSION_MODE_AUTO
:
2515 sTransmissionMode
<< "auto";
2518 case DVB_TRANSMISSION_MODE_2K
:
2519 sTransmissionMode
<< "2K";
2522 case DVB_TRANSMISSION_MODE_4K
:
2523 sTransmissionMode
<< "4K";
2526 case DVB_TRANSMISSION_MODE_8K
:
2527 sTransmissionMode
<< "8K";
2531 sTransmissionMode
<< "unknown";
2535 switch (fTuningParam
.u
.dvb_t
.guard_interval
) {
2536 case DVB_GUARD_INTERVAL_AUTO
:
2537 sGuardInterval
<< "auto";
2540 case DVB_GUARD_INTERVAL_1_4
:
2541 sGuardInterval
<< "1/4";
2544 case DVB_GUARD_INTERVAL_1_8
:
2545 sGuardInterval
<< "1/8";
2548 case DVB_GUARD_INTERVAL_1_16
:
2549 sGuardInterval
<< "1/16";
2552 case DVB_GUARD_INTERVAL_1_32
:
2553 sGuardInterval
<< "1/32";
2557 sGuardInterval
<< "unknown";
2561 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sInterfaceType
.String(),
2563 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sFrequency
.String(),
2565 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sBandwidth
.String(),
2567 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sVideoPid
.String(),
2569 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sAudioPid
.String(),
2571 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sPcrPid
.String(),
2574 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sModulation
.String(),
2576 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
,
2577 sTransmissionMode
.String(), B_GENERIC
);
2578 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sGuardInterval
.String(),
2580 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sCodeRateHP
.String(),
2582 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sCodeRateLP
.String(),
2584 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sInversion
.String(),
2586 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sHierarchy
.String(),
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";
2600 case DVB_INVERSION_ON
:
2604 case DVB_INVERSION_OFF
:
2605 sInversion
<< "off";
2609 sInversion
<< "unknown";
2613 switch (fTuningParam
.u
.dvb_s
.polarity
) {
2614 case DVB_POLARITY_VERTICAL
:
2615 sPolarity
<< "vertical";
2618 case DVB_POLARITY_HORIZONTAL
:
2619 sPolarity
<< "horizontal";
2623 sPolarity
<< "unknown";
2627 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sInterfaceType
.String(),
2629 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sVideoPid
.String(),
2631 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sAudioPid
.String(),
2633 info1
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sPcrPid
.String(),
2636 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sFrequency
.String(),
2638 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sPolarity
.String(),
2640 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sSymbolRate
.String(),
2642 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sInversion
.String(),
2644 info2
->MakeNullParameter(0, B_MEDIA_NO_TYPE
, sAgcInversion
.String(),
2653 DVBMediaNode::LoadSettings()
2655 TRACE("DVBMediaNode::LoadSettings\n");
2658 RefreshRegionList();
2659 fSelectedRegion
= 0;
2660 RefreshChannelList();
2661 fSelectedChannel
= 0;
2668 DVBMediaNode::RefreshStateList()
2670 TRACE("DVBMediaNode::RefreshStateList\n");
2672 fStateList
->MakeEmpty();
2673 fSelectedState
= -1;
2676 switch (fInterfaceType
) {
2677 case DVB_TYPE_DVB_C
:
2678 dir
= "/boot/home/config/settings/Media/dvb/dvb-c channels";
2681 case DVB_TYPE_DVB_H
:
2682 dir
= "/boot/home/config/settings/Media/dvb/dvb-h channels";
2685 case DVB_TYPE_DVB_S
:
2686 dir
= "/boot/home/config/settings/Media/dvb/dvb-s channels";
2689 case DVB_TYPE_DVB_T
:
2690 dir
= "/boot/home/config/settings/Media/dvb/dvb-t channels";
2694 printf("DVBMediaNode::RefreshStateList unknown interface type\n");
2698 TRACE("loading channel lists from dir = %s\n", dir
);
2703 while (B_OK
== d
.GetNextEntry(&e
, false)) {
2704 if (B_OK
!= e
.GetPath(&p
))
2706 fStateList
->AddItem(p
.Path());
2709 if (fStateList
->ItemAt(0))
2715 DVBMediaNode::RefreshRegionList()
2717 TRACE("DVBMediaNode::RefreshRegionList\n");
2719 fRegionList
->MakeEmpty();
2720 fSelectedRegion
= -1;
2722 const char *dir
= fStateList
->ItemAt(fSelectedState
);
2729 while (B_OK
== d
.GetNextEntry(&e
, false)) {
2730 if (B_OK
!= e
.GetPath(&p
))
2732 fRegionList
->AddItem(p
.Path());
2735 if (fRegionList
->ItemAt(0))
2736 fSelectedRegion
= 0;
2741 DVBMediaNode::RefreshChannelList()
2743 TRACE("DVBMediaNode::RefreshChannelList\n");
2745 fChannelList
->MakeEmpty();
2746 fSelectedChannel
= -1;
2748 const char *path
= fRegionList
->ItemAt(fSelectedRegion
);
2752 TRACE("opening channel list file = %s\n", path
);
2754 FILE *f
= fopen(path
, "r");
2759 while (fgets(line
, sizeof(line
), f
)) {
2760 if (line
[0] == ':') // skip comments
2762 if (strchr(line
, ':') == NULL
) // skip empty lines
2764 fChannelList
->AddItem(line
);
2769 if (fChannelList
->ItemAt(0))
2770 fSelectedChannel
= 0;
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))
2790 DVBMediaNode::AddStateItems(BDiscreteParameter
*param
)
2792 TRACE("DVBMediaNode::AddStateItems\n");
2795 for (int i
= 0; (str
= fStateList
->ItemAt(i
)); i
++) {
2796 str
= strrchr(str
, '/');
2800 param
->AddItem(i
, str
);
2802 if (param
->CountItems() == 0)
2803 param
->AddItem(-1, "none");
2808 DVBMediaNode::AddRegionItems(BDiscreteParameter
*param
)
2810 TRACE("DVBMediaNode::AddRegionItems\n");
2813 for (int i
= 0; (str
= fRegionList
->ItemAt(i
)); i
++) {
2814 str
= strrchr(str
, '/');
2818 param
->AddItem(i
, str
);
2820 if (param
->CountItems() == 0)
2821 param
->AddItem(-1, "none");
2826 DVBMediaNode::AddChannelItems(BDiscreteParameter
*param
)
2828 TRACE("DVBMediaNode::AddChannelItems\n");
2831 for (int i
= 0; (str
= fChannelList
->ItemAt(i
)); i
++) {
2833 // sscanf(str, "%s:", name);
2834 sscanf(str
, "%[^:]", name
);
2835 param
->AddItem(i
, name
);
2838 if (param
->CountItems() == 0)
2839 param
->AddItem(-1, "none");
2844 DVBMediaNode::AddAudioItems(BDiscreteParameter
*param
)
2846 TRACE("DVBMediaNode::AddAudioItems\n");
2848 if (param
->CountItems() == 0)
2849 param
->AddItem(-1, "default");
2854 DVBMediaNode::GetParameterValue(int32 id
, bigtime_t
*last_change
, void *value
,
2857 // TRACE("DVBMediaNode::GetParameterValue, id 0x%lx\n", id);
2862 *(int32
*)value
= fSelectedState
;
2867 *(int32
*)value
= fSelectedRegion
;
2872 *(int32
*)value
= fSelectedChannel
;
2877 *(int32
*)value
= fSelectedAudio
;
2888 DVBMediaNode::SetParameterValue(int32 id
, bigtime_t when
, const void *value
,
2891 TRACE("DVBMediaNode::SetParameterValue, id 0x%lx, size %ld, value 0x%lx\n",
2892 id
, size
, *(const int32
*)value
);
2896 fSelectedState
= *(const int32
*)value
;
2898 RefreshRegionList();
2899 RefreshChannelList();
2901 EventQueue()->AddEvent(media_timed_event(0,
2902 M_REFRESH_PARAMETER_WEB
));
2907 fSelectedRegion
= *(const int32
*)value
;
2909 RefreshChannelList();
2911 EventQueue()->AddEvent(media_timed_event(0,
2912 M_REFRESH_PARAMETER_WEB
));
2917 fSelectedChannel
= *(const int32
*)value
;
2919 // EventQueue()->AddEvent(media_timed_event(0,
2920 // M_REFRESH_PARAMETER_WEB));
2925 fSelectedAudio
= *(const int32
*)value
;
2932 TRACE("DVBMediaNode::SetParameterValue finished\n");
2937 DVBMediaNode::ExtractTuningParams(const char *description
, int audio_pid_index
,
2938 dvb_tuning_parameters_t
*tuning_param
, int *video_pid
, int *audio_pid
,
2944 printf("ExtractTuningParams: \"%s\"\n", description
);
2960 sscanf(description
, " %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:]"
2961 " : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] ", name
, freq
, para
,
2962 src
, srate
, vpid
, apid
, tpid
, ca
, sid
, nid
, tid
, rid
);
2964 char *cpid
= strchr(vpid
, '+');
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)
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");
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');
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
;
3026 TRACE("parse error, assuming DVB_INVERSION_OFF\n");
3027 param
->inversion
= DVB_INVERSION_OFF
;
3030 const char *pPolH
= strchr(para
, 'H');
3032 pPolH
= strchr(para
, 'h');
3033 const char *pPolV
= strchr(para
, 'V');
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
;
3043 TRACE("parse error, assuming DVB_POLARITY_HORIZONTAL\n");
3044 param
->polarity
= DVB_POLARITY_HORIZONTAL
;
3047 param
->frequency
= _freq
;
3048 param
->symbolrate
= _srate
;