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 snprintf(mci->pretty_name, sizeof(mci->pretty_name), "Haiku Media Kit:\n%s", fMCI.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 274 status_t 275 BMediaTrack::ReadFrames(void *out_buffer, 276 int64 *out_frameCount, 277 media_header *mh) 278 { 279 return ReadFrames(out_buffer, out_frameCount, mh, 0); 280 } 281 282 283 status_t 284 BMediaTrack::ReadFrames(void *out_buffer, 285 int64 *out_frameCount, 286 media_header *mh /* = 0 */, 287 media_decode_info *info /* = 0 */) 288 { 289 // CALLED(); 290 if (!fDecoder) 291 return B_NO_INIT; 292 if (!out_buffer || !out_frameCount) 293 return B_BAD_VALUE; 294 295 status_t result; 296 media_header header; 297 298 memset(&header, 0, sizeof(header)); // always clear it first, as the decoder doesn't set all fields 299 300 if (fRawDecoder) 301 result = fRawDecoder->Decode(out_buffer, out_frameCount, &header, info); 302 else 303 result = fDecoder->Decode(out_buffer, out_frameCount, &header, info); 304 if (result == B_OK) { 305 fCurFrame += *out_frameCount; 306 fCurTime = header.start_time; 307 } else { 308 ERROR("BMediaTrack::ReadFrames: decoder returned error 0x%08lx (%s)\n", result, strerror(result)); 309 *out_frameCount = 0; 310 } 311 if (mh) 312 *mh = header; 313 314 // PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, %Ld frames\n", fStream, header.start_time / 1000000, header.start_time % 1000000, *out_frameCount); 315 316 return result; 317 } 318 319 320 status_t 321 BMediaTrack::ReplaceFrames(const void *in_buffer, 322 int64 *io_frameCount, 323 const media_header *mh) 324 { 325 UNIMPLEMENTED(); 326 327 return B_OK; 328 } 329 330 331 status_t 332 BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags) 333 { 334 CALLED(); 335 if (!fDecoder || !fExtractor) 336 return B_NO_INIT; 337 if (!inout_time) 338 return B_BAD_VALUE; 339 340 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 341 | B_MEDIA_SEEK_TO_TIME; 342 bigtime_t seekTime = *inout_time; 343 344 int64 frame = 0; 345 bigtime_t time = seekTime; 346 status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); 347 if (result != B_OK) { 348 ERROR("BMediaTrack::SeekToTime: extractor seek failed\n"); 349 return result; 350 } 351 352 // TODO: Codecs cannot actually "seek" in the stream, all they 353 // can do is "reset" their decoder state, since they are made 354 // aware of the fact that there will be a jump in the data. Maybe 355 // rename the codec method? 356 result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time); 357 if (result != B_OK) { 358 ERROR("BMediaTrack::SeekToTime: decoder seek failed\n"); 359 return result; 360 } 361 362 if (fRawDecoder) { 363 result = fRawDecoder->Seek(seekTo, 0, &frame, seekTime, &time); 364 if (result != B_OK) { 365 ERROR("BMediaTrack::SeekToTime: raw decoder seek failed\n"); 366 return result; 367 } 368 } 369 370 *inout_time = time; 371 fCurFrame = frame; 372 fCurTime = time; 373 374 PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", seekTime / 1000000.0, *inout_time / 1000000.0); 375 376 return B_OK; 377 } 378 379 380 status_t 381 BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags) 382 { 383 CALLED(); 384 if (!fDecoder || !fExtractor) 385 return B_NO_INIT; 386 if (!inout_frame) 387 return B_BAD_VALUE; 388 389 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 390 | B_MEDIA_SEEK_TO_FRAME; 391 int64 seekFrame = *inout_frame; 392 393 int64 frame = seekFrame; 394 bigtime_t time = 0; 395 status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); 396 if (result != B_OK) { 397 ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n"); 398 return result; 399 } 400 401 // TODO: Codecs cannot actually "seek" in the stream, all they 402 // can do is "reset" their decoder state, since they are made 403 // aware of the fact that there will be a jump in the data. Maybe 404 // rename the codec method? 405 result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time); 406 if (result != B_OK) { 407 ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n"); 408 return result; 409 } 410 411 if (fRawDecoder) { 412 result = fRawDecoder->Seek(seekTo, seekFrame, &frame, 0, &time); 413 if (result != B_OK) { 414 ERROR("BMediaTrack::SeekToFrame: raw decoder seek failed\n"); 415 return result; 416 } 417 } 418 419 *inout_frame = frame; 420 fCurFrame = frame; 421 fCurTime = time; 422 423 PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %Ld, result %Ld\n", seekFrame, *inout_frame); 424 425 return B_OK; 426 } 427 428 429 status_t 430 BMediaTrack::FindKeyFrameForTime(bigtime_t *inoutTime, int32 flags) const 431 { 432 CALLED(); 433 if (!fExtractor) 434 return B_NO_INIT; 435 if (!inoutTime) 436 return B_BAD_VALUE; 437 438 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 439 | B_MEDIA_SEEK_TO_TIME; 440 441 int64 frame = 0; 442 // dummy frame, will be ignored because of flags 443 status_t result = fExtractor->FindKeyFrame(fStream, seekTo, &frame, 444 inoutTime); 445 if (result != B_OK) { 446 ERROR("BMediaTrack::FindKeyFrameForTime: extractor seek failed: %s\n", 447 strerror(result)); 448 return result; 449 } 450 451 return B_OK; 452 } 453 454 455 status_t 456 BMediaTrack::FindKeyFrameForFrame(int64 *inoutFrame, 457 int32 flags) const 458 { 459 CALLED(); 460 if (!fExtractor) 461 return B_NO_INIT; 462 if (!inoutFrame) 463 return B_BAD_VALUE; 464 465 uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) 466 | B_MEDIA_SEEK_TO_FRAME; 467 468 bigtime_t time = 0; 469 // dummy time, will be ignored because of flags 470 status_t result = fExtractor->FindKeyFrame(fStream, seekTo, inoutFrame, 471 &time); 472 if (result != B_OK) { 473 ERROR("BMediaTrack::FindKeyFrameForFrame: extractor seek failed: %s\n", 474 strerror(result)); 475 return result; 476 } 477 478 return B_OK; 479 } 480 481 482 status_t 483 BMediaTrack::ReadChunk(char **out_buffer, 484 int32 *out_size, 485 media_header *mh /* = 0 */) 486 { 487 CALLED(); 488 if (!fExtractor) 489 return B_NO_INIT; 490 if (!out_buffer || !out_size) 491 return B_BAD_VALUE; 492 493 status_t result; 494 media_header header; 495 const void *buffer; 496 size_t size; 497 498 memset(&header, 0, sizeof(header)); // always clear it first, as the reader doesn't set all fields 499 500 result = fExtractor->GetNextChunk(fStream, &buffer, &size, &header); 501 if (result == B_OK) { 502 *out_buffer = const_cast<char *>(static_cast<const char *>(buffer)); // yes this *is* ugly 503 *out_size = size; 504 fCurTime = header.start_time; 505 if (mh) 506 *mh = header; 507 } 508 509 return result; 510 } 511 512 513 status_t 514 BMediaTrack::AddCopyright(const char *data) 515 { 516 UNIMPLEMENTED(); 517 518 return B_OK; 519 } 520 521 522 status_t 523 BMediaTrack::AddTrackInfo(uint32 code, 524 const void *data, 525 size_t size, 526 uint32 flags) 527 { 528 UNIMPLEMENTED(); 529 530 return B_OK; 531 } 532 533 534 status_t 535 BMediaTrack::WriteFrames(const void *data, 536 int32 num_frames, 537 int32 flags) 538 { 539 UNIMPLEMENTED(); 540 541 return B_OK; 542 } 543 544 545 status_t 546 BMediaTrack::WriteFrames(const void *data, 547 int64 num_frames, 548 media_encode_info *info) 549 { 550 UNIMPLEMENTED(); 551 552 return B_OK; 553 } 554 555 556 status_t 557 BMediaTrack::WriteChunk(const void *data, 558 size_t size, 559 uint32 flags) 560 { 561 UNIMPLEMENTED(); 562 563 return B_OK; 564 } 565 566 567 status_t 568 BMediaTrack::WriteChunk(const void *data, 569 size_t size, 570 media_encode_info *info) 571 { 572 UNIMPLEMENTED(); 573 574 return B_OK; 575 } 576 577 578 status_t 579 BMediaTrack::Flush() 580 { 581 UNIMPLEMENTED(); 582 583 return B_OK; 584 } 585 586 587 // deprecated BeOS R5 API 588 BParameterWeb * 589 BMediaTrack::Web() 590 { 591 UNIMPLEMENTED(); 592 return NULL; 593 } 594 595 596 // returns a copy of the parameter web 597 status_t 598 BMediaTrack::GetParameterWeb(BParameterWeb** outWeb) 599 { 600 UNIMPLEMENTED(); 601 602 return B_OK; 603 } 604 605 606 status_t 607 BMediaTrack::GetParameterValue(int32 id, 608 void *valu, 609 size_t *size) 610 { 611 UNIMPLEMENTED(); 612 613 return B_ERROR; 614 } 615 616 617 status_t 618 BMediaTrack::SetParameterValue(int32 id, 619 const void *valu, 620 size_t size) 621 { 622 UNIMPLEMENTED(); 623 624 return B_ERROR; 625 } 626 627 628 BView * 629 BMediaTrack::GetParameterView() 630 { 631 UNIMPLEMENTED(); 632 return NULL; 633 } 634 635 636 status_t 637 BMediaTrack::GetQuality(float *quality) 638 { 639 UNIMPLEMENTED(); 640 641 return B_ERROR; 642 } 643 644 645 status_t 646 BMediaTrack::SetQuality(float quality) 647 { 648 UNIMPLEMENTED(); 649 650 return B_ERROR; 651 } 652 653 654 status_t 655 BMediaTrack::GetEncodeParameters(encode_parameters *parameters) const 656 { 657 UNIMPLEMENTED(); 658 659 return B_ERROR; 660 } 661 662 663 status_t 664 BMediaTrack::SetEncodeParameters(encode_parameters *parameters) 665 { 666 UNIMPLEMENTED(); 667 668 return B_ERROR; 669 } 670 671 672 status_t 673 BMediaTrack::Perform(int32 selector, 674 void *data) 675 { 676 UNIMPLEMENTED(); 677 678 return B_ERROR; 679 } 680 681 /************************************************************* 682 * private BMediaTrack 683 *************************************************************/ 684 685 BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor, 686 int32 stream) 687 { 688 CALLED(); 689 fWorkaroundFlags = 0; 690 fDecoder = NULL; 691 fRawDecoder = NULL; 692 fExtractor = extractor; 693 fStream = stream; 694 fErr = B_OK; 695 696 SetupWorkaround(); 697 698 if (fExtractor->CreateDecoder(fStream, &fDecoder, &fMCI) != B_OK) { 699 TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed\n"); 700 // we do not set fErr here, because ReadChunk should still work 701 fDecoder = 0; 702 return; 703 } 704 705 fCurFrame = 0; 706 fCurTime = 0; 707 708 // not used: 709 fEncoder = 0; 710 fEncoderID = 0; 711 fWriter = 0; 712 } 713 714 715 BMediaTrack::BMediaTrack(BPrivate::MediaWriter *writer, 716 int32 stream_num, 717 media_format *in_format, 718 BPrivate::media::Encoder *encoder, 719 media_codec_info *mci) 720 { 721 UNIMPLEMENTED(); 722 } 723 724 725 // Does nothing, returns B_ERROR, for Zeta compatiblity only 726 status_t 727 BMediaTrack::ControlCodec(int32 selector, void *io_data, size_t size) 728 { 729 return B_ERROR; 730 } 731 732 733 void 734 BMediaTrack::SetupWorkaround() 735 { 736 app_info ainfo; 737 thread_info tinfo; 738 739 get_thread_info(find_thread(0), &tinfo); 740 be_roster->GetRunningAppInfo(tinfo.team, &ainfo); 741 742 if (strcmp(ainfo.signature, "application/x-vnd.marcone-soundplay") == 0) { 743 fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT | FORCE_RAW_AUDIO_HOST_ENDIAN; 744 printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n"); 745 } 746 if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) { 747 fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO; 748 printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n"); 749 } 750 751 #if CONVERT_TO_INT32 // XXX test 752 if (!(fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT)) 753 fWorkaroundFlags |= FORCE_RAW_AUDIO_INT32_FORMAT; 754 #endif 755 } 756 757 bool 758 BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to) 759 { 760 _plugin_manager.DestroyDecoder(fRawDecoder); 761 fRawDecoder = NULL; 762 763 #ifdef TRACE_MEDIA_TRACK 764 char s[200]; 765 string_for_format(from, s, sizeof(s)); 766 printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s); 767 #endif 768 769 status_t res = _plugin_manager.CreateDecoder(&fRawDecoder, from); 770 if (res != B_OK) { 771 ERROR("BMediaTrack::SetupFormatTranslation: CreateDecoder failed\n"); 772 return false; 773 } 774 775 // XXX video? 776 int buffer_size = from.u.raw_audio.buffer_size; 777 int frame_size = (from.u.raw_audio.format & 15) * from.u.raw_audio.channel_count; 778 media_format notconstFrom = from; 779 780 ChunkProvider *chunkProvider = new(std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size, frame_size); 781 if (!chunkProvider) { 782 ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk provider\n"); 783 goto error; 784 } 785 fRawDecoder->SetChunkProvider(chunkProvider); 786 787 res = fRawDecoder->Setup(¬constFrom, 0, 0); 788 if (res != B_OK) { 789 ERROR("BMediaTrack::SetupFormatTranslation: Setup failed\n"); 790 goto error; 791 } 792 793 #ifdef TRACE_MEDIA_TRACK 794 string_for_format(*to, s, sizeof(s)); 795 printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s); 796 #endif 797 798 res = fRawDecoder->NegotiateOutputFormat(to); 799 if (res != B_OK) { 800 ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat failed\n"); 801 goto error; 802 } 803 804 #ifdef TRACE_MEDIA_TRACK 805 string_for_format(*to, s, sizeof(s)); 806 printf("BMediaTrack::SetupFormatTranslation: res: %s\n", s); 807 #endif 808 809 return true; 810 811 error: 812 _plugin_manager.DestroyDecoder(fRawDecoder); 813 fRawDecoder = NULL; 814 return false; 815 } 816 817 /* 818 // unimplemented 819 BMediaTrack::BMediaTrack() 820 BMediaTrack::BMediaTrack(const BMediaTrack &) 821 BMediaTrack &BMediaTrack::operator=(const BMediaTrack &) 822 */ 823 824 status_t BMediaTrack::_Reserved_BMediaTrack_0(int32 arg, ...) { return B_ERROR; } 825 status_t BMediaTrack::_Reserved_BMediaTrack_1(int32 arg, ...) { return B_ERROR; } 826 status_t BMediaTrack::_Reserved_BMediaTrack_2(int32 arg, ...) { return B_ERROR; } 827 status_t BMediaTrack::_Reserved_BMediaTrack_3(int32 arg, ...) { return B_ERROR; } 828 status_t BMediaTrack::_Reserved_BMediaTrack_4(int32 arg, ...) { return B_ERROR; } 829 status_t BMediaTrack::_Reserved_BMediaTrack_5(int32 arg, ...) { return B_ERROR; } 830 status_t BMediaTrack::_Reserved_BMediaTrack_6(int32 arg, ...) { return B_ERROR; } 831 status_t BMediaTrack::_Reserved_BMediaTrack_7(int32 arg, ...) { return B_ERROR; } 832 status_t BMediaTrack::_Reserved_BMediaTrack_8(int32 arg, ...) { return B_ERROR; } 833 status_t BMediaTrack::_Reserved_BMediaTrack_9(int32 arg, ...) { return B_ERROR; } 834 status_t BMediaTrack::_Reserved_BMediaTrack_10(int32 arg, ...) { return B_ERROR; } 835 status_t BMediaTrack::_Reserved_BMediaTrack_11(int32 arg, ...) { return B_ERROR; } 836 status_t BMediaTrack::_Reserved_BMediaTrack_12(int32 arg, ...) { return B_ERROR; } 837 status_t BMediaTrack::_Reserved_BMediaTrack_13(int32 arg, ...) { return B_ERROR; } 838 status_t BMediaTrack::_Reserved_BMediaTrack_14(int32 arg, ...) { return B_ERROR; } 839 status_t BMediaTrack::_Reserved_BMediaTrack_15(int32 arg, ...) { return B_ERROR; } 840 status_t BMediaTrack::_Reserved_BMediaTrack_16(int32 arg, ...) { return B_ERROR; } 841 status_t BMediaTrack::_Reserved_BMediaTrack_17(int32 arg, ...) { return B_ERROR; } 842 status_t BMediaTrack::_Reserved_BMediaTrack_18(int32 arg, ...) { return B_ERROR; } 843 status_t BMediaTrack::_Reserved_BMediaTrack_19(int32 arg, ...) { return B_ERROR; } 844 status_t BMediaTrack::_Reserved_BMediaTrack_20(int32 arg, ...) { return B_ERROR; } 845 status_t BMediaTrack::_Reserved_BMediaTrack_21(int32 arg, ...) { return B_ERROR; } 846 status_t BMediaTrack::_Reserved_BMediaTrack_22(int32 arg, ...) { return B_ERROR; } 847 status_t BMediaTrack::_Reserved_BMediaTrack_23(int32 arg, ...) { return B_ERROR; } 848 status_t BMediaTrack::_Reserved_BMediaTrack_24(int32 arg, ...) { return B_ERROR; } 849 status_t BMediaTrack::_Reserved_BMediaTrack_25(int32 arg, ...) { return B_ERROR; } 850 status_t BMediaTrack::_Reserved_BMediaTrack_26(int32 arg, ...) { return B_ERROR; } 851 status_t BMediaTrack::_Reserved_BMediaTrack_27(int32 arg, ...) { return B_ERROR; } 852 status_t BMediaTrack::_Reserved_BMediaTrack_28(int32 arg, ...) { return B_ERROR; } 853 status_t BMediaTrack::_Reserved_BMediaTrack_29(int32 arg, ...) { return B_ERROR; } 854 status_t BMediaTrack::_Reserved_BMediaTrack_30(int32 arg, ...) { return B_ERROR; } 855 status_t BMediaTrack::_Reserved_BMediaTrack_31(int32 arg, ...) { return B_ERROR; } 856 status_t BMediaTrack::_Reserved_BMediaTrack_32(int32 arg, ...) { return B_ERROR; } 857 status_t BMediaTrack::_Reserved_BMediaTrack_33(int32 arg, ...) { return B_ERROR; } 858 status_t BMediaTrack::_Reserved_BMediaTrack_34(int32 arg, ...) { return B_ERROR; } 859 status_t BMediaTrack::_Reserved_BMediaTrack_35(int32 arg, ...) { return B_ERROR; } 860 status_t BMediaTrack::_Reserved_BMediaTrack_36(int32 arg, ...) { return B_ERROR; } 861 status_t BMediaTrack::_Reserved_BMediaTrack_37(int32 arg, ...) { return B_ERROR; } 862 status_t BMediaTrack::_Reserved_BMediaTrack_38(int32 arg, ...) { return B_ERROR; } 863 status_t BMediaTrack::_Reserved_BMediaTrack_39(int32 arg, ...) { return B_ERROR; } 864 status_t BMediaTrack::_Reserved_BMediaTrack_40(int32 arg, ...) { return B_ERROR; } 865 status_t BMediaTrack::_Reserved_BMediaTrack_41(int32 arg, ...) { return B_ERROR; } 866 status_t BMediaTrack::_Reserved_BMediaTrack_42(int32 arg, ...) { return B_ERROR; } 867 status_t BMediaTrack::_Reserved_BMediaTrack_43(int32 arg, ...) { return B_ERROR; } 868 status_t BMediaTrack::_Reserved_BMediaTrack_44(int32 arg, ...) { return B_ERROR; } 869 status_t BMediaTrack::_Reserved_BMediaTrack_45(int32 arg, ...) { return B_ERROR; } 870 status_t BMediaTrack::_Reserved_BMediaTrack_46(int32 arg, ...) { return B_ERROR; } 871 status_t BMediaTrack::_Reserved_BMediaTrack_47(int32 arg, ...) { return B_ERROR; } 872 873 874 RawDecoderChunkProvider::RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size) 875 { 876 // printf("RawDecoderChunkProvider: buffer_size %d, frame_size %d\n", buffer_size, frame_size); 877 fDecoder = decoder; 878 fFrameSize = frame_size; 879 fBufferSize = buffer_size; 880 fBuffer = malloc(buffer_size); 881 } 882 883 RawDecoderChunkProvider::~RawDecoderChunkProvider() 884 { 885 free(fBuffer); 886 } 887 888 status_t 889 RawDecoderChunkProvider::GetNextChunk(const void **chunkBuffer, size_t *chunkSize, 890 media_header *mediaHeader) 891 { 892 int64 frames; 893 media_decode_info info; 894 status_t res = fDecoder->Decode(fBuffer, &frames, mediaHeader, &info); 895 if (res == B_OK) { 896 *chunkBuffer = fBuffer; 897 *chunkSize = frames * fFrameSize; 898 // printf("RawDecoderChunkProvider::GetNextChunk, %Ld frames, %ld bytes, start-time %Ld\n", frames, *chunkSize, mediaHeader->start_time); 899 } else { 900 ERROR("RawDecoderChunkProvider::GetNextChunk failed\n"); 901 } 902 return res; 903 } 904