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