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