1 /* 2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de> 3 * 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: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 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. 23 */ 24 25 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> 34 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> 43 44 #include <Directory.h> 45 #include <Entry.h> 46 #include <Path.h> 47 48 #include "MediaFormat.h" 49 #include "Packet.h" 50 #include "PacketQueue.h" 51 #include "pes.h" 52 #include "config.h" 53 54 //#define DUMP_VIDEO 55 //#define DUMP_AUDIO 56 //#define DUMP_RAW_AUDIO 57 //#define DUMP_MPEG_TS 58 59 60 #include "DVBMediaNode.h" 61 62 #define ENABLE_TRACE 63 //#define ENABLE_TRACE_TIMING 64 65 #undef TRACE 66 67 #ifdef ENABLE_TRACE 68 #define TRACE printf 69 #else 70 #define TRACE(a...) 71 #endif 72 73 #ifdef ENABLE_TRACE_TIMING 74 #define TRACE_TIMING printf 75 #else 76 #define TRACE_TIMING(a...) 77 #endif 78 79 #define RETURN_IF_ERROR(expr) { status_t e = (expr); if (e != B_OK) return e; } 80 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 86 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 92 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 103 104 #define PROCESSING_LATENCY 1500 105 // assumed latency for sending the buffer 106 107 #define STOP_CAPTURE_WHILE_TUNING 1 108 109 #define M_REFRESH_PARAMETER_WEB (BTimedEventQueue::B_USER_EVENT + 1) 110 111 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) 165 { 166 TRACE("DVBMediaNode::DVBMediaNode\n"); 167 168 AddNodeKind(B_PHYSICAL_INPUT); 169 170 fInternalID = internal_id; 171 fAddOn = addon; 172 173 fInitStatus = B_OK; 174 175 InitDefaultFormats(); 176 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; 183 184 // start the BMediaEventLooper control loop running 185 Run(); 186 187 TRACE("current RunMode = %d\n", RunMode()); 188 189 #ifdef DUMP_VIDEO 190 fVideoFile = open("/boot/home/dvb-video.mpg", O_RDWR | O_CREAT | O_TRUNC); 191 #endif 192 #ifdef DUMP_AUDIO 193 fAudioFile = open("/boot/home/dvb-audio.mpg", O_RDWR | O_CREAT | O_TRUNC); 194 #endif 195 #ifdef DUMP_RAW_AUDIO 196 fRawAudioFile = open("/boot/home/dvb-audio.raw", 197 O_RDWR | O_CREAT | O_TRUNC); 198 #endif 199 #ifdef DUMP_MPEG_TS 200 fMpegTsFile = open("/boot/home/dvb-mpeg.ts", O_RDWR | O_CREAT | O_TRUNC); 201 #endif 202 } 203 204 205 DVBMediaNode::~DVBMediaNode() 206 { 207 TRACE("DVBMediaNode::~DVBMediaNode\n"); 208 209 StopCapture(); 210 211 delete_sem(fVideoDelaySem); 212 delete_sem(fAudioDelaySem); 213 214 // fCard is owned by the media addon 215 delete fCardDataQueue; 216 delete fRawVideoQueue; 217 delete fRawAudioQueue; 218 delete fEncVideoQueue; 219 delete fEncAudioQueue; 220 delete fMpegTsQueue; 221 222 delete fDemux; 223 224 delete fBufferGroupRawVideo; 225 delete fBufferGroupRawAudio; 226 227 delete fStateList; 228 delete fRegionList; 229 delete fChannelList; 230 delete fAudioList; 231 232 #ifdef DUMP_VIDEO 233 close(fVideoFile); 234 #endif 235 #ifdef DUMP_AUDIO 236 close(fAudioFile); 237 #endif 238 #ifdef DUMP_RAW_AUDIO 239 close(fRawAudioFile); 240 #endif 241 #ifdef DUMP_MPEG_TS 242 close(fMpegTsFile); 243 #endif 244 245 } 246 247 248 /* BMediaNode */ 249 250 251 BMediaAddOn * 252 DVBMediaNode::AddOn(int32 *internal_id) const 253 { 254 if (internal_id) 255 *internal_id = fInternalID; 256 return fAddOn; 257 } 258 259 260 status_t 261 DVBMediaNode::HandleMessage(int32 message, const void *data, size_t size) 262 { 263 return B_ERROR; 264 } 265 266 267 void 268 DVBMediaNode::Preroll() 269 { 270 /* This hook may be called before the node is started to give the hardware 271 * a chance to start. */ 272 } 273 274 275 void 276 DVBMediaNode::SetTimeSource(BTimeSource *time_source) 277 { 278 TRACE("DVBMediaNode::SetTimeSource\n"); 279 //printf("current RunMode = %d\n", RunMode()); 280 //printf("_m_recordDelay = %Ld\n", _m_recordDelay); 281 } 282 283 284 void 285 DVBMediaNode::SetRunMode(run_mode mode) 286 { 287 TRACE("DVBMediaNode::SetRunMode: %d\n", mode); 288 TRACE("current RunMode = %d\n", RunMode()); 289 //printf("_m_recordDelay = %Ld\n", _m_recordDelay); 290 } 291 292 293 /* BMediaEventLooper */ 294 295 296 void 297 DVBMediaNode::NodeRegistered() 298 { 299 TRACE("DVBMediaNode::NodeRegistered\n"); 300 301 fOutputRawVideo.node = Node(); 302 fOutputRawVideo.source.port = ControlPort(); 303 fOutputRawVideo.source.id = ID_RAW_VIDEO; 304 fOutputRawVideo.destination = media_destination::null; 305 fOutputRawVideo.format = fDefaultFormatRawVideo; 306 strcpy(fOutputRawVideo.name, SourceDefaultName(fOutputRawVideo.source)); 307 308 fOutputRawAudio.node = Node(); 309 fOutputRawAudio.source.port = ControlPort(); 310 fOutputRawAudio.source.id = ID_RAW_AUDIO; 311 fOutputRawAudio.destination = media_destination::null; 312 fOutputRawAudio.format = fDefaultFormatRawAudio; 313 strcpy(fOutputRawAudio.name, SourceDefaultName(fOutputRawAudio.source)); 314 315 fOutputEncVideo.node = Node(); 316 fOutputEncVideo.source.port = ControlPort(); 317 fOutputEncVideo.source.id = ID_ENC_VIDEO; 318 fOutputEncVideo.destination = media_destination::null; 319 fOutputEncVideo.format = fDefaultFormatEncVideo; 320 strcpy(fOutputEncVideo.name, SourceDefaultName(fOutputEncVideo.source)); 321 322 fOutputEncAudio.node = Node(); 323 fOutputEncAudio.source.port = ControlPort(); 324 fOutputEncAudio.source.id = ID_ENC_AUDIO; 325 fOutputEncAudio.destination = media_destination::null; 326 fOutputEncAudio.format = fDefaultFormatEncAudio; 327 strcpy(fOutputEncAudio.name, SourceDefaultName(fOutputEncAudio.source)); 328 329 fOutputTS.node = Node(); 330 fOutputTS.source.port = ControlPort(); 331 fOutputTS.source.id = ID_TS; 332 fOutputTS.destination = media_destination::null; 333 fOutputTS.format = fDefaultFormatTS; 334 strcpy(fOutputTS.name, SourceDefaultName(fOutputTS.source)); 335 336 fCard->GetCardType(&fInterfaceType); 337 338 // set control thread priority 339 SetPriority(110); 340 341 LoadSettings(); 342 343 RefreshParameterWeb(); 344 345 // this nodes operates in recording mode, so set it (will be done 346 // asynchronously) 347 BMediaRoster::Roster()->SetRunModeNode(Node(), B_RECORDING); 348 // as it's a notification hook, calling this doesn't work: 349 // SetRunMode(B_RECORDING); 350 351 //printf("RunMode = %d\n", RunMode()); 352 //printf("_m_recordDelay = %Ld\n", _m_recordDelay); 353 } 354 355 356 void 357 DVBMediaNode::Stop(bigtime_t performance_time, bool immediate) 358 { 359 if (fStopDisabled) 360 return; 361 else 362 BMediaEventLooper::Stop(performance_time, immediate); 363 } 364 365 366 void 367 DVBMediaNode::HandleEvent(const media_timed_event *event, 368 bigtime_t lateness, bool realTimeEvent) 369 { 370 371 switch(event->type) 372 { 373 case M_REFRESH_PARAMETER_WEB: 374 RefreshParameterWeb(); 375 break; 376 case BTimedEventQueue::B_START: 377 HandleStart(event->event_time); 378 break; 379 case BTimedEventQueue::B_STOP: 380 HandleStop(); 381 break; 382 case BTimedEventQueue::B_WARP: 383 HandleTimeWarp(event->bigdata); 384 break; 385 case BTimedEventQueue::B_SEEK: 386 HandleSeek(event->bigdata); 387 break; 388 case BTimedEventQueue::B_HANDLE_BUFFER: 389 case BTimedEventQueue::B_DATA_STATUS: 390 case BTimedEventQueue::B_PARAMETER: 391 default: 392 TRACE("DVBMediaNode::HandleEvent: Unhandled event -- %lx\n", 393 event->type); 394 break; 395 } 396 } 397 398 399 /* BBufferProducer */ 400 401 402 status_t 403 DVBMediaNode::FormatChangeRequested(const media_source &source, 404 const media_destination &destination, media_format *io_format, 405 int32 *_deprecated_) 406 { 407 TRACE("DVBMediaNode::FormatChangeRequested denied: %s\n", 408 SourceDefaultName(source)); 409 return B_ERROR; 410 } 411 412 413 status_t 414 DVBMediaNode::GetNextOutput(int32 *cookie, media_output *out_output) 415 { 416 switch (*cookie) { 417 case 0: *out_output = fOutputRawVideo; break; 418 case 1: *out_output = fOutputRawAudio; break; 419 case 2: *out_output = fOutputEncVideo; break; 420 case 3: *out_output = fOutputEncAudio; break; 421 case 4: *out_output = fOutputTS; break; 422 default: return B_BAD_INDEX; 423 } 424 425 (*cookie) += 1; 426 return B_OK; 427 } 428 429 430 status_t 431 DVBMediaNode::DisposeOutputCookie(int32 cookie) 432 { 433 return B_OK; 434 } 435 436 437 status_t 438 DVBMediaNode::SetBufferGroup(const media_source &source, BBufferGroup *group) 439 { 440 TRACE("DVBMediaNode::SetBufferGroup denied: %s\n", 441 SourceDefaultName(source)); 442 return B_ERROR; 443 } 444 445 446 status_t 447 DVBMediaNode::VideoClippingChanged(const media_source &for_source, 448 int16 num_shorts, int16 *clip_data, 449 const media_video_display_info &display, int32 *_deprecated_) 450 { 451 return B_ERROR; 452 } 453 454 455 status_t 456 DVBMediaNode::GetLatency(bigtime_t *out_latency) 457 { 458 if (B_OK != BBufferProducer::GetLatency(out_latency)) 459 *out_latency = 50000; 460 461 printf("DVBMediaNode::GetLatency: %Ld\n", *out_latency); 462 *out_latency += PROCESSING_LATENCY; 463 return B_OK; 464 } 465 466 467 status_t 468 DVBMediaNode::FormatSuggestionRequested( 469 media_type type, int32 quality, media_format *format) 470 { 471 TRACE("DVBMediaNode::FormatSuggestionRequested\n"); 472 473 switch (type) { 474 case B_MEDIA_RAW_VIDEO: 475 *format = fDefaultFormatRawVideo; 476 break; 477 478 case B_MEDIA_RAW_AUDIO: 479 *format = fDefaultFormatRawAudio; 480 break; 481 482 case B_MEDIA_ENCODED_VIDEO: 483 *format = fDefaultFormatEncVideo; 484 break; 485 486 case B_MEDIA_ENCODED_AUDIO: 487 *format = fDefaultFormatEncAudio; 488 break; 489 490 case B_MEDIA_MULTISTREAM: 491 *format = fDefaultFormatTS; 492 break; 493 494 default: 495 TRACE("Bad type!\n"); 496 return B_MEDIA_BAD_FORMAT; 497 } 498 499 #ifdef DEBUG 500 TRACE("suggested format: "); 501 PrintFormat(*format); 502 #endif 503 504 return B_OK; 505 } 506 507 508 status_t 509 DVBMediaNode::FormatProposal(const media_source &source, media_format *format) 510 { 511 TRACE("DVBMediaNode::FormatProposal: %s\n", SourceDefaultName(source)); 512 513 /* The connection process: 514 * we are here => BBufferProducer::FormatProposal 515 * BBufferConsumer::AcceptFormat 516 * BBufferProducer::PrepareToConnect 517 * BBufferConsumer::Connected 518 * BBufferProducer::Connect 519 * 520 * What we need to do: 521 * - if the format contains a wildcard AND we have a requirement for that 522 * field, set it to the value we need. 523 * - if a field has a value that is not wildcard and not supported by us, 524 * we don't change it, and return B_MEDIA_BAD_FORMAT 525 * - after we are done, the format may still contain wildcards. 526 */ 527 528 if (source.port != ControlPort()) 529 goto _bad_source; 530 531 #ifdef DEBUG 532 TRACE("proposed format: "); 533 PrintFormat(*format); 534 TRACE("required format: "); 535 switch (source.id) { 536 case ID_RAW_VIDEO: 537 PrintFormat(fRequiredFormatRawVideo); 538 break; 539 540 case ID_RAW_AUDIO: 541 PrintFormat(fRequiredFormatRawAudio); 542 break; 543 544 case ID_ENC_VIDEO: 545 PrintFormat(fRequiredFormatEncVideo); 546 break; 547 548 case ID_ENC_AUDIO: 549 PrintFormat(fRequiredFormatEncAudio); 550 break; 551 552 case ID_TS: 553 PrintFormat(fRequiredFormatTS); 554 break; 555 } 556 #endif 557 558 switch (source.id) { 559 case ID_RAW_VIDEO: 560 // check if destination still available 561 if (fOutputRawVideo.destination != media_destination::null) 562 goto _bad_source; 563 // set requirements and check if compatible 564 color_space c; 565 c = format->u.raw_video.display.format; 566 format->SpecializeTo(&fRequiredFormatRawVideo); 567 format->u.raw_video.display.format = c; 568 // if (!format->Matches(&fRequiredFormatRawVideo)) 569 // goto _bad_format_1; 570 if (!VerifyFormatRawVideo(format->u.raw_video)) 571 goto _bad_format_2; 572 break; 573 574 case ID_RAW_AUDIO: 575 // check if destination still available 576 if (fOutputRawAudio.destination != media_destination::null) 577 goto _bad_source; 578 // set requirements and check if compatible 579 format->SpecializeTo(&fRequiredFormatRawAudio); 580 if (!format->Matches(&fRequiredFormatRawAudio)) 581 goto _bad_format_1; 582 if (!VerifyFormatRawAudio(format->u.raw_audio)) 583 goto _bad_format_2; 584 break; 585 586 case ID_ENC_VIDEO: 587 // check if destination still available 588 if (fOutputEncVideo.destination != media_destination::null) 589 goto _bad_source; 590 // set requirements and check if compatible 591 format->SpecializeTo(&fRequiredFormatEncVideo); 592 if (!format->Matches(&fRequiredFormatEncVideo)) 593 goto _bad_format_1; 594 break; 595 596 case ID_ENC_AUDIO: 597 // check if destination still available 598 if (fOutputEncAudio.destination != media_destination::null) 599 goto _bad_source; 600 // set requirements and check if compatible 601 format->SpecializeTo(&fRequiredFormatEncAudio); 602 if (!format->Matches(&fRequiredFormatEncAudio)) 603 goto _bad_format_1; 604 break; 605 606 case ID_TS: 607 // check if destination still available 608 if (fOutputTS.destination != media_destination::null) 609 goto _bad_source; 610 // set requirements and check if compatible 611 format->SpecializeTo(&fRequiredFormatTS); 612 if (!format->Matches(&fRequiredFormatTS)) 613 goto _bad_format_1; 614 break; 615 616 default: 617 goto _bad_source; 618 } 619 620 #ifdef DEBUG 621 TRACE("final format: "); 622 PrintFormat(*format); 623 #endif 624 625 return B_OK; 626 627 _bad_source: 628 TRACE("Error: bad source!\n"); 629 return B_MEDIA_BAD_SOURCE; 630 631 _bad_format_1: 632 TRACE("Error, bad format (1): "); 633 goto _bad_format; 634 635 _bad_format_2: 636 TRACE("Error, bad format (2): "); 637 goto _bad_format; 638 639 _bad_format: 640 #ifdef DEBUG 641 PrintFormat(*format); 642 #endif 643 return B_MEDIA_BAD_FORMAT; 644 } 645 646 647 status_t 648 DVBMediaNode::PrepareToConnect(const media_source &source, 649 const media_destination &destination, media_format *format, 650 media_source *out_source, char *out_name) 651 { 652 /* The connection process: 653 * BBufferProducer::FormatProposal 654 * BBufferConsumer::AcceptFormat 655 * we are here => BBufferProducer::PrepareToConnect 656 * BBufferConsumer::Connected 657 * BBufferProducer::Connect 658 * 659 * At this point, the consumer's AcceptFormat() method has been called, 660 * and that node has potentially changed the proposed format. It may 661 * also have left wildcards in the format. PrepareToConnect() 662 * *must* fully specialize the format before returning! 663 */ 664 665 TRACE("DVBMediaNode::PrepareToConnect: %s\n", SourceDefaultName(source)); 666 667 #ifdef DEBUG 668 TRACE("connecting format: "); 669 PrintFormat(*format); 670 TRACE("required format: "); 671 switch (source.id) { 672 case ID_RAW_VIDEO: 673 PrintFormat(fRequiredFormatRawVideo); 674 break; 675 676 case ID_RAW_AUDIO: 677 PrintFormat(fRequiredFormatRawAudio); 678 break; 679 680 case ID_ENC_VIDEO: 681 PrintFormat(fRequiredFormatEncVideo); 682 break; 683 684 case ID_ENC_AUDIO: 685 PrintFormat(fRequiredFormatEncAudio); 686 break; 687 688 case ID_TS: 689 PrintFormat(fRequiredFormatTS); 690 break; 691 } 692 #endif 693 694 // is the source valid? 695 if (source.port != ControlPort()) 696 goto _bad_source; 697 698 // 1) check if the output is still available, 699 // 2) specialize and verify the format 700 switch (source.id) { 701 case ID_RAW_VIDEO: 702 if (fOutputRawVideo.destination != media_destination::null) 703 goto _already_connected; 704 SpecializeFormatRawVideo(&format->u.raw_video); 705 // if (!format->Matches(&fRequiredFormatRawVideo)) 706 // goto _bad_format; 707 if (!VerifyFormatRawVideo(format->u.raw_video)) 708 goto _bad_format; 709 break; 710 711 case ID_RAW_AUDIO: 712 if (fOutputRawAudio.destination != media_destination::null) 713 goto _already_connected; 714 SpecializeFormatRawAudio(&format->u.raw_audio); 715 if (!format->Matches(&fRequiredFormatRawAudio)) 716 goto _bad_format; 717 if (!VerifyFormatRawAudio(format->u.raw_audio)) 718 goto _bad_format; 719 break; 720 721 case ID_ENC_VIDEO: 722 if (fOutputEncVideo.destination != media_destination::null) 723 goto _already_connected; 724 SpecializeFormatEncVideo(&format->u.encoded_video); 725 if (!format->Matches(&fRequiredFormatEncVideo)) 726 goto _bad_format; 727 break; 728 729 case ID_ENC_AUDIO: 730 if (fOutputEncAudio.destination != media_destination::null) 731 goto _already_connected; 732 SpecializeFormatEncAudio(&format->u.encoded_audio); 733 if (!format->Matches(&fRequiredFormatRawVideo)) 734 goto _bad_format; 735 break; 736 737 case ID_TS: 738 if (fOutputTS.destination != media_destination::null) 739 goto _already_connected; 740 SpecializeFormatTS(&format->u.multistream); 741 if (!format->Matches(&fRequiredFormatTS)) 742 goto _bad_format; 743 break; 744 745 default: 746 goto _bad_source; 747 } 748 749 #ifdef DEBUG 750 TRACE("final format: "); 751 PrintFormat(*format); 752 #endif 753 754 // reserve the connection by setting destination 755 // set the output's format to the new format 756 SetOutput(source, destination, *format); 757 758 // set source and suggest a name 759 *out_source = source; 760 strcpy(out_name, SourceDefaultName(source)); 761 762 return B_OK; 763 764 _bad_source: 765 TRACE("Error: bad source!\n"); 766 return B_MEDIA_BAD_SOURCE; 767 768 _bad_format: 769 #ifdef DEBUG 770 TRACE("Error, bad format: "); 771 PrintFormat(*format); 772 #endif 773 return B_MEDIA_BAD_FORMAT; 774 775 _already_connected: 776 TRACE("Error: already connected!\n"); 777 return B_MEDIA_ALREADY_CONNECTED; 778 } 779 780 781 void 782 DVBMediaNode::Connect(status_t error, const media_source &source, 783 const media_destination &destination, const media_format &format, 784 char *io_name) 785 { 786 /* The connection process: 787 * BBufferProducer::FormatProposal 788 * BBufferConsumer::AcceptFormat 789 * BBufferProducer::PrepareToConnect 790 * BBufferConsumer::Connected 791 * we are here => BBufferProducer::Connect 792 */ 793 794 TRACE("DVBMediaNode::Connect: %s\n", SourceDefaultName(source)); 795 796 if (error != B_OK) { 797 TRACE("Error during connecting\n"); 798 // if an error occured, unreserve the connection 799 ResetOutput(source); 800 return; 801 } 802 803 #ifdef DEBUG 804 TRACE("connected format: "); 805 PrintFormat(format); 806 #endif 807 808 // Since the destination is allowed to be changed by the 809 // consumer, the one we got in PrepareToConnect() is no 810 // longer correct, and must be updated here. 811 SetOutput(source, destination, format); 812 813 // Set output as connected 814 switch (source.id) { 815 case ID_RAW_VIDEO: 816 fOutputEnabledRawVideo = true; 817 break; 818 819 case ID_RAW_AUDIO: 820 fOutputEnabledRawAudio = true; 821 break; 822 823 case ID_ENC_VIDEO: 824 fOutputEnabledEncVideo = true; 825 break; 826 827 case ID_ENC_AUDIO: 828 fOutputEnabledEncAudio = true; 829 break; 830 831 case ID_TS: 832 fOutputEnabledTS = true; 833 break; 834 835 default: 836 break; 837 } 838 839 // if the connection has no name, we set it now 840 if (strlen(io_name) == 0) 841 strcpy(io_name, SourceDefaultName(source)); 842 843 #ifdef DEBUG 844 bigtime_t latency; 845 media_node_id ts; 846 if (B_OK != FindLatencyFor(destination, &latency, &ts)) 847 TRACE("FindLatencyFor failed\n"); 848 else 849 TRACE("downstream latency %Ld\n", latency); 850 #endif 851 } 852 853 854 void 855 DVBMediaNode::Disconnect(const media_source &source, 856 const media_destination &destination) 857 { 858 TRACE("DVBMediaNode::Disconnect: %s\n", SourceDefaultName(source)); 859 860 // unreserve the connection 861 ResetOutput(source); 862 863 // Set output to disconnected 864 switch (source.id) { 865 case ID_RAW_VIDEO: 866 fOutputEnabledRawVideo = false; 867 break; 868 869 case ID_RAW_AUDIO: 870 fOutputEnabledRawAudio = false; 871 break; 872 873 case ID_ENC_VIDEO: 874 fOutputEnabledEncVideo = false; 875 break; 876 877 case ID_ENC_AUDIO: 878 fOutputEnabledEncAudio = false; 879 break; 880 881 case ID_TS: 882 fOutputEnabledTS = false; 883 break; 884 885 default: 886 break; 887 } 888 } 889 890 891 void 892 DVBMediaNode::LateNoticeReceived(const media_source &source, 893 bigtime_t how_much, bigtime_t performance_time) 894 { 895 TRACE("DVBMediaNode::LateNoticeReceived %Ld late at %Ld\n", how_much, 896 performance_time); 897 } 898 899 900 void 901 DVBMediaNode::EnableOutput(const media_source &source, bool enabled, 902 int32 *_deprecated_) 903 { 904 TRACE("DVBMediaNode::EnableOutput id = %ld, enabled = %d\n", source.id, 905 enabled); 906 /* not used yet 907 switch (source.id) { 908 case ID_RAW_VIDEO: fOutputEnabledRawVideo = enabled; break; 909 case ID_RAW_AUDIO: fOutputEnabledRawAudio = enabled; break; 910 case ID_ENC_VIDEO: fOutputEnabledEncVideo = enabled; break; 911 case ID_ENC_AUDIO: fOutputEnabledEncAudio = enabled; break; 912 case ID_TS: fOutputEnabledTS = enabled; break; 913 default: break; 914 } 915 */ 916 } 917 918 919 status_t 920 DVBMediaNode::SetPlayRate(int32 numer, int32 denom) 921 { 922 923 return B_ERROR; 924 } 925 926 927 void 928 DVBMediaNode::AdditionalBufferRequested(const media_source &source, 929 media_buffer_id prev_buffer, bigtime_t prev_time, 930 const media_seek_tag *prev_tag) 931 { 932 TRACE("DVBMediaNode::AdditionalBufferRequested: %s\n", 933 SourceDefaultName(source)); 934 } 935 936 937 void 938 DVBMediaNode::LatencyChanged(const media_source &source, 939 const media_destination &destination, bigtime_t new_latency, 940 uint32 flags) 941 { 942 TRACE("DVBMediaNode::LatencyChanged to %Ld\n", new_latency); 943 } 944 945 /* DVBMediaNode */ 946 947 948 void 949 DVBMediaNode::HandleTimeWarp(bigtime_t performance_time) 950 { 951 TRACE("DVBMediaNode::HandleTimeWarp at %Ld\n", performance_time); 952 } 953 954 955 void 956 DVBMediaNode::HandleSeek(bigtime_t performance_time) 957 { 958 TRACE("DVBMediaNode::HandleSeek at %Ld\n", performance_time); 959 } 960 961 962 void 963 DVBMediaNode::InitDefaultFormats() 964 { 965 // 720 * 576 966 fDefaultFormatRawVideo.type = B_MEDIA_RAW_VIDEO; 967 fDefaultFormatRawVideo.u.raw_video.display.format = B_RGB32; 968 fDefaultFormatRawVideo.u.raw_video.display.line_width = 720; 969 fDefaultFormatRawVideo.u.raw_video.display.line_count = 576; 970 fDefaultFormatRawVideo.u.raw_video.last_active 971 = fDefaultFormatRawVideo.u.raw_video.display.line_count - 1; 972 fDefaultFormatRawVideo.u.raw_video.display.bytes_per_row 973 = fDefaultFormatRawVideo.u.raw_video.display.line_width * 4; 974 fDefaultFormatRawVideo.u.raw_video.field_rate = 0; 975 // wildcard 976 fDefaultFormatRawVideo.u.raw_video.interlace = 1; 977 fDefaultFormatRawVideo.u.raw_video.first_active = 0; 978 fDefaultFormatRawVideo.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT; 979 fDefaultFormatRawVideo.u.raw_video.pixel_width_aspect = 1; 980 fDefaultFormatRawVideo.u.raw_video.pixel_height_aspect = 1; 981 fDefaultFormatRawVideo.u.raw_video.display.pixel_offset = 0; 982 fDefaultFormatRawVideo.u.raw_video.display.line_offset = 0; 983 fDefaultFormatRawVideo.u.raw_video.display.flags = 0; 984 985 fDefaultFormatRawAudio.type = B_MEDIA_RAW_AUDIO; 986 fDefaultFormatRawAudio.u.raw_audio.frame_rate = 48000; 987 fDefaultFormatRawAudio.u.raw_audio.channel_count = 2; 988 // XXX broken in Haiku... 989 // fDefaultFormatRawAudio.u.raw_audio.format = 0; // wildcard 990 fDefaultFormatRawAudio.u.raw_audio.format 991 = media_raw_audio_format::B_AUDIO_SHORT; 992 // when set to 0, haiku mixer has problems when diung a format change 993 // set to short and debug the buffer_size problem first! 994 fDefaultFormatRawAudio.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; 995 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 0; // wildcard 996 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 0x1200; 997 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 0x1000; 998 fDefaultFormatRawAudio.u.raw_audio.buffer_size = 32768; 999 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 333 * 8; 1000 // fDefaultFormatRawAudio.u.raw_audio.buffer_size = 512; 1001 // when set to anything different from 32768 haiku mixer has problems 1002 1003 fDefaultFormatEncVideo.type = B_MEDIA_ENCODED_VIDEO; 1004 fDefaultFormatEncAudio.type = B_MEDIA_ENCODED_AUDIO; 1005 fDefaultFormatTS.type = B_MEDIA_MULTISTREAM; 1006 } 1007 1008 1009 bool 1010 DVBMediaNode::VerifyFormatRawVideo(const media_raw_video_format &format) 1011 { 1012 if (format.display.format != 0 && 1013 format.display.format != B_RGB32 && 1014 format.display.format != B_YCbCr422) 1015 return false; 1016 1017 return true; 1018 } 1019 1020 1021 bool 1022 DVBMediaNode::VerifyFormatRawAudio(const media_multi_audio_format &format) 1023 { 1024 if (format.format != 0 && 1025 format.format != media_raw_audio_format::B_AUDIO_FLOAT && 1026 format.format != media_raw_audio_format::B_AUDIO_SHORT) 1027 return false; 1028 1029 return true; 1030 } 1031 1032 1033 void 1034 DVBMediaNode::SpecializeFormatRawVideo(media_raw_video_format *format) 1035 { 1036 // Here we need to specialize *all* remaining wildcard 1037 // fields that the consumer didn't set 1038 if (format->field_rate == 0.0) 1039 format->field_rate = 25; 1040 1041 // XXX a lot is missing here... 1042 } 1043 1044 1045 void 1046 DVBMediaNode::SpecializeFormatRawAudio(media_multi_audio_format *format) 1047 { 1048 // Here we need to specialize *all* remaining wildcard 1049 // fields that the consumer didn't set 1050 if (format->format == 0) 1051 format->format = media_raw_audio_format::B_AUDIO_SHORT; 1052 1053 if (format->buffer_size == 0) 1054 format->buffer_size = 333 * 8; 1055 1056 // XXX a lot is missing here... 1057 } 1058 1059 1060 void 1061 DVBMediaNode::SpecializeFormatEncVideo(media_encoded_video_format *format) 1062 { 1063 // Here we need to specialize *all* remaining wildcard 1064 // fields that the consumer didn't set 1065 } 1066 1067 1068 void 1069 DVBMediaNode::SpecializeFormatEncAudio(media_encoded_audio_format *format) 1070 { 1071 // Here we need to specialize *all* remaining wildcard 1072 // fields that the consumer didn't set 1073 } 1074 1075 1076 void 1077 DVBMediaNode::SpecializeFormatTS(media_multistream_format *format) 1078 { 1079 // Here we need to specialize *all* remaining wildcard 1080 // fields that the consumer didn't set 1081 } 1082 1083 1084 status_t 1085 DVBMediaNode::SetOutput(const media_source &source, 1086 const media_destination &destination, const media_format &format) 1087 { 1088 switch (source.id) { 1089 case ID_RAW_VIDEO: 1090 fOutputRawVideo.destination = destination; 1091 fOutputRawVideo.format = format; 1092 break; 1093 1094 case ID_RAW_AUDIO: 1095 fOutputRawAudio.destination = destination; 1096 fOutputRawAudio.format = format; 1097 break; 1098 1099 case ID_ENC_VIDEO: 1100 fOutputEncVideo.destination = destination; 1101 fOutputEncVideo.format = format; 1102 break; 1103 1104 case ID_ENC_AUDIO: 1105 fOutputEncAudio.destination = destination; 1106 fOutputEncAudio.format = format; 1107 break; 1108 1109 case ID_TS: 1110 fOutputTS.destination = destination; 1111 fOutputTS.format = format; 1112 break; 1113 1114 default: 1115 return B_MEDIA_BAD_SOURCE; 1116 } 1117 return B_OK; 1118 } 1119 1120 1121 status_t 1122 DVBMediaNode::ResetOutput(const media_source &source) 1123 { 1124 switch (source.id) { 1125 case ID_RAW_VIDEO: 1126 fOutputRawVideo.destination = media_destination::null; 1127 fOutputRawVideo.format = fDefaultFormatRawVideo; 1128 break; 1129 1130 case ID_RAW_AUDIO: 1131 fOutputRawAudio.destination = media_destination::null; 1132 fOutputRawAudio.format = fDefaultFormatRawAudio; 1133 break; 1134 1135 case ID_ENC_VIDEO: 1136 fOutputEncVideo.destination = media_destination::null; 1137 fOutputEncVideo.format = fDefaultFormatEncVideo; 1138 break; 1139 1140 case ID_ENC_AUDIO: 1141 fOutputEncAudio.destination = media_destination::null; 1142 fOutputEncAudio.format = fDefaultFormatEncAudio; 1143 break; 1144 1145 case ID_TS: 1146 fOutputTS.destination = media_destination::null; 1147 fOutputTS.format = fDefaultFormatTS; 1148 break; 1149 1150 default: 1151 return B_MEDIA_BAD_SOURCE; 1152 } 1153 return B_OK; 1154 } 1155 1156 1157 const char * 1158 DVBMediaNode::SourceDefaultName(const media_source &source) 1159 { 1160 switch (source.id) { 1161 case ID_RAW_VIDEO: 1162 return "raw video"; 1163 1164 case ID_RAW_AUDIO: 1165 return "raw audio"; 1166 1167 case ID_ENC_VIDEO: 1168 return "encoded video"; 1169 1170 case ID_ENC_AUDIO: 1171 return "encoded audio"; 1172 1173 case ID_TS: 1174 return "MPEG2 TS"; 1175 1176 default: 1177 return NULL; 1178 } 1179 } 1180 1181 1182 void 1183 DVBMediaNode::HandleStart(bigtime_t performance_time) 1184 { 1185 TRACE("DVBMediaNode::HandleStart\n"); 1186 StartCapture(); 1187 } 1188 1189 1190 void 1191 DVBMediaNode::HandleStop(void) 1192 { 1193 TRACE("DVBMediaNode::HandleStop\n"); 1194 StopCapture(); 1195 } 1196 1197 1198 status_t 1199 DVBMediaNode::Tune() 1200 { 1201 TRACE("DVBMediaNode::Tune enter\n"); 1202 1203 TRACE("state %d, region %d, channel %d, audio %d\n", 1204 fSelectedState, fSelectedRegion, fSelectedChannel, fSelectedAudio); 1205 1206 status_t err; 1207 bool needs_tuning = false; 1208 1209 if (fSelectedChannel < 0 || fSelectedAudio < 0) { 1210 printf("DVBMediaNode::Tune: invalid tuning info\n"); 1211 StopCapture(); 1212 err = B_ERROR; 1213 goto end; 1214 // return B_ERROR; 1215 } 1216 1217 const char *desc; 1218 1219 dvb_tuning_parameters_t new_params; 1220 int new_video_pid; 1221 int new_audio_pid; 1222 int new_pcr_pid; 1223 1224 desc = fChannelList->ItemAt(fSelectedChannel); 1225 err = ExtractTuningParams(desc, fSelectedAudio, &new_params, 1226 &new_video_pid, &new_audio_pid, &new_pcr_pid); 1227 1228 if (err != B_OK) { 1229 printf("DVBMediaNode::Tune: getting tuning info failed\n"); 1230 StopCapture(); 1231 err = B_ERROR; 1232 goto end; 1233 // return B_ERROR; 1234 } 1235 /* 1236 if (fTuningParam.frequency == new_params.frequency) { 1237 printf("DVBMediaNode::Tune: frequency not changed\n"); 1238 fVideoPid = new_video_pid; 1239 fAudioPid = new_audio_pid; 1240 fPcrPid = new_pcr_pid; 1241 fDemux->SetPIDs(fVideoPid, fAudioPid, fPcrPid); 1242 return B_OK; 1243 } 1244 */ 1245 switch (fInterfaceType) { 1246 case DVB_TYPE_DVB_T: 1247 needs_tuning = (fTuningParam.u.dvb_t.frequency 1248 != new_params.u.dvb_t.frequency) || !fTuningSuccess; 1249 needs_tuning = true; 1250 break; 1251 1252 case DVB_TYPE_DVB_S: 1253 printf("needs_tuning = %d, forcing tuning for DVB-S\n", 1254 needs_tuning); 1255 needs_tuning = true; 1256 break; 1257 1258 default: 1259 needs_tuning = true; 1260 break; 1261 } 1262 1263 fTuningParam = new_params; 1264 fVideoPid = new_video_pid; 1265 fAudioPid = new_audio_pid; 1266 fPcrPid = new_pcr_pid; 1267 1268 if (needs_tuning) { 1269 printf("about to stop capture 1\n"); 1270 #if STOP_CAPTURE_WHILE_TUNING 1271 printf("about to stop capture 2\n"); 1272 err = StopCapture(); 1273 if (err) { 1274 printf("Tune: StopCapture failed\n"); 1275 goto end; 1276 } 1277 #endif 1278 } else { 1279 #if STOP_CAPTURE_WHILE_TUNING 1280 StopCaptureThreads(); 1281 #endif 1282 } 1283 1284 if (needs_tuning) { 1285 err = fCard->SetTuningParameter(fTuningParam); 1286 fTuningSuccess = err == B_OK; 1287 } 1288 1289 fDemux->SetPIDs(fVideoPid, fAudioPid, fPcrPid); 1290 1291 if (needs_tuning) { 1292 if (fTuningSuccess) { 1293 fCard->GetTuningParameter(&fTuningParam); 1294 err = StartCapture(); 1295 } 1296 } else { 1297 #if STOP_CAPTURE_WHILE_TUNING 1298 StartCaptureThreads(); 1299 #endif 1300 } 1301 1302 end: 1303 EventQueue()->AddEvent(media_timed_event(0, M_REFRESH_PARAMETER_WEB)); 1304 // RefreshParameterWeb(); 1305 1306 TRACE("DVBMediaNode::Tune finished\n"); 1307 return err; 1308 } 1309 1310 1311 status_t 1312 DVBMediaNode::StartCapture() 1313 { 1314 TRACE("DVBMediaNode::StartCapture\n"); 1315 1316 if (fCaptureActive) 1317 return B_OK; 1318 1319 RETURN_IF_ERROR(StopCaptureThreads()); 1320 1321 if (!fTuningSuccess) { 1322 RETURN_IF_ERROR(Tune()); 1323 } 1324 1325 RETURN_IF_ERROR(StartCaptureThreads()); 1326 1327 fCard->CaptureStart(); 1328 1329 fCaptureActive = true; 1330 1331 RefreshParameterWeb(); 1332 1333 return B_OK; 1334 } 1335 1336 1337 status_t 1338 DVBMediaNode::StopCapture() 1339 { 1340 TRACE("DVBMediaNode::StopCapture\n"); 1341 if (!fCaptureActive) 1342 return B_OK; 1343 1344 StopCaptureThreads(); 1345 1346 fCard->CaptureStop(); 1347 1348 fCaptureActive = false; 1349 return B_OK; 1350 } 1351 1352 1353 status_t 1354 DVBMediaNode::StartCaptureThreads() 1355 { 1356 TRACE("DVBMediaNode::StartCaptureThreads\n"); 1357 1358 if (fCaptureThreadsActive) 1359 return B_OK; 1360 1361 fTerminateThreads = false; 1362 1363 fThreadIdCardReader = spawn_thread(_card_reader_thread_, "DVB card reader", 1364 120, this); 1365 fThreadIdMpegDemux = spawn_thread(_mpeg_demux_thread_, "DVB MPEG demux", 1366 110, this); 1367 fThreadIdEncAudio = spawn_thread(_enc_audio_thread_, "DVB audio streaming", 1368 110, this); 1369 fThreadIdEncVideo = spawn_thread(_enc_video_thread_, "DVB video streaming", 1370 110, this); 1371 fThreadIdMpegTS = spawn_thread(_mpeg_ts_thread_, "DVB MPEG TS streaming", 1372 110, this); 1373 fThreadIdRawAudio = spawn_thread(_raw_audio_thread_, "DVB audio decode", 1374 100, this); 1375 fThreadIdRawVideo = spawn_thread(_raw_video_thread_, "DVB video decode", 1376 85, this); 1377 resume_thread(fThreadIdCardReader); 1378 resume_thread(fThreadIdMpegDemux); 1379 resume_thread(fThreadIdEncAudio); 1380 resume_thread(fThreadIdEncVideo); 1381 resume_thread(fThreadIdMpegTS); 1382 resume_thread(fThreadIdRawAudio); 1383 resume_thread(fThreadIdRawVideo); 1384 1385 fCaptureThreadsActive = true; 1386 return B_OK; 1387 } 1388 1389 1390 status_t 1391 DVBMediaNode::StopCaptureThreads() 1392 { 1393 TRACE("DVBMediaNode::StopCaptureThreads\n"); 1394 1395 if (!fCaptureThreadsActive) 1396 return B_OK; 1397 1398 fTerminateThreads = true; 1399 1400 fCardDataQueue->Terminate(); 1401 fEncVideoQueue->Terminate(); 1402 fEncAudioQueue->Terminate(); 1403 fMpegTsQueue->Terminate(); 1404 fRawVideoQueue->Terminate(); 1405 fRawAudioQueue->Terminate(); 1406 1407 status_t dummy; // NULL as parameter does not work 1408 wait_for_thread(fThreadIdCardReader, &dummy); 1409 wait_for_thread(fThreadIdMpegDemux, &dummy); 1410 wait_for_thread(fThreadIdEncAudio, &dummy); 1411 wait_for_thread(fThreadIdEncVideo, &dummy); 1412 wait_for_thread(fThreadIdMpegTS, &dummy); 1413 wait_for_thread(fThreadIdRawAudio, &dummy); 1414 wait_for_thread(fThreadIdRawVideo, &dummy); 1415 1416 fCardDataQueue->Restart(); 1417 fEncVideoQueue->Restart(); 1418 fEncAudioQueue->Restart(); 1419 fMpegTsQueue->Restart(); 1420 fRawVideoQueue->Restart(); 1421 fRawAudioQueue->Restart(); 1422 1423 fCaptureThreadsActive = false; 1424 return B_OK; 1425 } 1426 1427 1428 int32 1429 DVBMediaNode::_card_reader_thread_(void *arg) 1430 { 1431 static_cast<DVBMediaNode *>(arg)->card_reader_thread(); 1432 return 0; 1433 } 1434 1435 1436 int32 1437 DVBMediaNode::_mpeg_demux_thread_(void *arg) 1438 { 1439 static_cast<DVBMediaNode *>(arg)->mpeg_demux_thread(); 1440 return 0; 1441 } 1442 1443 1444 int32 1445 DVBMediaNode::_raw_audio_thread_(void *arg) 1446 { 1447 static_cast<DVBMediaNode *>(arg)->raw_audio_thread(); 1448 return 0; 1449 } 1450 1451 1452 int32 1453 DVBMediaNode::_raw_video_thread_(void *arg) 1454 { 1455 static_cast<DVBMediaNode *>(arg)->raw_video_thread(); 1456 return 0; 1457 } 1458 1459 1460 int32 1461 DVBMediaNode::_enc_audio_thread_(void *arg) 1462 { 1463 static_cast<DVBMediaNode *>(arg)->enc_audio_thread(); 1464 return 0; 1465 } 1466 1467 1468 int32 1469 DVBMediaNode::_enc_video_thread_(void *arg) 1470 { 1471 static_cast<DVBMediaNode *>(arg)->enc_video_thread(); 1472 return 0; 1473 } 1474 1475 1476 int32 1477 DVBMediaNode::_mpeg_ts_thread_(void *arg) 1478 { 1479 static_cast<DVBMediaNode *>(arg)->mpeg_ts_thread(); 1480 return 0; 1481 } 1482 1483 1484 void 1485 DVBMediaNode::card_reader_thread() 1486 { 1487 while (!fTerminateThreads) { 1488 void *data; 1489 size_t size; 1490 status_t err; 1491 bigtime_t end_time; 1492 err = fCard->Capture(&data, &size, &end_time); 1493 if (err != B_OK) { 1494 TRACE("fCard->Capture failed, error %lx (%s)\n", err, 1495 strerror(err)); 1496 continue; 1497 } 1498 1499 // TRACE("captured %ld bytes\n", size); 1500 1501 Packet *packet = new Packet(data, size, end_time); 1502 1503 err = fCardDataQueue->Insert(packet); 1504 if (err != B_OK) { 1505 delete packet; 1506 TRACE("fCardDataQueue->Insert failed, error %lx\n", err); 1507 continue; 1508 } 1509 } 1510 } 1511 1512 1513 void 1514 DVBMediaNode::mpeg_demux_thread() 1515 { 1516 while (!fTerminateThreads) { 1517 status_t err; 1518 Packet *packet; 1519 err = fCardDataQueue->Remove(&packet); 1520 if (err != B_OK) { 1521 TRACE("fCardDataQueue->Remove failed, error %lx\n", err); 1522 continue; 1523 } 1524 1525 // packet->TimeStamp() is the end time of the capture 1526 fDemux->AddData(packet); 1527 } 1528 } 1529 1530 1531 void 1532 DVBMediaNode::mpeg_ts_thread() 1533 { 1534 while (!fTerminateThreads) { 1535 status_t err; 1536 Packet *packet; 1537 err = fMpegTsQueue->Remove(&packet); 1538 if (err != B_OK) { 1539 TRACE("fMpegTsQueue->Remove failed, error %lx\n", err); 1540 continue; 1541 } 1542 1543 // TRACE("mpeg ts packet, size %6ld, start_time %14Ld\n", 1544 // packet->Size(), packet->TimeStamp()); 1545 1546 #ifdef DUMP_MPEG_TS 1547 lock.Lock(); 1548 write(fMpegTsFile, packet->Data(), packet->Size()); 1549 lock.Unlock(); 1550 #endif 1551 1552 delete packet; 1553 } 1554 } 1555 1556 1557 void 1558 DVBMediaNode::enc_audio_thread() 1559 { 1560 while (!fTerminateThreads) { 1561 status_t err; 1562 Packet *packet; 1563 err = fEncAudioQueue->Remove(&packet); 1564 if (err != B_OK) { 1565 TRACE("fEncAudioQueue->Remove failed, error %lx\n", err); 1566 continue; 1567 } 1568 // TRACE("enc audio packet, size %6ld, start_time %14Ld\n", 1569 // packet->Size(), packet->TimeStamp()); 1570 1571 #ifdef DUMP_AUDIO 1572 const uint8 *data; 1573 size_t size; 1574 if (B_OK != pes_extract(packet->Data(), packet->Size(), &data, 1575 &size)) { 1576 TRACE("audio pes_extract failed\n"); 1577 delete packet; 1578 return; 1579 } 1580 lock.Lock(); 1581 write(fAudioFile, data, size); 1582 lock.Unlock(); 1583 #endif 1584 1585 if (!fOutputEnabledEncAudio) { 1586 delete packet; 1587 continue; 1588 } 1589 1590 // send encoded audio buffer 1591 1592 1593 delete packet; 1594 } 1595 } 1596 1597 1598 void 1599 DVBMediaNode::enc_video_thread() 1600 { 1601 while (!fTerminateThreads) { 1602 status_t err; 1603 Packet *packet; 1604 err = fEncVideoQueue->Remove(&packet); 1605 if (err != B_OK) { 1606 TRACE("fEncVideoQueue->Remove failed, error %lx\n", err); 1607 continue; 1608 } 1609 1610 // TRACE("enc video packet, size %6ld, start_time %14Ld\n", 1611 // packet->Size(), packet->TimeStamp()); 1612 1613 1614 #ifdef DUMP_VIDEO 1615 int8 *data; 1616 size_t size; 1617 if (B_OK != pes_extract(packet->Data(), packet->Size(), &data, 1618 &size)) { 1619 TRACE("video pes_extract failed\n"); 1620 delete packet; 1621 return; 1622 } 1623 lock.Lock(); 1624 write(fVideoFile, data, size); 1625 lock.Unlock(); 1626 #endif 1627 1628 if (!fOutputEnabledEncVideo) { 1629 delete packet; 1630 continue; 1631 } 1632 1633 // send encoded video buffer 1634 1635 delete packet; 1636 } 1637 } 1638 1639 1640 void 1641 DVBMediaNode::raw_audio_thread() 1642 { 1643 media_format format; 1644 status_t err; 1645 err = GetStreamFormat(fRawAudioQueue, &format); 1646 if (err) { 1647 printf("fAudioDecoder init error %s\n", strerror(err)); 1648 return; 1649 } 1650 1651 // create decoder interface 1652 1653 fAudioDecoder = new MediaStreamDecoder(&_GetNextAudioChunk, this); 1654 1655 err = fAudioDecoder->SetInputFormat(format); 1656 if (err) { 1657 printf("fAudioDecoder SetInputFormat error %s\n", strerror(err)); 1658 return; 1659 } 1660 1661 TRACE("requested audio decoder format: "); 1662 PrintFormat(fOutputRawAudio); 1663 1664 media_format fmt = fOutputRawAudio.format; 1665 err = fAudioDecoder->SetOutputFormat(&fmt); 1666 if (err) { 1667 printf("fAudioDecoder SetOutputFormat error %s\n", strerror(err)); 1668 return; 1669 } 1670 1671 TRACE("final audio decoder format: "); 1672 PrintFormat(fmt); 1673 1674 // change format of connection 1675 if (format_is_compatible(fmt, fOutputRawAudio.format)) { 1676 printf("audio formats are compatible\n"); 1677 fOutputRawAudio.format = fmt; 1678 } else { 1679 printf("audio formats NOT compatible\n"); 1680 lock.Lock(); 1681 err = ChangeFormat(fOutputRawAudio.source, 1682 fOutputRawAudio.destination, 1683 &fmt); 1684 lock.Unlock(); 1685 printf("format change result %lx (%s)\n", err, strerror(err)); 1686 PrintFormat(fmt); 1687 fOutputRawAudio.format = fmt; 1688 if (err) 1689 return; 1690 } 1691 1692 // decode data and send buffers 1693 1694 delete fBufferGroupRawAudio; 1695 fBufferGroupRawAudio = new BBufferGroup( 1696 fOutputRawAudio.format.u.raw_audio.buffer_size * 3, 25); 1697 1698 while (!fTerminateThreads) { 1699 int64 frameCount; 1700 media_header mh; 1701 1702 if (!fOutputEnabledRawAudio) { 1703 fRawAudioQueue->Flush(40000); 1704 continue; 1705 } 1706 1707 BBuffer* buf; 1708 buf = fBufferGroupRawAudio->RequestBuffer( 1709 fOutputRawAudio.format.u.raw_audio.buffer_size, 1710 AUDIO_BUFFER_REQUEST_TIMEOUT); 1711 if (!buf) { 1712 TRACE("audio: request buffer timout\n"); 1713 continue; 1714 } 1715 1716 err = fAudioDecoder->Decode(buf->Data(), &frameCount, &mh, NULL); 1717 if (err) { 1718 buf->Recycle(); 1719 printf("fAudioDecoder Decode error %s\n", strerror(err)); 1720 continue; 1721 } 1722 1723 #ifdef DUMP_RAW_AUDIO 1724 lock.Lock(); 1725 write(fRawAudioFile, buf->Data(), mh.size_used); 1726 lock.Unlock(); 1727 #endif 1728 1729 if (fOutputRawAudio.format.u.raw_audio.buffer_size != mh.size_used 1730 || int(fOutputRawAudio.format.u.raw_audio.frame_rate) 1731 != mh.u.raw_audio.frame_rate 1732 || fOutputRawAudio.format.u.raw_audio.channel_count 1733 != mh.u.raw_audio.channel_count) { 1734 TRACE("audio: decode format change: changed buffer_size from %ld" 1735 " to %ld\n", fOutputRawAudio.format.u.raw_audio.buffer_size, 1736 mh.size_used); 1737 TRACE("audio: decode format change: changed channel_count from %ld" 1738 " to %ld\n", fOutputRawAudio.format.u.raw_audio.channel_count, 1739 mh.u.raw_audio.channel_count); 1740 TRACE("audio: decode format change: changed frame_rate from %.0f" 1741 " to %.0f\n", fOutputRawAudio.format.u.raw_audio.frame_rate, 1742 mh.u.raw_audio.frame_rate); 1743 fOutputRawAudio.format.u.raw_audio.buffer_size = mh.size_used; 1744 fOutputRawAudio.format.u.raw_audio.frame_rate 1745 = mh.u.raw_audio.frame_rate; 1746 fOutputRawAudio.format.u.raw_audio.channel_count 1747 = mh.u.raw_audio.channel_count; 1748 lock.Lock(); 1749 err = ChangeFormat(fOutputRawAudio.source, 1750 fOutputRawAudio.destination, &fOutputRawAudio.format); 1751 lock.Unlock(); 1752 printf("format change result %lx (%s)\n", err, strerror(err)); 1753 PrintFormat(fOutputRawAudio.format); 1754 if (err) { 1755 buf->Recycle(); 1756 return; // we are dead! 1757 } 1758 } 1759 1760 bigtime_t ts_perf_time; 1761 bigtime_t ts_sys_time; 1762 bigtime_t ts_offset; 1763 bigtime_t aud_time; 1764 bigtime_t start_time; 1765 1766 // calculate start time of audio data 1767 1768 fDemux->TimesourceInfo(&ts_perf_time, &ts_sys_time); 1769 ts_offset = ts_sys_time - ts_perf_time; 1770 aud_time = mh.start_time; // measured in PCR time base 1771 start_time = TimeSource()->PerformanceTimeFor(aud_time + ts_offset); 1772 1773 // calculate delay and wait 1774 1775 bigtime_t delay; 1776 delay = start_time - TimeSource()->Now(); 1777 TRACE_TIMING("audio delay is %Ld\n", delay); 1778 if (delay < -AUDIO_MAX_LATE) { 1779 printf("audio: decoded packet is %Ldms too late, dropped\n", 1780 -delay / 1000); 1781 buf->Recycle(); 1782 continue; 1783 } 1784 if (delay < 0) 1785 // printf("audio: decoded packet is %Ldms too late\n", -delay / 1000); 1786 1787 if (delay > AUDIO_MAX_EARLY) { 1788 printf("audio: decoded packet is %Ldms too early, dropped\n", 1789 delay / 1000); 1790 buf->Recycle(); 1791 continue; 1792 } 1793 if (delay > 0) 1794 // printf("audio: decoded packet is %Ldms too early\n", delay / 1000); 1795 1796 delay -= PROCESSING_LATENCY; 1797 if (delay > 0) { 1798 if (acquire_sem_etc(fAudioDelaySem, 1, B_RELATIVE_TIMEOUT, delay) 1799 != B_TIMED_OUT) { 1800 printf("audio: delay sem not timed out, dropped packet\n"); 1801 buf->Recycle(); 1802 continue; 1803 } 1804 } 1805 1806 TRACE_TIMING("audio playback delay %Ld\n", 1807 start_time - TimeSource()->Now()); 1808 1809 media_header* hdr; 1810 hdr = buf->Header(); 1811 hdr->type = B_MEDIA_RAW_AUDIO; 1812 hdr->size_used = mh.size_used; 1813 hdr->time_source = TimeSource()->ID(); 1814 hdr->start_time = start_time; 1815 lock.Lock(); 1816 if (SendBuffer(buf, fOutputRawAudio.source, 1817 fOutputRawAudio.destination) != B_OK) { 1818 TRACE("audio: sending buffer failed\n"); 1819 buf->Recycle(); 1820 } 1821 lock.Unlock(); 1822 } 1823 1824 delete fCurrentAudioPacket; 1825 fCurrentAudioPacket = 0; 1826 } 1827 1828 1829 void 1830 DVBMediaNode::raw_video_thread() 1831 { 1832 media_format format; 1833 status_t err; 1834 err = GetStreamFormat(fRawVideoQueue, &format); 1835 if (err) { 1836 printf("fVideoDecoder init error %s\n", strerror(err)); 1837 return; 1838 } 1839 1840 // create decoder interface 1841 1842 fVideoDecoder = new MediaStreamDecoder(&_GetNextVideoChunk, this); 1843 1844 err = fVideoDecoder->SetInputFormat(format); 1845 if (err) { 1846 printf("fVideoDecoder SetInputFormat error %s\n", strerror(err)); 1847 return; 1848 } 1849 1850 TRACE("requested video decoder format: "); 1851 PrintFormat(fOutputRawVideo); 1852 1853 media_format fmt = fOutputRawVideo.format; 1854 err = fVideoDecoder->SetOutputFormat(&fmt); 1855 if (err) { 1856 printf("fVideoDecoder SetOutputFormat error %s\n", strerror(err)); 1857 return; 1858 } 1859 1860 TRACE("final video decoder format: "); 1861 PrintFormat(fmt); 1862 1863 // change format of connection 1864 if (format_is_compatible(fmt, fOutputRawVideo.format)) { 1865 printf("video formats are compatible\n"); 1866 fOutputRawVideo.format = fmt; 1867 } else { 1868 printf("video formats NOT compatible\n"); 1869 lock.Lock(); 1870 err = ChangeFormat(fOutputRawVideo.source, 1871 fOutputRawVideo.destination, 1872 &fmt); 1873 lock.Unlock(); 1874 printf("format change result %lx (%s)\n", err, strerror(err)); 1875 PrintFormat(fmt); 1876 fOutputRawVideo.format = fmt; 1877 if (err) { 1878 printf("video format change failed\n"); 1879 return; 1880 } 1881 } 1882 1883 // decode data and send buffers 1884 1885 uint32 video_buffer_size_max = 720 * 576 * 4; 1886 uint32 video_buffer_size 1887 = fOutputRawVideo.format.u.raw_video.display.line_count 1888 * fOutputRawVideo.format.u.raw_video.display.bytes_per_row; 1889 1890 delete fBufferGroupRawVideo; 1891 fBufferGroupRawVideo = new BBufferGroup(video_buffer_size_max, 4); 1892 1893 while (!fTerminateThreads) { 1894 int64 frameCount; 1895 media_header mh; 1896 1897 if (!fOutputEnabledRawVideo) { 1898 fRawVideoQueue->Flush(40000); 1899 continue; 1900 } 1901 1902 // fetch a new buffer (always of maximum size as the stream may change) 1903 BBuffer* buf; 1904 buf = fBufferGroupRawVideo->RequestBuffer(video_buffer_size_max, 1905 VIDEO_BUFFER_REQUEST_TIMEOUT); 1906 if (!buf) { 1907 TRACE("video: request buffer timout\n"); 1908 continue; 1909 } 1910 1911 // decode one video frame into buffer 1912 err = fVideoDecoder->Decode(buf->Data(), &frameCount, &mh, NULL); 1913 if (err) { 1914 buf->Recycle(); 1915 printf("fVideoDecoder Decode error %s\n", strerror(err)); 1916 continue; 1917 } 1918 1919 // check if the format of the stream has changed 1920 if (mh.u.raw_video.display_line_width 1921 != fOutputRawVideo.format.u.raw_video.display.line_width 1922 || mh.u.raw_video.display_line_count 1923 != fOutputRawVideo.format.u.raw_video.display.line_count 1924 || mh.u.raw_video.bytes_per_row 1925 != fOutputRawVideo.format.u.raw_video.display.bytes_per_row 1926 || mh.u.raw_video.pixel_width_aspect 1927 != fOutputRawVideo.format.u.raw_video.pixel_width_aspect 1928 || mh.u.raw_video.pixel_height_aspect 1929 != fOutputRawVideo.format.u.raw_video.pixel_height_aspect 1930 || mh.size_used != video_buffer_size) { 1931 printf("video format changed:\n"); 1932 printf(" line_width %ld => %ld\n", 1933 fOutputRawVideo.format.u.raw_video.display.line_width, 1934 mh.u.raw_video.display_line_width); 1935 printf(" line_count %ld => %ld\n", 1936 fOutputRawVideo.format.u.raw_video.display.line_count, 1937 mh.u.raw_video.display_line_count); 1938 printf(" bytes_per_row %ld => %ld\n", 1939 fOutputRawVideo.format.u.raw_video.display.bytes_per_row, 1940 mh.u.raw_video.bytes_per_row); 1941 printf(" pixel_width_aspect %d => %d\n", 1942 fOutputRawVideo.format.u.raw_video.pixel_width_aspect, 1943 mh.u.raw_video.pixel_width_aspect); 1944 printf(" pixel_height_aspect %d => %d\n", 1945 fOutputRawVideo.format.u.raw_video.pixel_height_aspect, 1946 mh.u.raw_video.pixel_height_aspect); 1947 printf(" video_buffer_size %ld => %ld\n", video_buffer_size, 1948 mh.size_used); 1949 1950 // recalculate video buffer size 1951 video_buffer_size 1952 = fOutputRawVideo.format.u.raw_video.display.line_count 1953 * fOutputRawVideo.format.u.raw_video.display.bytes_per_row; 1954 1955 // perform a video format change 1956 fOutputRawVideo.format.u.raw_video.display.line_width 1957 = mh.u.raw_video.display_line_width; 1958 fOutputRawVideo.format.u.raw_video.display.line_count 1959 = mh.u.raw_video.display_line_count; 1960 fOutputRawVideo.format.u.raw_video.display.bytes_per_row 1961 = mh.u.raw_video.bytes_per_row; 1962 fOutputRawVideo.format.u.raw_video.pixel_width_aspect 1963 = mh.u.raw_video.pixel_width_aspect; 1964 fOutputRawVideo.format.u.raw_video.pixel_height_aspect 1965 = mh.u.raw_video.pixel_height_aspect; 1966 fOutputRawVideo.format.u.raw_video.last_active 1967 = mh.u.raw_video.display_line_count - 1; 1968 lock.Lock(); 1969 err = ChangeFormat(fOutputRawVideo.source, 1970 fOutputRawVideo.destination, &fOutputRawVideo.format); 1971 lock.Unlock(); 1972 printf("format change result %lx (%s)\n", err, strerror(err)); 1973 PrintFormat(fOutputRawVideo.format); 1974 if (err) { 1975 buf->Recycle(); 1976 printf("video format change failed\n"); 1977 return; // we are dead 1978 } 1979 } 1980 1981 // calculate start time for video 1982 bigtime_t ts_perf_time; 1983 bigtime_t ts_sys_time; 1984 bigtime_t ts_offset; 1985 bigtime_t pic_time; 1986 bigtime_t start_time; 1987 1988 fDemux->TimesourceInfo(&ts_perf_time, &ts_sys_time); 1989 ts_offset = ts_sys_time - ts_perf_time; 1990 pic_time = mh.start_time; // measured in PCR time base 1991 start_time = TimeSource()->PerformanceTimeFor(pic_time + ts_offset); 1992 1993 // calculate delay and wait 1994 1995 bigtime_t delay; 1996 delay = start_time - TimeSource()->Now(); 1997 TRACE_TIMING("video delay %Ld\n", delay); 1998 if (delay < -VIDEO_MAX_LATE) { 1999 printf("video: decoded packet is %Ldms too late, dropped\n", 2000 -delay / 1000); 2001 buf->Recycle(); 2002 continue; 2003 } 2004 if (delay > VIDEO_MAX_EARLY) { 2005 printf("video: decoded packet is %Ldms too early, dropped\n", 2006 delay / 1000); 2007 buf->Recycle(); 2008 continue; 2009 } 2010 delay -= PROCESSING_LATENCY; 2011 if (delay > 0) { 2012 if (acquire_sem_etc(fVideoDelaySem, 1, B_RELATIVE_TIMEOUT, delay) 2013 != B_TIMED_OUT) { 2014 printf("video: delay sem not timed out, dropped packet\n"); 2015 buf->Recycle(); 2016 continue; 2017 } 2018 } 2019 2020 TRACE_TIMING("video playback delay %Ld\n", start_time 2021 - TimeSource()->Now()); 2022 2023 media_header* hdr; 2024 hdr = buf->Header(); 2025 hdr->type = B_MEDIA_RAW_VIDEO; 2026 hdr->size_used = video_buffer_size; 2027 hdr->time_source = TimeSource()->ID(); 2028 hdr->start_time = start_time; 2029 lock.Lock(); 2030 if (SendBuffer(buf, fOutputRawVideo.source, 2031 fOutputRawVideo.destination) != B_OK) { 2032 TRACE("video: sending buffer failed\n"); 2033 buf->Recycle(); 2034 } 2035 lock.Unlock(); 2036 } 2037 2038 delete fCurrentVideoPacket; 2039 fCurrentVideoPacket = 0; 2040 } 2041 2042 2043 inline status_t 2044 DVBMediaNode::GetNextVideoChunk(const void **chunkData, size_t *chunkLen, 2045 media_header *mh) 2046 { 2047 // TRACE("DVBMediaNode::GetNextVideoChunk\n"); 2048 2049 delete fCurrentVideoPacket; 2050 2051 status_t err; 2052 err = fRawVideoQueue->Remove(&fCurrentVideoPacket); 2053 if (err != B_OK) { 2054 TRACE("fRawVideoQueue->Remove failed, error %lx\n", err); 2055 fCurrentVideoPacket = 0; 2056 return B_ERROR; 2057 } 2058 2059 const uint8 *data; 2060 size_t size; 2061 2062 if (B_OK != pes_extract(fCurrentVideoPacket->Data(), 2063 fCurrentVideoPacket->Size(), &data, &size)) { 2064 TRACE("video pes_extract failed\n"); 2065 return B_ERROR; 2066 } 2067 2068 *chunkData = data; 2069 *chunkLen = size; 2070 // measured in PCR time base 2071 mh->start_time = fCurrentVideoPacket->TimeStamp(); 2072 2073 return B_OK; 2074 } 2075 2076 2077 inline status_t 2078 DVBMediaNode::GetNextAudioChunk(const void **chunkData, size_t *chunkLen, 2079 media_header *mh) 2080 { 2081 // TRACE("DVBMediaNode::GetNextAudioChunk\n"); 2082 2083 delete fCurrentAudioPacket; 2084 2085 status_t err; 2086 err = fRawAudioQueue->Remove(&fCurrentAudioPacket); 2087 if (err != B_OK) { 2088 TRACE("fRawAudioQueue->Remove failed, error %lx\n", err); 2089 fCurrentAudioPacket = 0; 2090 return B_ERROR; 2091 } 2092 2093 const uint8 *data; 2094 size_t size; 2095 2096 if (B_OK != pes_extract(fCurrentAudioPacket->Data(), 2097 fCurrentAudioPacket->Size(), &data, &size)) { 2098 TRACE("audio pes_extract failed\n"); 2099 return B_ERROR; 2100 } 2101 2102 *chunkData = data; 2103 *chunkLen = size; 2104 // measured in PCR time base 2105 mh->start_time = fCurrentAudioPacket->TimeStamp(); 2106 2107 // printf("GetNextAudioChunk: done start_time %Ld\n", mh->start_time); 2108 2109 return B_OK; 2110 } 2111 2112 2113 status_t 2114 DVBMediaNode::_GetNextVideoChunk(const void **chunkData, size_t *chunkLen, 2115 media_header *mh, void *cookie) 2116 { 2117 return static_cast<DVBMediaNode *>(cookie)->GetNextVideoChunk(chunkData, 2118 chunkLen, mh); 2119 } 2120 2121 2122 status_t 2123 DVBMediaNode::_GetNextAudioChunk(const void **chunkData, size_t *chunkLen, 2124 media_header *mh, void *cookie) 2125 { 2126 return static_cast<DVBMediaNode *>(cookie)->GetNextAudioChunk(chunkData, 2127 chunkLen, mh); 2128 } 2129 2130 2131 status_t 2132 DVBMediaNode::GetStreamFormat(PacketQueue *queue, media_format *format) 2133 { 2134 status_t status; 2135 Packet *packet; 2136 const uint8 *data; 2137 size_t size; 2138 int stream_id; 2139 2140 // get copy of the first packet from queue, and determine format 2141 status = queue->Peek(&packet); 2142 if (status != B_OK) { 2143 TRACE("queue->Peek failed, error %lx\n", status); 2144 return status; 2145 } 2146 status = pes_extract(packet->Data(), packet->Size(), &data, &size); 2147 if (status != B_OK) { 2148 TRACE("pes_extract failed\n"); 2149 goto done; 2150 } 2151 status = pes_stream_id(packet->Data(), packet->Size(), &stream_id); 2152 if (status != B_OK) { 2153 TRACE("pes_stream_id failed\n"); 2154 goto done; 2155 } 2156 status = GetHeaderFormat(format, data, size, stream_id); 2157 if (status != B_OK) { 2158 TRACE("GetHeaderFormat failed, error %lx\n", status); 2159 goto done; 2160 } 2161 2162 done: 2163 delete packet; 2164 return status; 2165 } 2166 2167 2168 enum { 2169 ID_STATE = 11, 2170 ID_REGION = 12, 2171 ID_CHANNEL = 13, 2172 ID_AUDIO = 14, 2173 }; 2174 2175 2176 void 2177 DVBMediaNode::RefreshParameterWeb() 2178 { 2179 TRACE("DVBMediaNode::RefreshParameterWeb enter\n"); 2180 fWeb = CreateParameterWeb(); 2181 SetParameterWeb(fWeb); 2182 TRACE("DVBMediaNode::RefreshParameterWeb finished\n"); 2183 } 2184 2185 2186 void 2187 DVBMediaNode::SetAboutInfo(BParameterGroup *about) 2188 { 2189 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "DVB media_addon info:", 2190 B_GENERIC); 2191 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Version " VERSION, 2192 B_GENERIC); 2193 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Revision " REVISION, 2194 B_GENERIC); 2195 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Build " BUILD, B_GENERIC); 2196 2197 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "", B_GENERIC); 2198 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Driver info:", B_GENERIC); 2199 2200 dvb_type_t type; 2201 char name[200]; 2202 char info[200]; 2203 2204 fCard->GetCardType(&type); 2205 fCard->GetCardInfo(name, sizeof(name), info, sizeof(info)); 2206 2207 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, name, B_GENERIC); 2208 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, info, B_GENERIC); 2209 } 2210 2211 2212 BParameterWeb * 2213 DVBMediaNode::CreateParameterWeb() 2214 { 2215 /* Set up the parameter web */ 2216 BParameterWeb *web = new BParameterWeb(); 2217 2218 char n[200], i[200]; 2219 fCard->GetCardInfo(n, sizeof(n), i, sizeof(i)); 2220 2221 BString name; 2222 name << Name() << " - " << i; 2223 2224 BParameterGroup *main = web->MakeGroup(name.String()); 2225 2226 BParameterGroup *ctrl = main->MakeGroup("Channel Selection"); 2227 ctrl->MakeNullParameter(0, B_MEDIA_NO_TYPE, ctrl->Name(), B_GENERIC); 2228 2229 BParameterGroup *pref = main->MakeGroup("Preferences"); 2230 pref->MakeNullParameter(0, B_MEDIA_NO_TYPE, pref->Name(), B_GENERIC); 2231 2232 BDiscreteParameter *state = pref->MakeDiscreteParameter( 2233 ID_STATE, B_MEDIA_RAW_VIDEO, "State", B_GENERIC); 2234 2235 BDiscreteParameter *region = pref->MakeDiscreteParameter( 2236 ID_REGION, B_MEDIA_RAW_VIDEO, "Region", B_GENERIC); 2237 2238 BDiscreteParameter *chan = ctrl->MakeDiscreteParameter( 2239 ID_CHANNEL, B_MEDIA_RAW_VIDEO, "Channel", 2240 /* B_TUNER_CHANNEL */ B_GENERIC); 2241 2242 BDiscreteParameter *aud = ctrl->MakeDiscreteParameter( 2243 ID_AUDIO, B_MEDIA_RAW_VIDEO, "Audio", B_GENERIC); 2244 2245 AddStateItems(state); 2246 AddRegionItems(region); 2247 AddChannelItems(chan); 2248 AddAudioItems(aud); 2249 2250 2251 if (!fTuningSuccess || !fCaptureActive) { 2252 BParameterGroup *info = main->MakeGroup("Info"); 2253 info->MakeNullParameter(0, B_MEDIA_NO_TYPE, info->Name(), B_GENERIC); 2254 BParameterGroup *about = main->MakeGroup("About"); 2255 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, about->Name(), B_GENERIC); 2256 SetAboutInfo(about); 2257 // info->MakeNullParameter(0, B_MEDIA_NO_TYPE, 2258 // fCaptureActive ? "Tuning failed" : "Node stopped", B_GENERIC); 2259 info->MakeNullParameter(0, B_MEDIA_NO_TYPE, "Node is stopped", 2260 B_GENERIC); 2261 info->MakeNullParameter(0, B_MEDIA_NO_TYPE, "or tuning failed.", 2262 B_GENERIC); 2263 return web; 2264 } 2265 2266 BParameterGroup *info1 = main->MakeGroup("Info"); 2267 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, info1->Name(), B_GENERIC); 2268 BParameterGroup *info2 = main->MakeGroup("Info"); 2269 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, info2->Name(), B_GENERIC); 2270 BParameterGroup *about = main->MakeGroup("About"); 2271 about->MakeNullParameter(0, B_MEDIA_NO_TYPE, about->Name(), B_GENERIC); 2272 SetAboutInfo(about); 2273 2274 BString sInterfaceType = "Interface Type: "; 2275 BString sFrequency = "Frequency: "; 2276 BString sAudioPid = "Audio PID: "; 2277 BString sVideoPid = "Video PID: "; 2278 BString sPcrPid = "PCR PID: "; 2279 BString sInversion = "Inversion: "; 2280 BString sBandwidth = "Bandwith: "; 2281 BString sModulation = "Modulation: "; 2282 BString sHierarchy = "Hierarchy: "; 2283 BString sCodeRateHP = "Code Rate HP: "; 2284 BString sCodeRateLP = "Code Rate LP: "; 2285 BString sTransmissionMode = "Transmission Mode: "; 2286 BString sGuardInterval = "Guard Interval: "; 2287 2288 BString sSymbolRate = "Symbol Rate: "; 2289 BString sPolarity = "Polarity: "; 2290 BString sAgcInversion = "AGC Inversion: "; 2291 2292 switch (fInterfaceType) { 2293 case DVB_TYPE_DVB_C: 2294 sInterfaceType << "DVB-C"; 2295 break; 2296 2297 case DVB_TYPE_DVB_H: 2298 sInterfaceType << "DVB-H"; 2299 break; 2300 2301 case DVB_TYPE_DVB_S: 2302 sInterfaceType << "DVB-S"; 2303 break; 2304 2305 case DVB_TYPE_DVB_T: 2306 sInterfaceType << "DVB-T"; 2307 break; 2308 2309 default: 2310 sInterfaceType << "unknown"; 2311 break; 2312 } 2313 2314 sAudioPid << fAudioPid; 2315 sVideoPid << fVideoPid; 2316 sPcrPid << fPcrPid; 2317 2318 if (fInterfaceType == DVB_TYPE_DVB_T) { 2319 2320 sFrequency << fTuningParam.u.dvb_t.frequency / 1000000 << " MHz"; 2321 2322 switch (fTuningParam.u.dvb_t.inversion) { 2323 case DVB_INVERSION_AUTO: 2324 sInversion << "auto"; 2325 break; 2326 2327 case DVB_INVERSION_ON: 2328 sInversion << "on"; 2329 break; 2330 2331 case DVB_INVERSION_OFF: 2332 sInversion << "off"; 2333 break; 2334 2335 default: 2336 sInversion << "unknown"; 2337 break; 2338 } 2339 2340 switch (fTuningParam.u.dvb_t.bandwidth) { 2341 case DVB_BANDWIDTH_AUTO: 2342 sBandwidth << "auto"; 2343 break; 2344 2345 case DVB_BANDWIDTH_6_MHZ: 2346 sBandwidth << "6 MHz"; 2347 break; 2348 2349 case DVB_BANDWIDTH_7_MHZ: 2350 sBandwidth << "7 MHz"; 2351 break; 2352 2353 case DVB_BANDWIDTH_8_MHZ: 2354 sBandwidth << "8 MHz"; 2355 break; 2356 2357 default: 2358 sBandwidth << "unknown"; 2359 break; 2360 } 2361 2362 switch (fTuningParam.u.dvb_t.modulation) { 2363 case DVB_MODULATION_AUTO: 2364 sModulation << "auto"; 2365 break; 2366 2367 case DVB_MODULATION_QPSK: 2368 sModulation << "QPSK"; 2369 break; 2370 2371 case DVB_MODULATION_16_QAM: 2372 sModulation << "16 QAM"; 2373 break; 2374 2375 case DVB_MODULATION_32_QAM: 2376 sModulation << "32 QAM"; 2377 break; 2378 2379 case DVB_MODULATION_64_QAM: 2380 sModulation << "64 QAM"; 2381 break; 2382 2383 case DVB_MODULATION_128_QAM: 2384 sModulation << "128 QAM"; 2385 break; 2386 2387 case DVB_MODULATION_256_QAM: 2388 sModulation << "256 QAM"; 2389 break; 2390 2391 default: 2392 sModulation << "unknown"; 2393 break; 2394 } 2395 2396 switch (fTuningParam.u.dvb_t.hierarchy) { 2397 case DVB_HIERARCHY_AUTO: 2398 sHierarchy << "auto"; 2399 break; 2400 2401 case DVB_HIERARCHY_NONE: 2402 sHierarchy << "none"; 2403 break; 2404 2405 case DVB_HIERARCHY_1: 2406 sHierarchy << "1"; 2407 break; 2408 2409 case DVB_HIERARCHY_2: 2410 sHierarchy << "2"; 2411 break; 2412 2413 case DVB_HIERARCHY_4: 2414 sHierarchy << "4"; 2415 break; 2416 2417 default: 2418 sHierarchy << "unknown"; 2419 break; 2420 } 2421 2422 switch (fTuningParam.u.dvb_t.code_rate_hp) { 2423 case DVB_FEC_AUTO: 2424 sCodeRateHP << "auto"; 2425 break; 2426 2427 case DVB_FEC_NONE: 2428 sCodeRateHP << "none"; 2429 break; 2430 2431 case DVB_FEC_1_2: 2432 sCodeRateHP << "FEC 1/2"; 2433 break; 2434 2435 case DVB_FEC_2_3: 2436 sCodeRateHP << "FEC 2/3"; 2437 break; 2438 2439 case DVB_FEC_3_4: 2440 sCodeRateHP << "FEC 3/4"; 2441 break; 2442 2443 case DVB_FEC_4_5: 2444 sCodeRateHP << "FEC 4/5"; 2445 break; 2446 2447 case DVB_FEC_5_6: 2448 sCodeRateHP << "FEC 5/6"; 2449 break; 2450 2451 case DVB_FEC_6_7: 2452 sCodeRateHP << "FEC 6/7"; 2453 break; 2454 2455 case DVB_FEC_7_8: 2456 sCodeRateHP << "FEC 7/8"; 2457 break; 2458 2459 case DVB_FEC_8_9: 2460 sCodeRateHP << "FEC 8/9"; 2461 break; 2462 2463 default: 2464 sCodeRateHP << "unknown"; 2465 break; 2466 } 2467 2468 switch (fTuningParam.u.dvb_t.code_rate_lp) { 2469 case DVB_FEC_AUTO: 2470 sCodeRateLP << "auto"; 2471 break; 2472 2473 case DVB_FEC_NONE: 2474 sCodeRateLP << "none"; 2475 break; 2476 2477 case DVB_FEC_1_2: 2478 sCodeRateLP << "FEC 1/2"; 2479 break; 2480 2481 case DVB_FEC_2_3: 2482 sCodeRateLP << "FEC 2/3"; 2483 break; 2484 2485 case DVB_FEC_3_4: 2486 sCodeRateLP << "FEC 3/4"; 2487 break; 2488 2489 case DVB_FEC_4_5: 2490 sCodeRateLP << "FEC 4/5"; 2491 break; 2492 2493 case DVB_FEC_5_6: 2494 sCodeRateLP << "FEC 5/6"; 2495 break; 2496 2497 case DVB_FEC_6_7: 2498 sCodeRateLP << "FEC 6/7"; 2499 break; 2500 2501 case DVB_FEC_7_8: 2502 sCodeRateLP << "FEC 7/8"; 2503 break; 2504 2505 case DVB_FEC_8_9: 2506 sCodeRateLP << "FEC 8/9"; 2507 break; 2508 2509 default: 2510 sCodeRateLP << "unknown"; 2511 break; 2512 } 2513 2514 switch (fTuningParam.u.dvb_t.transmission_mode) { 2515 case DVB_TRANSMISSION_MODE_AUTO: 2516 sTransmissionMode << "auto"; 2517 break; 2518 2519 case DVB_TRANSMISSION_MODE_2K: 2520 sTransmissionMode << "2K"; 2521 break; 2522 2523 case DVB_TRANSMISSION_MODE_4K: 2524 sTransmissionMode << "4K"; 2525 break; 2526 2527 case DVB_TRANSMISSION_MODE_8K: 2528 sTransmissionMode << "8K"; 2529 break; 2530 2531 default: 2532 sTransmissionMode << "unknown"; 2533 break; 2534 } 2535 2536 switch (fTuningParam.u.dvb_t.guard_interval) { 2537 case DVB_GUARD_INTERVAL_AUTO: 2538 sGuardInterval << "auto"; 2539 break; 2540 2541 case DVB_GUARD_INTERVAL_1_4: 2542 sGuardInterval << "1/4"; 2543 break; 2544 2545 case DVB_GUARD_INTERVAL_1_8: 2546 sGuardInterval << "1/8"; 2547 break; 2548 2549 case DVB_GUARD_INTERVAL_1_16: 2550 sGuardInterval << "1/16"; 2551 break; 2552 2553 case DVB_GUARD_INTERVAL_1_32: 2554 sGuardInterval << "1/32"; 2555 break; 2556 2557 default: 2558 sGuardInterval << "unknown"; 2559 break; 2560 } 2561 2562 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInterfaceType.String(), 2563 B_GENERIC); 2564 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sFrequency.String(), 2565 B_GENERIC); 2566 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sBandwidth.String(), 2567 B_GENERIC); 2568 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sVideoPid.String(), 2569 B_GENERIC); 2570 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sAudioPid.String(), 2571 B_GENERIC); 2572 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sPcrPid.String(), 2573 B_GENERIC); 2574 2575 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sModulation.String(), 2576 B_GENERIC); 2577 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, 2578 sTransmissionMode.String(), B_GENERIC); 2579 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sGuardInterval.String(), 2580 B_GENERIC); 2581 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sCodeRateHP.String(), 2582 B_GENERIC); 2583 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sCodeRateLP.String(), 2584 B_GENERIC); 2585 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInversion.String(), 2586 B_GENERIC); 2587 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sHierarchy.String(), 2588 B_GENERIC); 2589 } 2590 2591 if (fInterfaceType == DVB_TYPE_DVB_S) { 2592 2593 sFrequency << fTuningParam.u.dvb_s.frequency / 1000000 << " MHz"; 2594 sSymbolRate << fTuningParam.u.dvb_s.symbolrate; 2595 2596 switch (fTuningParam.u.dvb_s.inversion) { 2597 case DVB_INVERSION_AUTO: 2598 sInversion << "auto"; 2599 break; 2600 2601 case DVB_INVERSION_ON: 2602 sInversion << "on"; 2603 break; 2604 2605 case DVB_INVERSION_OFF: 2606 sInversion << "off"; 2607 break; 2608 2609 default: 2610 sInversion << "unknown"; 2611 break; 2612 } 2613 2614 switch (fTuningParam.u.dvb_s.polarity) { 2615 case DVB_POLARITY_VERTICAL: 2616 sPolarity << "vertical"; 2617 break; 2618 2619 case DVB_POLARITY_HORIZONTAL: 2620 sPolarity << "horizontal"; 2621 break; 2622 2623 default: 2624 sPolarity << "unknown"; 2625 break; 2626 } 2627 2628 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInterfaceType.String(), 2629 B_GENERIC); 2630 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sVideoPid.String(), 2631 B_GENERIC); 2632 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sAudioPid.String(), 2633 B_GENERIC); 2634 info1->MakeNullParameter(0, B_MEDIA_NO_TYPE, sPcrPid.String(), 2635 B_GENERIC); 2636 2637 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sFrequency.String(), 2638 B_GENERIC); 2639 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sPolarity.String(), 2640 B_GENERIC); 2641 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sSymbolRate.String(), 2642 B_GENERIC); 2643 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sInversion.String(), 2644 B_GENERIC); 2645 info2->MakeNullParameter(0, B_MEDIA_NO_TYPE, sAgcInversion.String(), 2646 B_GENERIC); 2647 } 2648 2649 return web; 2650 } 2651 2652 2653 void 2654 DVBMediaNode::LoadSettings() 2655 { 2656 TRACE("DVBMediaNode::LoadSettings\n"); 2657 RefreshStateList(); 2658 fSelectedState = 0; 2659 RefreshRegionList(); 2660 fSelectedRegion = 0; 2661 RefreshChannelList(); 2662 fSelectedChannel = 0; 2663 RefreshAudioList(); 2664 fSelectedAudio = 0; 2665 } 2666 2667 2668 void 2669 DVBMediaNode::RefreshStateList() 2670 { 2671 TRACE("DVBMediaNode::RefreshStateList\n"); 2672 2673 fStateList->MakeEmpty(); 2674 fSelectedState = -1; 2675 2676 const char *dir; 2677 switch (fInterfaceType) { 2678 case DVB_TYPE_DVB_C: 2679 dir = "/boot/home/config/settings/Media/dvb/dvb-c channels"; 2680 break; 2681 2682 case DVB_TYPE_DVB_H: 2683 dir = "/boot/home/config/settings/Media/dvb/dvb-h channels"; 2684 break; 2685 2686 case DVB_TYPE_DVB_S: 2687 dir = "/boot/home/config/settings/Media/dvb/dvb-s channels"; 2688 break; 2689 2690 case DVB_TYPE_DVB_T: 2691 dir = "/boot/home/config/settings/Media/dvb/dvb-t channels"; 2692 break; 2693 2694 default: 2695 printf("DVBMediaNode::RefreshStateList unknown interface type\n"); 2696 return; 2697 } 2698 2699 TRACE("loading channel lists from dir = %s\n", dir); 2700 2701 BDirectory d(dir); 2702 BEntry e; 2703 BPath p; 2704 while (B_OK == d.GetNextEntry(&e, false)) { 2705 if (B_OK != e.GetPath(&p)) 2706 continue; 2707 fStateList->AddItem(p.Path()); 2708 } 2709 2710 if (fStateList->ItemAt(0)) 2711 fSelectedState = 0; 2712 } 2713 2714 2715 void 2716 DVBMediaNode::RefreshRegionList() 2717 { 2718 TRACE("DVBMediaNode::RefreshRegionList\n"); 2719 2720 fRegionList->MakeEmpty(); 2721 fSelectedRegion = -1; 2722 2723 const char *dir = fStateList->ItemAt(fSelectedState); 2724 if (!dir) 2725 return; 2726 2727 BDirectory d(dir); 2728 BEntry e; 2729 BPath p; 2730 while (B_OK == d.GetNextEntry(&e, false)) { 2731 if (B_OK != e.GetPath(&p)) 2732 continue; 2733 fRegionList->AddItem(p.Path()); 2734 } 2735 2736 if (fRegionList->ItemAt(0)) 2737 fSelectedRegion = 0; 2738 } 2739 2740 2741 void 2742 DVBMediaNode::RefreshChannelList() 2743 { 2744 TRACE("DVBMediaNode::RefreshChannelList\n"); 2745 2746 fChannelList->MakeEmpty(); 2747 fSelectedChannel = -1; 2748 2749 const char *path = fRegionList->ItemAt(fSelectedRegion); 2750 if (!path) 2751 return; 2752 2753 TRACE("opening channel list file = %s\n", path); 2754 2755 FILE *f = fopen(path, "r"); 2756 if (!f) 2757 return; 2758 2759 char line[1024]; 2760 while (fgets(line, sizeof(line), f)) { 2761 if (line[0] == ':') // skip comments 2762 continue; 2763 if (strchr(line, ':') == NULL) // skip empty lines 2764 continue; 2765 fChannelList->AddItem(line); 2766 } 2767 2768 fclose(f); 2769 2770 if (fChannelList->ItemAt(0)) 2771 fSelectedChannel = 0; 2772 } 2773 2774 2775 void 2776 DVBMediaNode::RefreshAudioList() 2777 { 2778 TRACE("DVBMediaNode::RefreshAudioList\n"); 2779 2780 fAudioList->MakeEmpty(); 2781 fSelectedAudio = -1; 2782 2783 fAudioList->AddItem("default"); // XXX test 2784 2785 if (fAudioList->ItemAt(0)) 2786 fSelectedAudio = 0; 2787 } 2788 2789 2790 void 2791 DVBMediaNode::AddStateItems(BDiscreteParameter *param) 2792 { 2793 TRACE("DVBMediaNode::AddStateItems\n"); 2794 2795 const char *str; 2796 for (int i = 0; (str = fStateList->ItemAt(i)); i++) { 2797 str = strrchr(str, '/'); 2798 if (!str) 2799 continue; 2800 str++; 2801 param->AddItem(i, str); 2802 } 2803 if (param->CountItems() == 0) 2804 param->AddItem(-1, "none"); 2805 } 2806 2807 2808 void 2809 DVBMediaNode::AddRegionItems(BDiscreteParameter *param) 2810 { 2811 TRACE("DVBMediaNode::AddRegionItems\n"); 2812 2813 const char *str; 2814 for (int i = 0; (str = fRegionList->ItemAt(i)); i++) { 2815 str = strrchr(str, '/'); 2816 if (!str) 2817 continue; 2818 str++; 2819 param->AddItem(i, str); 2820 } 2821 if (param->CountItems() == 0) 2822 param->AddItem(-1, "none"); 2823 } 2824 2825 2826 void 2827 DVBMediaNode::AddChannelItems(BDiscreteParameter *param) 2828 { 2829 TRACE("DVBMediaNode::AddChannelItems\n"); 2830 2831 const char *str; 2832 for (int i = 0; (str = fChannelList->ItemAt(i)); i++) { 2833 char name[256]; 2834 // sscanf(str, "%s:", name); 2835 sscanf(str, "%[^:]", name); 2836 param->AddItem(i, name); 2837 2838 } 2839 if (param->CountItems() == 0) 2840 param->AddItem(-1, "none"); 2841 } 2842 2843 2844 void 2845 DVBMediaNode::AddAudioItems(BDiscreteParameter *param) 2846 { 2847 TRACE("DVBMediaNode::AddAudioItems\n"); 2848 2849 if (param->CountItems() == 0) 2850 param->AddItem(-1, "default"); 2851 } 2852 2853 2854 status_t 2855 DVBMediaNode::GetParameterValue(int32 id, bigtime_t *last_change, void *value, 2856 size_t *size) 2857 { 2858 // TRACE("DVBMediaNode::GetParameterValue, id 0x%lx\n", id); 2859 2860 switch (id) { 2861 case ID_STATE: 2862 *size = 4; 2863 *(int32 *)value = fSelectedState; 2864 break; 2865 2866 case ID_REGION: 2867 *size = 4; 2868 *(int32 *)value = fSelectedRegion; 2869 break; 2870 2871 case ID_CHANNEL: 2872 *size = 4; 2873 *(int32 *)value = fSelectedChannel; 2874 break; 2875 2876 case ID_AUDIO: 2877 *size = 4; 2878 *(int32 *)value = fSelectedAudio; 2879 break; 2880 2881 default: 2882 return B_ERROR; 2883 } 2884 return B_OK; 2885 } 2886 2887 2888 void 2889 DVBMediaNode::SetParameterValue(int32 id, bigtime_t when, const void *value, 2890 size_t size) 2891 { 2892 TRACE("DVBMediaNode::SetParameterValue, id 0x%lx, size %ld, value 0x%lx\n", 2893 id, size, *(const int32 *)value); 2894 2895 switch (id) { 2896 case ID_STATE: 2897 fSelectedState = *(const int32 *)value; 2898 StopCapture(); 2899 RefreshRegionList(); 2900 RefreshChannelList(); 2901 RefreshAudioList(); 2902 EventQueue()->AddEvent(media_timed_event(0, 2903 M_REFRESH_PARAMETER_WEB)); 2904 // Tune(); 2905 break; 2906 2907 case ID_REGION: 2908 fSelectedRegion = *(const int32 *)value; 2909 StopCapture(); 2910 RefreshChannelList(); 2911 RefreshAudioList(); 2912 EventQueue()->AddEvent(media_timed_event(0, 2913 M_REFRESH_PARAMETER_WEB)); 2914 // Tune(); 2915 break; 2916 2917 case ID_CHANNEL: 2918 fSelectedChannel = *(const int32 *)value; 2919 RefreshAudioList(); 2920 // EventQueue()->AddEvent(media_timed_event(0, 2921 // M_REFRESH_PARAMETER_WEB)); 2922 Tune(); 2923 break; 2924 2925 case ID_AUDIO: 2926 fSelectedAudio = *(const int32 *)value; 2927 Tune(); 2928 break; 2929 2930 default: 2931 break; 2932 } 2933 TRACE("DVBMediaNode::SetParameterValue finished\n"); 2934 } 2935 2936 2937 status_t 2938 DVBMediaNode::ExtractTuningParams(const char *description, int audio_pid_index, 2939 dvb_tuning_parameters_t *tuning_param, int *video_pid, int *audio_pid, 2940 int *pcr_pid) 2941 { 2942 if (!description) 2943 return B_ERROR; 2944 2945 printf("ExtractTuningParams: \"%s\"\n", description); 2946 2947 char name[50]; 2948 char freq[50]; 2949 char para[100]; 2950 char src[50]; 2951 char srate[50]; 2952 char vpid[50]; 2953 char apid[50]; 2954 char tpid[50]; 2955 char ca[50]; 2956 char sid[50]; 2957 char nid[50]; 2958 char tid[50]; 2959 char rid[50]; 2960 2961 sscanf(description, " %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:]" 2962 " : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] : %[^:] ", name, freq, para, 2963 src, srate, vpid, apid, tpid, ca, sid, nid, tid, rid); 2964 2965 char *cpid = strchr(vpid, '+'); 2966 if (cpid) cpid++; 2967 2968 int _vpid = strtol(vpid, 0, 0); 2969 int _apid = strtol(apid, 0, 0); 2970 // int _tpid = strtol(tpid, 0, 0); 2971 int _cpid = cpid ? strtol(cpid, 0, 0) : _vpid; 2972 int _srate = strtol(srate, 0, 0); 2973 int64 _freq = strtol(freq, 0, 0); 2974 while (_freq && _freq <= 1000000) 2975 _freq *= 1000; 2976 2977 if (fInterfaceType == DVB_TYPE_DVB_S && _freq < 950000000) { 2978 TRACE("workaround activated: type is DVB_S and frequency < 950 MHz," 2979 " multiplying by 1000!\n"); 2980 _freq *= 1000; 2981 } 2982 2983 2984 *video_pid = _vpid; 2985 *audio_pid = _apid; 2986 *pcr_pid = _cpid; 2987 2988 TRACE("parsing result: params: '%s'\n", para); 2989 2990 TRACE("parsing result: video pid %d\n", _vpid); 2991 TRACE("parsing result: audio pid %d\n", _apid); 2992 TRACE("parsing result: PCR pid %d\n", _cpid); 2993 TRACE("parsing result: symbol rate %d\n", _srate); 2994 TRACE("parsing result: Frequency %Ld Hz, %Ld MHz\n", _freq, _freq / 1000000); 2995 2996 if (fInterfaceType == DVB_TYPE_DVB_T) { 2997 2998 dvb_t_tuning_parameters_t *param = &tuning_param->u.dvb_t; 2999 3000 TRACE("Interface is DVB-T\n"); 3001 param->frequency = _freq; 3002 param->inversion = DVB_INVERSION_OFF; 3003 param->bandwidth = DVB_BANDWIDTH_8_MHZ; 3004 param->modulation = DVB_MODULATION_16_QAM; 3005 param->hierarchy = DVB_HIERARCHY_NONE; 3006 param->code_rate_hp = DVB_FEC_2_3; 3007 param->code_rate_lp = DVB_FEC_2_3; 3008 param->transmission_mode = DVB_TRANSMISSION_MODE_8K; 3009 param->guard_interval = DVB_GUARD_INTERVAL_1_4; 3010 } 3011 3012 if (fInterfaceType == DVB_TYPE_DVB_S) { 3013 dvb_s_tuning_parameters_t *param = &tuning_param->u.dvb_s; 3014 3015 TRACE("Interface is DVB-S\n"); 3016 3017 const char *pInv = strchr(para, 'I'); 3018 if (pInv == NULL) 3019 pInv = strchr(para, 'i'); 3020 if (pInv != NULL && pInv[1] == '0') { 3021 TRACE("DVB_INVERSION_OFF\n"); 3022 param->inversion = DVB_INVERSION_OFF; 3023 } else if (pInv != NULL && pInv[1] == '1') { 3024 TRACE("DVB_INVERSION_ON\n"); 3025 param->inversion = DVB_INVERSION_ON; 3026 } else { 3027 TRACE("parse error, assuming DVB_INVERSION_OFF\n"); 3028 param->inversion = DVB_INVERSION_OFF; 3029 } 3030 3031 const char *pPolH = strchr(para, 'H'); 3032 if (pPolH == NULL) 3033 pPolH = strchr(para, 'h'); 3034 const char *pPolV = strchr(para, 'V'); 3035 if (pPolV == NULL) 3036 pPolV = strchr(para, 'v'); 3037 if (pPolH != NULL && pPolV == NULL) { 3038 TRACE("DVB_POLARITY_HORIZONTAL\n"); 3039 param->polarity = DVB_POLARITY_HORIZONTAL; 3040 } else if (pPolH == NULL && pPolV != NULL) { 3041 TRACE("DVB_POLARITY_VERTICAL\n"); 3042 param->polarity = DVB_POLARITY_VERTICAL; 3043 } else { 3044 TRACE("parse error, assuming DVB_POLARITY_HORIZONTAL\n"); 3045 param->polarity = DVB_POLARITY_HORIZONTAL; 3046 } 3047 3048 param->frequency = _freq; 3049 param->symbolrate = _srate; 3050 } 3051 3052 return B_OK; 3053 } 3054