1 /* 2 * Copyright 2009, Stephan Aßmus <superstippi@gmx.de> 3 * Copyright 2002-2004, Marcus Overhagen <marcus@overhagen.de> 4 * All rights reserved. Distributed under the terms of the MIT license. 5 */ 6 7 #include <MediaFile.h> 8 9 #include <new> 10 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include <File.h> 15 #include <MediaTrack.h> 16 #include <Url.h> 17 18 #include "debug.h" 19 20 #include "MediaExtractor.h" 21 #include "MediaWriter.h" 22 23 24 BMediaFile::BMediaFile(const entry_ref* ref) 25 { 26 CALLED(); 27 _Init(); 28 fDeleteSource = true; 29 _InitReader(new(std::nothrow) BFile(ref, O_RDONLY)); 30 } 31 32 33 BMediaFile::BMediaFile(BDataIO* source) 34 { 35 CALLED(); 36 _Init(); 37 _InitReader(source); 38 } 39 40 41 BMediaFile::BMediaFile(const entry_ref* ref, int32 flags) 42 { 43 CALLED(); 44 _Init(); 45 fDeleteSource = true; 46 _InitReader(new(std::nothrow) BFile(ref, O_RDONLY), NULL, flags); 47 } 48 49 50 BMediaFile::BMediaFile(BDataIO* source, int32 flags) 51 { 52 CALLED(); 53 _Init(); 54 _InitReader(source, NULL, flags); 55 } 56 57 58 BMediaFile::BMediaFile(const entry_ref* ref, const media_file_format* mfi, 59 int32 flags) 60 { 61 CALLED(); 62 _Init(); 63 fDeleteSource = true; 64 _InitWriter(new(std::nothrow) BFile(ref, B_CREATE_FILE | B_ERASE_FILE 65 | B_WRITE_ONLY), NULL, mfi, flags); 66 } 67 68 69 BMediaFile::BMediaFile(BDataIO* destination, const media_file_format* mfi, 70 int32 flags) 71 { 72 CALLED(); 73 _Init(); 74 _InitWriter(destination, NULL, mfi, flags); 75 } 76 77 78 // File will be set later by SetTo() 79 BMediaFile::BMediaFile(const media_file_format* mfi, int32 flags) 80 { 81 debugger("BMediaFile::BMediaFile not implemented"); 82 } 83 84 85 BMediaFile::BMediaFile(const BUrl& url) 86 { 87 CALLED(); 88 _Init(); 89 fDeleteSource = true; 90 _InitReader(NULL, &url); 91 } 92 93 94 BMediaFile::BMediaFile(const BUrl& url, int32 flags) 95 { 96 CALLED(); 97 _Init(); 98 fDeleteSource = true; 99 _InitReader(NULL, &url, flags); 100 } 101 102 103 BMediaFile::BMediaFile(BUrl destination, const media_file_format* mfi, 104 int32 flags) 105 { 106 CALLED(); 107 _Init(); 108 fDeleteSource = true; 109 _InitWriter(NULL, &destination, mfi, flags); 110 // TODO: Implement streaming server support, it's 111 // a pretty complex thing compared to client mode 112 // and will require to expand the current BMediaFile 113 // design to be aware of it. 114 } 115 116 117 status_t 118 BMediaFile::SetTo(const entry_ref* ref) 119 { 120 CALLED(); 121 122 if (ref == NULL) 123 return B_BAD_VALUE; 124 125 _UnInit(); 126 fDeleteSource = true; 127 _InitReader(new(std::nothrow) BFile(ref, O_RDONLY)); 128 129 return fErr; 130 } 131 132 133 status_t 134 BMediaFile::SetTo(BDataIO* destination) 135 { 136 CALLED(); 137 138 // TODO: A BUrl SetTo should be provided 139 if (destination == NULL) 140 return B_BAD_VALUE; 141 142 _UnInit(); 143 _InitReader(destination); 144 145 return fErr; 146 } 147 148 149 BMediaFile::~BMediaFile() 150 { 151 CALLED(); 152 153 _UnInit(); 154 } 155 156 157 status_t 158 BMediaFile::InitCheck() const 159 { 160 CALLED(); 161 return fErr; 162 } 163 164 165 status_t 166 BMediaFile::GetFileFormatInfo(media_file_format* mfi) const 167 { 168 CALLED(); 169 if (mfi == NULL) 170 return B_BAD_VALUE; 171 if (fErr) 172 return B_ERROR; 173 *mfi = fMFI; 174 return B_OK; 175 } 176 177 178 status_t 179 BMediaFile::GetMetaData(BMessage* _data) const 180 { 181 if (fExtractor == NULL) 182 return B_NO_INIT; 183 if (_data == NULL) 184 return B_BAD_VALUE; 185 186 _data->MakeEmpty(); 187 188 return fExtractor->GetMetaData(_data); 189 } 190 191 192 const char* 193 BMediaFile::Copyright() const 194 { 195 return fExtractor->Copyright(); 196 } 197 198 199 int32 200 BMediaFile::CountTracks() const 201 { 202 return fTrackNum; 203 } 204 205 206 // Can be called multiple times with the same index. You must call 207 // ReleaseTrack() when you're done with a track. 208 BMediaTrack* 209 BMediaFile::TrackAt(int32 index) 210 { 211 CALLED(); 212 if (fTrackList == NULL || fExtractor == NULL 213 || index < 0 || index >= fTrackNum) { 214 return NULL; 215 } 216 if (fTrackList[index] == NULL) { 217 TRACE("BMediaFile::TrackAt, creating new track for index %" 218 B_PRId32 "\n", index); 219 fTrackList[index] = new(std::nothrow) BMediaTrack(fExtractor, index); 220 TRACE("BMediaFile::TrackAt, new track is %p\n", fTrackList[index]); 221 } 222 return fTrackList[index]; 223 } 224 225 226 // Release the resource used by a given BMediaTrack object, to reduce 227 // the memory usage of your application. The specific 'track' object 228 // can no longer be used, but you can create another one by calling 229 // TrackAt() with the same track index. 230 status_t 231 BMediaFile::ReleaseTrack(BMediaTrack* track) 232 { 233 CALLED(); 234 if (!fTrackList || !track) 235 return B_ERROR; 236 for (int32 i = 0; i < fTrackNum; i++) { 237 if (fTrackList[i] == track) { 238 TRACE("BMediaFile::ReleaseTrack, releasing track %p with index " 239 "%" B_PRId32 "\n", track, i); 240 delete track; 241 fTrackList[i] = NULL; 242 return B_OK; 243 } 244 } 245 fprintf(stderr, "BMediaFile::ReleaseTrack track %p not found\n", track); 246 return B_ERROR; 247 } 248 249 250 status_t 251 BMediaFile::ReleaseAllTracks() 252 { 253 CALLED(); 254 if (!fTrackList) 255 return B_ERROR; 256 for (int32 i = 0; i < fTrackNum; i++) { 257 if (fTrackList[i]) { 258 TRACE("BMediaFile::ReleaseAllTracks, releasing track %p with " 259 "index %" B_PRId32 "\n", fTrackList[i], i); 260 delete fTrackList[i]; 261 fTrackList[i] = NULL; 262 } 263 } 264 return B_OK; 265 } 266 267 268 // Create and add a track to the media file 269 BMediaTrack* 270 BMediaFile::CreateTrack(media_format* mediaFormat, 271 const media_codec_info* codecInfo, uint32 flags) 272 { 273 if (mediaFormat == NULL) 274 return NULL; 275 276 // NOTE: It is allowed to pass NULL for codecInfo. In that case, the 277 // track won't have an Encoder and you can only use WriteChunk() with 278 // already encoded data. 279 280 // Make room for the new track. 281 BMediaTrack** trackList = (BMediaTrack**)realloc(fTrackList, 282 (fTrackNum + 1) * sizeof(BMediaTrack*)); 283 if (trackList == NULL) 284 return NULL; 285 286 int32 streamIndex = fTrackNum; 287 fTrackList = trackList; 288 fTrackNum += 1; 289 290 BMediaTrack* track = new(std::nothrow) BMediaTrack(fWriter, streamIndex, 291 mediaFormat, codecInfo); 292 293 fTrackList[streamIndex] = track; 294 295 return track; 296 } 297 298 299 // Create and add a raw track to the media file (it has no encoder) 300 BMediaTrack* 301 BMediaFile::CreateTrack(media_format* mf, uint32 flags) 302 { 303 return CreateTrack(mf, NULL, flags); 304 } 305 306 307 // For BeOS R5 compatibility 308 extern "C" BMediaTrack* 309 CreateTrack__10BMediaFileP12media_formatPC16media_codec_info( 310 BMediaFile* self, media_format* mf, const media_codec_info* mci); 311 BMediaTrack* 312 CreateTrack__10BMediaFileP12media_formatPC16media_codec_info(BMediaFile* self, 313 media_format* mf, const media_codec_info* mci) 314 { 315 return self->CreateTrack(mf, mci, 0); 316 } 317 318 319 // For BeOS R5 compatibility 320 extern "C" BMediaTrack* CreateTrack__10BMediaFileP12media_format( 321 BMediaFile* self, media_format* mf); 322 BMediaTrack* 323 CreateTrack__10BMediaFileP12media_format(BMediaFile* self, media_format* mf) 324 { 325 return self->CreateTrack(mf, NULL, 0); 326 } 327 328 329 // Lets you set the copyright info for the entire file 330 status_t 331 BMediaFile::AddCopyright(const char* copyright) 332 { 333 if (fWriter == NULL) 334 return B_NO_INIT; 335 336 return fWriter->SetCopyright(copyright); 337 } 338 339 340 // Call this to add user-defined chunks to a file (if they're supported) 341 status_t 342 BMediaFile::AddChunk(int32 type, const void* data, size_t size) 343 { 344 UNIMPLEMENTED(); 345 return B_OK; 346 } 347 348 349 // After you have added all the tracks you want, call this 350 status_t 351 BMediaFile::CommitHeader() 352 { 353 if (fWriter == NULL) 354 return B_NO_INIT; 355 356 return fWriter->CommitHeader(); 357 } 358 359 360 // After you have written all the data to the track objects, call this 361 status_t 362 BMediaFile::CloseFile() 363 { 364 if (fWriter == NULL) 365 return B_NO_INIT; 366 367 return fWriter->Close(); 368 } 369 370 // This is for controlling file format parameters 371 372 // returns a copy of the parameter web 373 status_t 374 BMediaFile::GetParameterWeb(BParameterWeb** outWeb) 375 { 376 UNIMPLEMENTED(); 377 return B_ERROR; 378 } 379 380 381 // deprecated BeOS R5 API 382 BParameterWeb* 383 BMediaFile::Web() 384 { 385 UNIMPLEMENTED(); 386 return 0; 387 } 388 389 390 status_t 391 BMediaFile::GetParameterValue(int32 id, void* value, size_t* size) 392 { 393 UNIMPLEMENTED(); 394 return B_OK; 395 } 396 397 398 status_t 399 BMediaFile::SetParameterValue(int32 id, const void* value, size_t size) 400 { 401 UNIMPLEMENTED(); 402 return B_OK; 403 } 404 405 406 BView* 407 BMediaFile::GetParameterView() 408 { 409 UNIMPLEMENTED(); 410 return 0; 411 } 412 413 414 status_t 415 BMediaFile::Perform(int32 selector, void* data) 416 { 417 UNIMPLEMENTED(); 418 return B_OK; 419 } 420 421 422 status_t 423 BMediaFile::ControlFile(int32 selector, void* ioData, size_t size) 424 { 425 UNIMPLEMENTED(); 426 return B_ERROR; 427 } 428 429 430 // #pragma mark - private 431 432 433 void 434 BMediaFile::_Init() 435 { 436 CALLED(); 437 438 fSource = NULL; 439 fTrackNum = 0; 440 fTrackList = NULL; 441 fExtractor = NULL; 442 fWriter = NULL; 443 fWriterID = 0; 444 fErr = B_OK; 445 fDeleteSource = false; 446 447 // not used so far: 448 fEncoderMgr = NULL; 449 fWriterMgr = NULL; 450 fFileClosed = false; 451 } 452 453 454 void 455 BMediaFile::_UnInit() 456 { 457 ReleaseAllTracks(); 458 free(fTrackList); 459 fTrackList = NULL; 460 fTrackNum = 0; 461 delete fExtractor; 462 fExtractor = NULL; 463 delete fWriter; 464 fWriter = NULL; 465 if (fDeleteSource) { 466 delete fSource; 467 fSource = NULL; 468 fDeleteSource = false; 469 } 470 } 471 472 473 void 474 BMediaFile::_InitReader(BDataIO* source, const BUrl* url, int32 flags) 475 { 476 CALLED(); 477 478 if (source == NULL && url == NULL) { 479 fErr = B_NO_MEMORY; 480 return; 481 } 482 483 if (source != NULL) { 484 if (BFile* file = dynamic_cast<BFile*>(source)) { 485 fErr = file->InitCheck(); 486 if (fErr != B_OK) 487 return; 488 } 489 fExtractor = new(std::nothrow) MediaExtractor(source, flags); 490 } else 491 fExtractor = new(std::nothrow) MediaExtractor(*url, flags); 492 493 if (fExtractor == NULL) 494 fErr = B_NO_MEMORY; 495 else 496 fErr = fExtractor->InitCheck(); 497 if (fErr != B_OK) 498 return; 499 500 // Get the actual source from the extractor 501 fSource = fExtractor->Source(); 502 503 fExtractor->GetFileFormatInfo(&fMFI); 504 fTrackNum = fExtractor->StreamCount(); 505 fTrackList = (BMediaTrack**)malloc(fTrackNum * sizeof(BMediaTrack*)); 506 if (fTrackList == NULL) { 507 fErr = B_NO_MEMORY; 508 return; 509 } 510 memset(fTrackList, 0, fTrackNum * sizeof(BMediaTrack*)); 511 } 512 513 514 void 515 BMediaFile::_InitWriter(BDataIO* target, const BUrl* url, 516 const media_file_format* fileFormat, int32 flags) 517 { 518 CALLED(); 519 520 if (fileFormat == NULL) { 521 fErr = B_BAD_VALUE; 522 return; 523 } 524 525 if (target == NULL && url == NULL) { 526 fErr = B_NO_MEMORY; 527 return; 528 } 529 530 fMFI = *fileFormat; 531 532 if (target != NULL) 533 fWriter = new(std::nothrow) MediaWriter(target, fMFI); 534 else 535 fWriter = new(std::nothrow) MediaWriter(*url, fMFI); 536 537 if (fWriter == NULL) 538 fErr = B_NO_MEMORY; 539 else 540 fErr = fWriter->InitCheck(); 541 if (fErr != B_OK) 542 return; 543 544 // Get the actual source from the writer 545 fSource = fWriter->Target(); 546 fTrackNum = 0; 547 } 548 549 550 /* 551 //unimplemented 552 BMediaFile::BMediaFile(); 553 BMediaFile::BMediaFile(const BMediaFile&); 554 BMediaFile::BMediaFile& operator=(const BMediaFile&); 555 */ 556 557 status_t BMediaFile::_Reserved_BMediaFile_0(int32 arg, ...) { return B_ERROR; } 558 status_t BMediaFile::_Reserved_BMediaFile_1(int32 arg, ...) { return B_ERROR; } 559 status_t BMediaFile::_Reserved_BMediaFile_2(int32 arg, ...) { return B_ERROR; } 560 status_t BMediaFile::_Reserved_BMediaFile_3(int32 arg, ...) { return B_ERROR; } 561 status_t BMediaFile::_Reserved_BMediaFile_4(int32 arg, ...) { return B_ERROR; } 562 status_t BMediaFile::_Reserved_BMediaFile_5(int32 arg, ...) { return B_ERROR; } 563 status_t BMediaFile::_Reserved_BMediaFile_6(int32 arg, ...) { return B_ERROR; } 564 status_t BMediaFile::_Reserved_BMediaFile_7(int32 arg, ...) { return B_ERROR; } 565 status_t BMediaFile::_Reserved_BMediaFile_8(int32 arg, ...) { return B_ERROR; } 566 status_t BMediaFile::_Reserved_BMediaFile_9(int32 arg, ...) { return B_ERROR; } 567 status_t BMediaFile::_Reserved_BMediaFile_10(int32 arg, ...) { return B_ERROR; } 568 status_t BMediaFile::_Reserved_BMediaFile_11(int32 arg, ...) { return B_ERROR; } 569 status_t BMediaFile::_Reserved_BMediaFile_12(int32 arg, ...) { return B_ERROR; } 570 status_t BMediaFile::_Reserved_BMediaFile_13(int32 arg, ...) { return B_ERROR; } 571 status_t BMediaFile::_Reserved_BMediaFile_14(int32 arg, ...) { return B_ERROR; } 572 status_t BMediaFile::_Reserved_BMediaFile_15(int32 arg, ...) { return B_ERROR; } 573 status_t BMediaFile::_Reserved_BMediaFile_16(int32 arg, ...) { return B_ERROR; } 574 status_t BMediaFile::_Reserved_BMediaFile_17(int32 arg, ...) { return B_ERROR; } 575 status_t BMediaFile::_Reserved_BMediaFile_18(int32 arg, ...) { return B_ERROR; } 576 status_t BMediaFile::_Reserved_BMediaFile_19(int32 arg, ...) { return B_ERROR; } 577 status_t BMediaFile::_Reserved_BMediaFile_20(int32 arg, ...) { return B_ERROR; } 578 status_t BMediaFile::_Reserved_BMediaFile_21(int32 arg, ...) { return B_ERROR; } 579 status_t BMediaFile::_Reserved_BMediaFile_22(int32 arg, ...) { return B_ERROR; } 580 status_t BMediaFile::_Reserved_BMediaFile_23(int32 arg, ...) { return B_ERROR; } 581 status_t BMediaFile::_Reserved_BMediaFile_24(int32 arg, ...) { return B_ERROR; } 582 status_t BMediaFile::_Reserved_BMediaFile_25(int32 arg, ...) { return B_ERROR; } 583 status_t BMediaFile::_Reserved_BMediaFile_26(int32 arg, ...) { return B_ERROR; } 584 status_t BMediaFile::_Reserved_BMediaFile_27(int32 arg, ...) { return B_ERROR; } 585 status_t BMediaFile::_Reserved_BMediaFile_28(int32 arg, ...) { return B_ERROR; } 586 status_t BMediaFile::_Reserved_BMediaFile_29(int32 arg, ...) { return B_ERROR; } 587 status_t BMediaFile::_Reserved_BMediaFile_30(int32 arg, ...) { return B_ERROR; } 588 status_t BMediaFile::_Reserved_BMediaFile_31(int32 arg, ...) { return B_ERROR; } 589 status_t BMediaFile::_Reserved_BMediaFile_32(int32 arg, ...) { return B_ERROR; } 590 status_t BMediaFile::_Reserved_BMediaFile_33(int32 arg, ...) { return B_ERROR; } 591 status_t BMediaFile::_Reserved_BMediaFile_34(int32 arg, ...) { return B_ERROR; } 592 status_t BMediaFile::_Reserved_BMediaFile_35(int32 arg, ...) { return B_ERROR; } 593 status_t BMediaFile::_Reserved_BMediaFile_36(int32 arg, ...) { return B_ERROR; } 594 status_t BMediaFile::_Reserved_BMediaFile_37(int32 arg, ...) { return B_ERROR; } 595 status_t BMediaFile::_Reserved_BMediaFile_38(int32 arg, ...) { return B_ERROR; } 596 status_t BMediaFile::_Reserved_BMediaFile_39(int32 arg, ...) { return B_ERROR; } 597 status_t BMediaFile::_Reserved_BMediaFile_40(int32 arg, ...) { return B_ERROR; } 598 status_t BMediaFile::_Reserved_BMediaFile_41(int32 arg, ...) { return B_ERROR; } 599 status_t BMediaFile::_Reserved_BMediaFile_42(int32 arg, ...) { return B_ERROR; } 600 status_t BMediaFile::_Reserved_BMediaFile_43(int32 arg, ...) { return B_ERROR; } 601 status_t BMediaFile::_Reserved_BMediaFile_44(int32 arg, ...) { return B_ERROR; } 602 status_t BMediaFile::_Reserved_BMediaFile_45(int32 arg, ...) { return B_ERROR; } 603 status_t BMediaFile::_Reserved_BMediaFile_46(int32 arg, ...) { return B_ERROR; } 604 status_t BMediaFile::_Reserved_BMediaFile_47(int32 arg, ...) { return B_ERROR; } 605 606