1 /* 2 * Copyright (c) 2002-2007, Marcus Overhagen <marcus@overhagen.de> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * * Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include <MediaTrack.h> 27 #include <Roster.h> 28 #include <string.h> 29 #include <stdlib.h> 30 #include <new> 31 #include "MediaExtractor.h" 32 #include "PluginManager.h" 33 #include "debug.h" 34 35 //#define TRACE_MEDIA_TRACK 36 #ifdef TRACE_MEDIA_TRACK 37 #ifndef TRACE 38 #define TRACE printf 39 #endif 40 #else 41 #ifndef TRACE 42 #define TRACE(a...) 43 #endif 44 #endif 45 46 #define ERROR(a...) fprintf(stderr, a) 47 48 49 #define CONVERT_TO_INT32 0 // XXX test! this triggers a few bugs! 50 51 // flags used for workarounds 52 enum { 53 FORCE_RAW_AUDIO = 0x0001, 54 FORCE_RAW_VIDEO = 0x0002, 55 FORCE_RAW_AUDIO_INT16_FORMAT = 0x0010, 56 FORCE_RAW_AUDIO_INT32_FORMAT = 0x0020, 57 FORCE_RAW_AUDIO_FLOAT_FORMAT = 0x0040, 58 FORCE_RAW_AUDIO_HOST_ENDIAN = 0x0100, 59 IGNORE_ENCODED_AUDIO = 0x1000, 60 IGNORE_ENCODED_VIDEO = 0x2000, 61 }; 62 63 #define B_MEDIA_DISABLE_FORMAT_TRANSLATION 0x4000 // XXX move this (after name change?) to MediaDefs.h 64 65 class RawDecoderChunkProvider : public ChunkProvider 66 { 67 public: 68 RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size); 69 virtual ~RawDecoderChunkProvider(); 70 71 status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize, media_header *mediaHeader); 72 73 private: 74 Decoder *fDecoder; 75 void *fBuffer; 76 int fBufferSize; 77 int fFrameSize; 78 }; 79 80 81 /************************************************************* 82 * protected BMediaTrack 83 *************************************************************/ 84 85 BMediaTrack::~BMediaTrack() 86 { 87 CALLED(); 88 _plugin_manager.DestroyDecoder(fRawDecoder); 89 _plugin_manager.DestroyDecoder(fDecoder); 90 } 91 92 /************************************************************* 93 * public BMediaTrack 94 *************************************************************/ 95 96 status_t 97 BMediaTrack::InitCheck() const 98 { 99 CALLED(); 100 return fErr; 101 } 102 103 104 status_t 105 BMediaTrack::GetCodecInfo(media_codec_info *mci) const 106 { 107 CALLED(); 108 if (!fDecoder) 109 return B_NO_INIT; 110 111 *mci = fMCI; 112 strlcpy(mci->pretty_name, fMCI.pretty_name, sizeof(mci->pretty_name)); 113 114 return B_OK; 115 } 116 117 118 status_t 119 BMediaTrack::EncodedFormat(media_format *out_format) const 120 { 121 CALLED(); 122 if (!out_format) 123 return B_BAD_VALUE; 124 if (!fExtractor) 125 return B_NO_INIT; 126 127 *out_format = *fExtractor->EncodedFormat(fStream); 128 129 #ifdef TRACE_MEDIA_TRACK 130 char s[200]; 131 string_for_format(*out_format, s, sizeof(s)); 132 printf("BMediaTrack::EncodedFormat: %s\n", s); 133 #endif 134 135 return B_OK; 136 } 137 138 139 // for BeOS R5 compatibilitly 140 extern "C" status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack *self, media_format *inout_format); 141 status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack *self, 142 media_format *inout_format) 143 { 144 return self->DecodedFormat(inout_format, 0); 145 } 146 147 148 status_t 149 BMediaTrack::DecodedFormat(media_format *inout_format, uint32 flags) 150 { 151 CALLED(); 152 if (!inout_format) 153 return B_BAD_VALUE; 154 if (!fExtractor || !fDecoder) 155 return B_NO_INIT; 156 157 _plugin_manager.DestroyDecoder(fRawDecoder); 158 fRawDecoder = 0; 159 160 #ifdef TRACE_MEDIA_TRACK 161 char s[200]; 162 string_for_format(*inout_format, s, sizeof(s)); 163 printf("BMediaTrack::DecodedFormat: req1: %s\n", s); 164 #endif 165 166 if ((fWorkaroundFlags & FORCE_RAW_AUDIO) || ((fWorkaroundFlags & IGNORE_ENCODED_AUDIO) && inout_format->type == B_MEDIA_ENCODED_AUDIO)) { 167 inout_format->type = B_MEDIA_RAW_AUDIO; 168 inout_format->u.raw_audio = media_multi_audio_format::wildcard; 169 } 170 if ((fWorkaroundFlags & FORCE_RAW_VIDEO) || ((fWorkaroundFlags & IGNORE_ENCODED_VIDEO) && inout_format->type == B_MEDIA_ENCODED_VIDEO)) { 171 inout_format->type = B_MEDIA_RAW_VIDEO; 172 inout_format->u.raw_video = media_raw_video_format::wildcard; 173 } 174 if (inout_format->type == B_MEDIA_RAW_AUDIO) { 175 if (fWorkaroundFlags & FORCE_RAW_AUDIO_HOST_ENDIAN) 176 inout_format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; 177 if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT) 178 inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; 179 if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT32_FORMAT) 180 inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; 181 if (fWorkaroundFlags & FORCE_RAW_AUDIO_FLOAT_FORMAT) 182 inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; 183 } 184 185 #ifdef TRACE_MEDIA_TRACK 186 string_for_format(*inout_format, s, sizeof(s)); 187 printf("BMediaTrack::DecodedFormat: req2: %s\n", s); 188 #endif 189 190 media_format requested_format = *inout_format; 191 192 status_t res; 193 194 res = fDecoder->NegotiateOutputFormat(inout_format); 195 196 #ifdef TRACE_MEDIA_TRACK 197 string_for_format(*inout_format, s, sizeof(s)); 198 printf("BMediaTrack::DecodedFormat: nego: %s\n", s); 199 #endif 200 201 if (inout_format->type == 0) 202 debugger("Decoder didn't set output format type"); 203 if (inout_format->type == B_MEDIA_RAW_AUDIO) { 204 if (inout_format->u.raw_audio.byte_order == 0) 205 debugger("Decoder didn't set raw audio output byte order"); 206 if (inout_format->u.raw_audio.format == 0) 207 debugger("Decoder didn't set raw audio output sample format"); 208 if (inout_format->u.raw_audio.buffer_size <= 0) 209 debugger("Decoder didn't set raw audio output buffer size"); 210 } 211 if (inout_format->type == B_MEDIA_RAW_VIDEO) { 212 if (inout_format->u.raw_video.display.format == 0) 213 debugger("Decoder didn't set raw video output color space"); 214 if (inout_format->u.raw_video.display.line_width == 0) 215 debugger("Decoder didn't set raw video output line_width"); 216 if (inout_format->u.raw_video.display.line_count == 0) 217 debugger("Decoder didn't set raw video output line_count"); 218 if (inout_format->u.raw_video.display.bytes_per_row == 0) 219 debugger("Decoder didn't set raw video output bytes_per_row"); 220 } 221 222 if (0 == (flags & B_MEDIA_DISABLE_FORMAT_TRANSLATION)) { 223 if (requested_format.type == B_MEDIA_RAW_AUDIO 224 && inout_format->type == B_MEDIA_RAW_AUDIO 225 && requested_format.u.raw_audio.format != 0 226 && requested_format.u.raw_audio.format != inout_format->u.raw_audio.format) { 227 if (SetupFormatTranslation(*inout_format, &requested_format)) { 228 *inout_format = requested_format; 229 } 230 } 231 } 232 233 // string_for_format(*inout_format, s, sizeof(s)); 234 // printf("BMediaTrack::DecodedFormat: res: %s\n", s); 235 236 return res; 237 } 238 239 240 int64 241 BMediaTrack::CountFrames() const 242 { 243 CALLED(); 244 int64 frames = fExtractor ? fExtractor->CountFrames(fStream) : 0; 245 // printf("BMediaTrack::CountFrames: %Ld\n", frames); 246 return frames; 247 } 248 249 250 bigtime_t 251 BMediaTrack::Duration() const 252 { 253 CALLED(); 254 bigtime_t duration = fExtractor ? fExtractor->Duration(fStream) : 0; 255 // printf("BMediaTrack::Duration: %Ld\n", duration); 256 return duration; 257 } 258 259 260 int64 261 BMediaTrack::CurrentFrame() const 262 { 263 return fCurFrame; 264 } 265 266 267 bigtime_t 268 BMediaTrack::CurrentTime() const 269 { 270 return fCurTime; 271 } 272 273 // BMediaTrack::ReadFrames(char *, long long *, media_header *) 274 // Compatibility for R5 and below. Required by Corum III and Civ:CTP. 275 #if __GNUC__ < 3 276 277 extern "C" status_t 278 ReadFrames__11BMediaTrackPcPxP12media_header(BMediaTrack *self, 279 char *out_buffer, 280 int64 *out_frameCount, 281 media_header *mh) 282 { 283 return self->ReadFrames(out_buffer, out_frameCount, mh, 0); 284 } 285 286 #endif // __GNUC__ < 3 287 288 status_t 289 BMediaTrack::ReadFrames(void *out_buffer, 290 int64 *out_frameCount, 291 media_header *mh) 292 { 293 return ReadFrames(out_buffer, out_frameCount, mh, 0); 294 } 295 296 297 status_t 298 BMediaTrack::ReadFrames(void *out_buffer, 299 int64 *out_frameCount, 300 media_header *mh /* = 0 */, 301 media_decode_info *info /* = 0 */) 302 { 303 // CALLED(); 304 if (!fDecoder) 305 return B_NO_INIT; 306 if (!out_buffer || !out_frameCount) 307 return B_BAD_VALUE; 308 309 status_t result; 310 media_header header; 311 312 memset(&header, 0, sizeof(header)); // always clear it first, as the decoder doesn't set all fields 313 314 if (fRawDecoder) 315 result = fRawDecoder->Decode(out_buffer, out_frameCount, &header, info); 316 else 317 result = fDecoder->Decode(out_buffer, out_frameCount, &header, info); 318 if (result == B_OK) { 319 fCurFrame += *out_frameCount; 320 fCurTime = header.start_time; 321 } else { 322 ERROR("BMediaTrack::ReadFrames: decoder returned error 0x%08lx (%s)\n", result, strerror(result)); 323 *out_frameCount = 0; 324 } 325 if (mh) 326 *mh = header; 327 328 // PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, %Ld frames\n", fStream, header.start_time / 1000000, header.start_time % 1000000, *out_frameCount); 329 330 return result; 331 } 332 333 334 status_t 335 BMediaTrack::ReplaceFrames(const void *in_buffer, 336 int64 *io_frameCount, 337 const media_header *mh) 338 { 339 UNIMPLEMENTED(); 340 341 return B_OK; 342 } 343 344 345 status_t 346 BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags) 347 { 348 CALLED(); 349 if (!fDecoder || !fExtractor) 350 return B_NO_INIT; 351 if (!inout_time) 352 return B_BAD_VALUE; 353 354 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 355 | B_MEDIA_SEEK_TO_TIME; 356 bigtime_t seekTime = *inout_time; 357 358 int64 frame = 0; 359 bigtime_t time = seekTime; 360 status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); 361 if (result != B_OK) { 362 ERROR("BMediaTrack::SeekToTime: extractor seek failed\n"); 363 return result; 364 } 365 366 // TODO: Codecs cannot actually "seek" in the stream, all they 367 // can do is "reset" their decoder state, since they are made 368 // aware of the fact that there will be a jump in the data. Maybe 369 // rename the codec method? 370 result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time); 371 if (result != B_OK) { 372 ERROR("BMediaTrack::SeekToTime: decoder seek failed\n"); 373 return result; 374 } 375 376 if (fRawDecoder) { 377 result = fRawDecoder->Seek(seekTo, 0, &frame, seekTime, &time); 378 if (result != B_OK) { 379 ERROR("BMediaTrack::SeekToTime: raw decoder seek failed\n"); 380 return result; 381 } 382 } 383 384 *inout_time = time; 385 fCurFrame = frame; 386 fCurTime = time; 387 388 PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", seekTime / 1000000.0, *inout_time / 1000000.0); 389 390 return B_OK; 391 } 392 393 394 status_t 395 BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags) 396 { 397 CALLED(); 398 if (!fDecoder || !fExtractor) 399 return B_NO_INIT; 400 if (!inout_frame) 401 return B_BAD_VALUE; 402 403 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 404 | B_MEDIA_SEEK_TO_FRAME; 405 int64 seekFrame = *inout_frame; 406 407 int64 frame = seekFrame; 408 bigtime_t time = 0; 409 status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); 410 if (result != B_OK) { 411 ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n"); 412 return result; 413 } 414 415 // TODO: Codecs cannot actually "seek" in the stream, all they 416 // can do is "reset" their decoder state, since they are made 417 // aware of the fact that there will be a jump in the data. Maybe 418 // rename the codec method? 419 result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time); 420 if (result != B_OK) { 421 ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n"); 422 return result; 423 } 424 425 if (fRawDecoder) { 426 result = fRawDecoder->Seek(seekTo, seekFrame, &frame, 0, &time); 427 if (result != B_OK) { 428 ERROR("BMediaTrack::SeekToFrame: raw decoder seek failed\n"); 429 return result; 430 } 431 } 432 433 *inout_frame = frame; 434 fCurFrame = frame; 435 fCurTime = time; 436 437 PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %Ld, result %Ld\n", seekFrame, *inout_frame); 438 439 return B_OK; 440 } 441 442 443 status_t 444 BMediaTrack::FindKeyFrameForTime(bigtime_t *inoutTime, int32 flags) const 445 { 446 CALLED(); 447 if (!fExtractor) 448 return B_NO_INIT; 449 if (!inoutTime) 450 return B_BAD_VALUE; 451 452 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 453 | B_MEDIA_SEEK_TO_TIME; 454 455 int64 frame = 0; 456 // dummy frame, will be ignored because of flags 457 status_t result = fExtractor->FindKeyFrame(fStream, seekTo, &frame, 458 inoutTime); 459 if (result != B_OK) { 460 ERROR("BMediaTrack::FindKeyFrameForTime: extractor seek failed: %s\n", 461 strerror(result)); 462 return result; 463 } 464 465 return B_OK; 466 } 467 468 469 status_t 470 BMediaTrack::FindKeyFrameForFrame(int64 *inoutFrame, 471 int32 flags) const 472 { 473 CALLED(); 474 if (!fExtractor) 475 return B_NO_INIT; 476 if (!inoutFrame) 477 return B_BAD_VALUE; 478 479 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 480 | B_MEDIA_SEEK_TO_FRAME; 481 482 bigtime_t time = 0; 483 // dummy time, will be ignored because of flags 484 status_t result = fExtractor->FindKeyFrame(fStream, seekTo, inoutFrame, 485 &time); 486 if (result != B_OK) { 487 ERROR("BMediaTrack::FindKeyFrameForFrame: extractor seek failed: %s\n", 488 strerror(result)); 489 return result; 490 } 491 492 return B_OK; 493 } 494 495 496 status_t 497 BMediaTrack::ReadChunk(char **out_buffer, 498 int32 *out_size, 499 media_header *mh /* = 0 */) 500 { 501 CALLED(); 502 if (!fExtractor) 503 return B_NO_INIT; 504 if (!out_buffer || !out_size) 505 return B_BAD_VALUE; 506 507 status_t result; 508 media_header header; 509 const void *buffer; 510 size_t size; 511 512 memset(&header, 0, sizeof(header)); // always clear it first, as the reader doesn't set all fields 513 514 result = fExtractor->GetNextChunk(fStream, &buffer, &size, &header); 515 if (result == B_OK) { 516 *out_buffer = const_cast<char *>(static_cast<const char *>(buffer)); // yes this *is* ugly 517 *out_size = size; 518 fCurTime = header.start_time; 519 if (mh) 520 *mh = header; 521 } 522 523 return result; 524 } 525 526 527 status_t 528 BMediaTrack::AddCopyright(const char *data) 529 { 530 UNIMPLEMENTED(); 531 532 return B_OK; 533 } 534 535 536 status_t 537 BMediaTrack::AddTrackInfo(uint32 code, 538 const void *data, 539 size_t size, 540 uint32 flags) 541 { 542 UNIMPLEMENTED(); 543 544 return B_OK; 545 } 546 547 548 status_t 549 BMediaTrack::WriteFrames(const void *data, 550 int32 num_frames, 551 int32 flags) 552 { 553 UNIMPLEMENTED(); 554 555 return B_OK; 556 } 557 558 559 status_t 560 BMediaTrack::WriteFrames(const void *data, 561 int64 num_frames, 562 media_encode_info *info) 563 { 564 UNIMPLEMENTED(); 565 566 return B_OK; 567 } 568 569 570 status_t 571 BMediaTrack::WriteChunk(const void *data, 572 size_t size, 573 uint32 flags) 574 { 575 UNIMPLEMENTED(); 576 577 return B_OK; 578 } 579 580 581 status_t 582 BMediaTrack::WriteChunk(const void *data, 583 size_t size, 584 media_encode_info *info) 585 { 586 UNIMPLEMENTED(); 587 588 return B_OK; 589 } 590 591 592 status_t 593 BMediaTrack::Flush() 594 { 595 UNIMPLEMENTED(); 596 597 return B_OK; 598 } 599 600 601 // deprecated BeOS R5 API 602 BParameterWeb * 603 BMediaTrack::Web() 604 { 605 UNIMPLEMENTED(); 606 return NULL; 607 } 608 609 610 // returns a copy of the parameter web 611 status_t 612 BMediaTrack::GetParameterWeb(BParameterWeb** outWeb) 613 { 614 UNIMPLEMENTED(); 615 616 return B_OK; 617 } 618 619 620 status_t 621 BMediaTrack::GetParameterValue(int32 id, 622 void *valu, 623 size_t *size) 624 { 625 UNIMPLEMENTED(); 626 627 return B_ERROR; 628 } 629 630 631 status_t 632 BMediaTrack::SetParameterValue(int32 id, 633 const void *valu, 634 size_t size) 635 { 636 UNIMPLEMENTED(); 637 638 return B_ERROR; 639 } 640 641 642 BView * 643 BMediaTrack::GetParameterView() 644 { 645 UNIMPLEMENTED(); 646 return NULL; 647 } 648 649 650 status_t 651 BMediaTrack::GetQuality(float *quality) 652 { 653 UNIMPLEMENTED(); 654 655 return B_ERROR; 656 } 657 658 659 status_t 660 BMediaTrack::SetQuality(float quality) 661 { 662 UNIMPLEMENTED(); 663 664 return B_ERROR; 665 } 666 667 668 status_t 669 BMediaTrack::GetEncodeParameters(encode_parameters *parameters) const 670 { 671 UNIMPLEMENTED(); 672 673 return B_ERROR; 674 } 675 676 677 status_t 678 BMediaTrack::SetEncodeParameters(encode_parameters *parameters) 679 { 680 UNIMPLEMENTED(); 681 682 return B_ERROR; 683 } 684 685 686 status_t 687 BMediaTrack::Perform(int32 selector, 688 void *data) 689 { 690 UNIMPLEMENTED(); 691 692 return B_ERROR; 693 } 694 695 /************************************************************* 696 * private BMediaTrack 697 *************************************************************/ 698 699 BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor, 700 int32 stream) 701 { 702 CALLED(); 703 fWorkaroundFlags = 0; 704 fDecoder = NULL; 705 fRawDecoder = NULL; 706 fExtractor = extractor; 707 fStream = stream; 708 fErr = B_OK; 709 710 SetupWorkaround(); 711 712 status_t ret = fExtractor->CreateDecoder(fStream, &fDecoder, &fMCI); 713 if (ret != B_OK) { 714 TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: " 715 "%s\n", strerror(ret)); 716 // we do not set fErr here, because ReadChunk should still work 717 fDecoder = NULL; 718 return; 719 } 720 721 fCurFrame = 0; 722 fCurTime = 0; 723 724 // not used: 725 fEncoder = NULL; 726 fEncoderID = 0; 727 fWriter = NULL; 728 } 729 730 731 BMediaTrack::BMediaTrack(BPrivate::MediaWriter *writer, 732 int32 stream_num, 733 media_format *in_format, 734 BPrivate::media::Encoder *encoder, 735 media_codec_info *mci) 736 { 737 UNIMPLEMENTED(); 738 } 739 740 741 // Does nothing, returns B_ERROR, for Zeta compatiblity only 742 status_t 743 BMediaTrack::ControlCodec(int32 selector, void *io_data, size_t size) 744 { 745 return B_ERROR; 746 } 747 748 749 void 750 BMediaTrack::SetupWorkaround() 751 { 752 app_info ainfo; 753 thread_info tinfo; 754 755 get_thread_info(find_thread(0), &tinfo); 756 be_roster->GetRunningAppInfo(tinfo.team, &ainfo); 757 758 if (strcmp(ainfo.signature, "application/x-vnd.marcone-soundplay") == 0) { 759 fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT | FORCE_RAW_AUDIO_HOST_ENDIAN; 760 printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n"); 761 } 762 if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) { 763 fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO; 764 printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n"); 765 } 766 767 #if CONVERT_TO_INT32 // XXX test 768 if (!(fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT)) 769 fWorkaroundFlags |= FORCE_RAW_AUDIO_INT32_FORMAT; 770 #endif 771 } 772 773 bool 774 BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to) 775 { 776 _plugin_manager.DestroyDecoder(fRawDecoder); 777 fRawDecoder = NULL; 778 779 #ifdef TRACE_MEDIA_TRACK 780 char s[200]; 781 string_for_format(from, s, sizeof(s)); 782 printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s); 783 #endif 784 785 status_t res = _plugin_manager.CreateDecoder(&fRawDecoder, from); 786 if (res != B_OK) { 787 ERROR("BMediaTrack::SetupFormatTranslation: CreateDecoder failed\n"); 788 return false; 789 } 790 791 // XXX video? 792 int buffer_size = from.u.raw_audio.buffer_size; 793 int frame_size = (from.u.raw_audio.format & 15) * from.u.raw_audio.channel_count; 794 media_format notconstFrom = from; 795 796 ChunkProvider *chunkProvider = new(std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size, frame_size); 797 if (!chunkProvider) { 798 ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk provider\n"); 799 goto error; 800 } 801 fRawDecoder->SetChunkProvider(chunkProvider); 802 803 res = fRawDecoder->Setup(¬constFrom, 0, 0); 804 if (res != B_OK) { 805 ERROR("BMediaTrack::SetupFormatTranslation: Setup failed\n"); 806 goto error; 807 } 808 809 #ifdef TRACE_MEDIA_TRACK 810 string_for_format(*to, s, sizeof(s)); 811 printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s); 812 #endif 813 814 res = fRawDecoder->NegotiateOutputFormat(to); 815 if (res != B_OK) { 816 ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat failed\n"); 817 goto error; 818 } 819 820 #ifdef TRACE_MEDIA_TRACK 821 string_for_format(*to, s, sizeof(s)); 822 printf("BMediaTrack::SetupFormatTranslation: res: %s\n", s); 823 #endif 824 825 return true; 826 827 error: 828 _plugin_manager.DestroyDecoder(fRawDecoder); 829 fRawDecoder = NULL; 830 return false; 831 } 832 833 /* 834 // unimplemented 835 BMediaTrack::BMediaTrack() 836 BMediaTrack::BMediaTrack(const BMediaTrack &) 837 BMediaTrack &BMediaTrack::operator=(const BMediaTrack &) 838 */ 839 840 status_t BMediaTrack::_Reserved_BMediaTrack_0(int32 arg, ...) { return B_ERROR; } 841 status_t BMediaTrack::_Reserved_BMediaTrack_1(int32 arg, ...) { return B_ERROR; } 842 status_t BMediaTrack::_Reserved_BMediaTrack_2(int32 arg, ...) { return B_ERROR; } 843 status_t BMediaTrack::_Reserved_BMediaTrack_3(int32 arg, ...) { return B_ERROR; } 844 status_t BMediaTrack::_Reserved_BMediaTrack_4(int32 arg, ...) { return B_ERROR; } 845 status_t BMediaTrack::_Reserved_BMediaTrack_5(int32 arg, ...) { return B_ERROR; } 846 status_t BMediaTrack::_Reserved_BMediaTrack_6(int32 arg, ...) { return B_ERROR; } 847 status_t BMediaTrack::_Reserved_BMediaTrack_7(int32 arg, ...) { return B_ERROR; } 848 status_t BMediaTrack::_Reserved_BMediaTrack_8(int32 arg, ...) { return B_ERROR; } 849 status_t BMediaTrack::_Reserved_BMediaTrack_9(int32 arg, ...) { return B_ERROR; } 850 status_t BMediaTrack::_Reserved_BMediaTrack_10(int32 arg, ...) { return B_ERROR; } 851 status_t BMediaTrack::_Reserved_BMediaTrack_11(int32 arg, ...) { return B_ERROR; } 852 status_t BMediaTrack::_Reserved_BMediaTrack_12(int32 arg, ...) { return B_ERROR; } 853 status_t BMediaTrack::_Reserved_BMediaTrack_13(int32 arg, ...) { return B_ERROR; } 854 status_t BMediaTrack::_Reserved_BMediaTrack_14(int32 arg, ...) { return B_ERROR; } 855 status_t BMediaTrack::_Reserved_BMediaTrack_15(int32 arg, ...) { return B_ERROR; } 856 status_t BMediaTrack::_Reserved_BMediaTrack_16(int32 arg, ...) { return B_ERROR; } 857 status_t BMediaTrack::_Reserved_BMediaTrack_17(int32 arg, ...) { return B_ERROR; } 858 status_t BMediaTrack::_Reserved_BMediaTrack_18(int32 arg, ...) { return B_ERROR; } 859 status_t BMediaTrack::_Reserved_BMediaTrack_19(int32 arg, ...) { return B_ERROR; } 860 status_t BMediaTrack::_Reserved_BMediaTrack_20(int32 arg, ...) { return B_ERROR; } 861 status_t BMediaTrack::_Reserved_BMediaTrack_21(int32 arg, ...) { return B_ERROR; } 862 status_t BMediaTrack::_Reserved_BMediaTrack_22(int32 arg, ...) { return B_ERROR; } 863 status_t BMediaTrack::_Reserved_BMediaTrack_23(int32 arg, ...) { return B_ERROR; } 864 status_t BMediaTrack::_Reserved_BMediaTrack_24(int32 arg, ...) { return B_ERROR; } 865 status_t BMediaTrack::_Reserved_BMediaTrack_25(int32 arg, ...) { return B_ERROR; } 866 status_t BMediaTrack::_Reserved_BMediaTrack_26(int32 arg, ...) { return B_ERROR; } 867 status_t BMediaTrack::_Reserved_BMediaTrack_27(int32 arg, ...) { return B_ERROR; } 868 status_t BMediaTrack::_Reserved_BMediaTrack_28(int32 arg, ...) { return B_ERROR; } 869 status_t BMediaTrack::_Reserved_BMediaTrack_29(int32 arg, ...) { return B_ERROR; } 870 status_t BMediaTrack::_Reserved_BMediaTrack_30(int32 arg, ...) { return B_ERROR; } 871 status_t BMediaTrack::_Reserved_BMediaTrack_31(int32 arg, ...) { return B_ERROR; } 872 status_t BMediaTrack::_Reserved_BMediaTrack_32(int32 arg, ...) { return B_ERROR; } 873 status_t BMediaTrack::_Reserved_BMediaTrack_33(int32 arg, ...) { return B_ERROR; } 874 status_t BMediaTrack::_Reserved_BMediaTrack_34(int32 arg, ...) { return B_ERROR; } 875 status_t BMediaTrack::_Reserved_BMediaTrack_35(int32 arg, ...) { return B_ERROR; } 876 status_t BMediaTrack::_Reserved_BMediaTrack_36(int32 arg, ...) { return B_ERROR; } 877 status_t BMediaTrack::_Reserved_BMediaTrack_37(int32 arg, ...) { return B_ERROR; } 878 status_t BMediaTrack::_Reserved_BMediaTrack_38(int32 arg, ...) { return B_ERROR; } 879 status_t BMediaTrack::_Reserved_BMediaTrack_39(int32 arg, ...) { return B_ERROR; } 880 status_t BMediaTrack::_Reserved_BMediaTrack_40(int32 arg, ...) { return B_ERROR; } 881 status_t BMediaTrack::_Reserved_BMediaTrack_41(int32 arg, ...) { return B_ERROR; } 882 status_t BMediaTrack::_Reserved_BMediaTrack_42(int32 arg, ...) { return B_ERROR; } 883 status_t BMediaTrack::_Reserved_BMediaTrack_43(int32 arg, ...) { return B_ERROR; } 884 status_t BMediaTrack::_Reserved_BMediaTrack_44(int32 arg, ...) { return B_ERROR; } 885 status_t BMediaTrack::_Reserved_BMediaTrack_45(int32 arg, ...) { return B_ERROR; } 886 status_t BMediaTrack::_Reserved_BMediaTrack_46(int32 arg, ...) { return B_ERROR; } 887 status_t BMediaTrack::_Reserved_BMediaTrack_47(int32 arg, ...) { return B_ERROR; } 888 889 890 RawDecoderChunkProvider::RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size) 891 { 892 // printf("RawDecoderChunkProvider: buffer_size %d, frame_size %d\n", buffer_size, frame_size); 893 fDecoder = decoder; 894 fFrameSize = frame_size; 895 fBufferSize = buffer_size; 896 fBuffer = malloc(buffer_size); 897 } 898 899 RawDecoderChunkProvider::~RawDecoderChunkProvider() 900 { 901 free(fBuffer); 902 } 903 904 status_t 905 RawDecoderChunkProvider::GetNextChunk(const void **chunkBuffer, size_t *chunkSize, 906 media_header *mediaHeader) 907 { 908 int64 frames; 909 media_decode_info info; 910 status_t res = fDecoder->Decode(fBuffer, &frames, mediaHeader, &info); 911 if (res == B_OK) { 912 *chunkBuffer = fBuffer; 913 *chunkSize = frames * fFrameSize; 914 // printf("RawDecoderChunkProvider::GetNextChunk, %Ld frames, %ld bytes, start-time %Ld\n", frames, *chunkSize, mediaHeader->start_time); 915 } else { 916 ERROR("RawDecoderChunkProvider::GetNextChunk failed\n"); 917 } 918 return res; 919 } 920