Changeset 204
- Timestamp:
- 12/10/06 04:48:09 (2 years ago)
- Files:
-
- trunk/Perian-Info.plist (modified) (2 diffs)
- trunk/PerianAviImporter.r (modified) (1 diff)
- trunk/ff_MovieImport.c (modified) (9 diffs)
- trunk/ff_MovieImportDispatch.h (modified) (1 diff)
- trunk/ff_dataref.c (modified) (3 diffs)
- trunk/ff_private.c (modified) (5 diffs)
- trunk/ff_private.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Perian-Info.plist
r17 r204 7 7 <key>CFBundleExecutable</key> 8 8 <string>Perian</string> 9 <key>CFBundleGetInfoString</key> 10 <string>0.1 (SVNREVISION ffmpeg: FFMPEGREVISION), Copyright 2006 The Perian Team</string> 9 11 <key>CFBundleIdentifier</key> 10 <string> com.yourcompany.Perian</string>12 <string>org.perian.Perian</string> 11 13 <key>CFBundleInfoDictionaryVersion</key> 12 14 <string>6.0</string> … … 16 18 <string>????</string> 17 19 <key>CFBundleVersion</key> 18 <string>0.1</string> 19 <key>CFBundleGetInfoString</key> 20 <string>0.1 (SVNREVISION ffmpeg: FFMPEGREVISION), Copyright 2006 The Perian Team</string> 20 <string>0.5</string> 21 21 <key>CSResourcesFileMapped</key> 22 22 <string>yes</string> trunk/PerianAviImporter.r
r148 r204 35 35 #define kFFAvi_MovieImportFlags \ 36 36 ( canMovieImportFiles | canMovieImportInPlace | canMovieImportDataReferences | canMovieImportValidateFile \ 37 | canMovieImportValidateDataReferences | hasMovieImportMIMEList | movieImportMustGetDestinationMediaType\38 | cmpThreadSafe )37 | canMovieImportValidateDataReferences | canMovieImportWithIdle | hasMovieImportMIMEList \ 38 | movieImportMustGetDestinationMediaType | cmpThreadSafe ) 39 39 40 40 /* Component Manager Things - trunk/ff_MovieImport.c
r176 r204 44 44 #define COMPONENT_UPP_SELECT_ROOT() MovieImport 45 45 46 struct _ff_global_context {47 ComponentInstance ci;48 OSType componentType;49 50 /* For feedback during import */51 MovieProgressUPP prog;52 long refcon;53 54 /* for overwriting the default sample descriptions */55 ImageDescriptionHandle imgHdl;56 SoundDescriptionHandle sndHdl;57 AVInputFormat *format;58 };59 typedef struct _ff_global_context ff_global_context;60 typedef ff_global_context *ff_global_ptr;61 62 46 #include <CoreServices/Components.k.h> 63 47 #include <QuickTime/QuickTimeComponents.k.h> … … 122 106 123 107 storage->componentType = descout.componentSubType; 108 storage->movieLoadState = kMovieLoadStateLoading; 124 109 bail: 125 110 return result; … … 133 118 if(storage->sndHdl) 134 119 DisposeHandle((Handle)storage->sndHdl); 120 121 if(storage->stream_map) 122 av_free(storage->stream_map); 123 124 if(storage->format_context) 125 av_close_input_file(storage->format_context); 135 126 136 127 if(storage) … … 317 308 /* Prepare the iocontext structure */ 318 309 memset(&byteContext, 0, sizeof(byteContext)); 319 result = url_open_dataref(&byteContext, dataRef, dataRefType );310 result = url_open_dataref(&byteContext, dataRef, dataRefType, NULL, NULL, NULL); 320 311 require_noerr(result, bail); 321 312 … … 375 366 AVFormatContext *ic = NULL; 376 367 AVFormatParameters params; 377 int64_t dataOffset;378 368 AVPacket pkt; 379 NCStream *map = NULL;380 int map_count,j,count;381 369 OSType mediaType; 382 Track track;383 370 Media media; 384 TimeRecord time; 385 int i; 386 short hadIndex = 0; 387 371 int count, hadIndex, i, j; 372 388 373 /* make sure that in case of error, the flag movieImportResultComplete is not set */ 389 374 *outFlags = 0; … … 394 379 if(valid != 255) 395 380 goto bail; 396 381 397 382 /* Prepare the iocontext structure */ 398 383 memset(&byteContext, 0, sizeof(byteContext)); 399 result = url_open_dataref(&byteContext, dataRef, dataRefType );384 result = url_open_dataref(&byteContext, dataRef, dataRefType, &storage->dataHandler, &storage->dataHandlerSupportsWideOffsets, &storage->dataSize); 400 385 require_noerr(result, bail); 401 386 … … 404 389 result = av_open_input_stream(&ic, &byteContext, "", storage->format, ¶ms); 405 390 require_noerr(result,bail); 391 storage->format_context = ic; 406 392 407 393 /* Get the Stream Infos if not already read */ … … 410 396 goto bail; 411 397 412 /* Seek backwards to get a manually read packet for file offset */ 413 if(ic->streams[0]->index_entries == NULL || storage->componentType == 'FLV ') 414 { 415 if (IS_AVI(storage->componentType)) 416 //Try to seek to the first frame; don't care if it fails 417 // Is this really needed for AVIs w/out an index? It seems to work fine without, 418 // and it seems that with it the first frame is skipped. 419 av_seek_frame(ic, -1, 0, 0); 420 dataOffset = 0; 421 } 422 else 423 { 424 result = av_seek_frame(ic, -1, 0, 0); 425 if(result < 0) goto bail; 426 427 ic->iformat->read_packet(ic, &pkt); 428 /* read_packet will give the first decodable packet. However, that isn't necessarily 429 the first entry in the index, so look for an entry with a matching size. */ 430 for (i = 0; i < ic->streams[pkt.stream_index]->nb_index_entries; i++) { 431 if (pkt.size == ic->streams[pkt.stream_index]->index_entries[i].size) { 432 dataOffset = pkt.pos - ic->streams[pkt.stream_index]->index_entries[i].pos; 433 break; 398 //determine a header offset (needed by index-based import). 399 result = determine_header_offset(storage); 400 if(result < 0) 401 goto bail; 402 403 /* Initialize the Movie */ 404 storage->movie = theMovie; 405 if(inFlags & movieImportMustUseTrack) { 406 storage->map_count = 1; 407 prepare_track(ic, &storage->stream_map, targetTrack, dataRef, dataRefType); 408 } else { 409 storage->map_count = ic->nb_streams; 410 prepare_movie(ic, &storage->stream_map, theMovie, dataRef, dataRefType); 411 } 412 413 /* replace the SampleDescription if user called MovieImportSetSampleDescription() */ 414 if(storage->imgHdl) { 415 for(j = 0; j < storage->map_count; j++) { 416 NCStream ncstream = storage->stream_map[j]; 417 GetMediaHandlerDescription(ncstream.media, &mediaType, NULL, NULL); 418 if(mediaType == VideoMediaType && ncstream.sampleHdl) { 419 DisposeHandle((Handle)ncstream.sampleHdl); 420 ncstream.sampleHdl = (SampleDescriptionHandle)storage->imgHdl; 434 421 } 435 422 } 436 av_free_packet(&pkt); 437 } 438 439 /* Initialize the Movie */ 440 if(inFlags & movieImportMustUseTrack) { 441 map_count = 1; 442 prepare_track(ic, &map, targetTrack, dataRef, dataRefType); 443 } else { 444 map_count = ic->nb_streams; 445 prepare_movie(ic, &map, theMovie, dataRef, dataRefType); 446 } 447 448 /* replace the SampleDescription if user called MovieImportSetSampleDescription() */ 449 if(storage->imgHdl) { 450 for(j = 0; j < map_count; j++) { 451 GetMediaHandlerDescription(map[j].media, &mediaType, NULL, NULL); 452 if(mediaType == VideoMediaType && map[j].sampleHdl) { 453 DisposeHandle((Handle)map[j].sampleHdl); 454 map[j].sampleHdl = (SampleDescriptionHandle)storage->imgHdl; 423 } 424 if(storage->sndHdl) { 425 for(j = 0; j < storage->map_count; j++) { 426 NCStream ncstream = storage->stream_map[j]; 427 GetMediaHandlerDescription(ncstream.media, &mediaType, NULL, NULL); 428 if(mediaType == SoundMediaType && ncstream.sampleHdl) { 429 DisposeHandle((Handle)ncstream.sampleHdl); 430 ncstream.sampleHdl = (SampleDescriptionHandle)storage->sndHdl; 455 431 } 456 432 } 457 433 } 458 if(storage->sndHdl) {459 for(j = 0; j < map_count; j++) {460 GetMediaHandlerDescription(map[j].media, &mediaType, NULL, NULL);461 if(mediaType == SoundMediaType && map[j].sampleHdl) {462 DisposeHandle((Handle)map[j].sampleHdl);463 map[j].sampleHdl = (SampleDescriptionHandle)storage->sndHdl;464 }465 }466 }467 468 /* Import the Data*/469 /* FIXME: Implement the progress upp */470 /* note: flv builds a partial index that's unusable, so force importing without an index */471 if (!(storage->componentType == 'FLV '))472 hadIndex = import_avi(ic, map, dataOffset);473 474 if (!hadIndex)475 import_without_index(ic, map, dataOffset);476 477 /* Insert the Medias into the Tracks */478 result = noErr;479 for(j = 0; j < map_count && result == noErr; j++) {480 media = map[j].media;481 if(media) {482 /* we could handle this stream.483 * convert the atTime parameter to track scale.484 * FIXME: check if that's correct */485 time.value.hi = 0;486 time.value.lo = atTime;487 time.scale = GetMovieTimeScale(theMovie);488 time.base = NULL;489 ConvertTimeScale(&time, GetMediaTimeScale(media));490 491 track = GetMediaTrack(media);492 result = InsertMediaIntoTrack(track, time.value.lo, 0, GetMediaDuration(media), fixed1);493 }494 }495 require_noerr(result,bail);496 497 /* Set return values of the function */498 434 499 435 count = 0; media = NULL; 500 for(j = 0; j < map_count; j++) {501 media = map[j].media;436 for(j = 0; j < storage->map_count; j++) { 437 media = storage->stream_map[j].media; 502 438 if(media) 503 439 count++; 504 440 } 441 442 if(count > 1) 443 *outFlags |= movieImportResultUsedMultipleTracks; 505 444 506 445 /* The usedTrack parameter. Count the number of Tracks and set usedTrack if we operated … … 509 448 *usedTrack = GetMediaTrack(media); 510 449 511 /* the addedDuration parameter */ 512 if(addedDuration) { 513 *addedDuration = 0; 514 for(j = 0; j < map_count; j++) { 515 media = map[j].media; 516 if(media) { 517 time.value.hi = 0; 518 time.value.lo = GetMediaDuration(media); 519 time.scale = GetMediaTimeScale(media); 520 time.base = NULL; 521 ConvertTimeScale(&time, GetMovieTimeScale(theMovie)); 522 523 /* if that's longer than before, replace */ 524 if(time.value.lo > *addedDuration) 525 *addedDuration = time.value.lo; 526 } 450 result = noErr; 451 452 *addedDuration = 0; 453 454 //attempt to import using indexes. 455 result = import_using_index(storage, &hadIndex, addedDuration); 456 require_noerr(result, bail); 457 458 if(hadIndex) { 459 //file had an index and was imported; we are done. 460 *outFlags |= movieImportResultComplete; 461 462 } else if(inFlags & movieImportWithIdle) { 463 if(addedDuration && ic->duration > 0) { 464 TimeValue sampleTime; 465 TimeScale movieTimeScale = GetMovieTimeScale(theMovie); 466 *addedDuration = movieTimeScale * ic->duration / AV_TIME_BASE; 467 468 //create a placeholder track so that progress displays correctly. 469 create_placeholder_track(storage, *addedDuration, dataRef, dataRefType); 470 471 //give the data handler a hint as to how fast we need the data. 472 //suggest a speed that's faster than the bare minimum. 473 //if there's an error, the data handler probably doesn't support 474 //this, so we can just ignore. 475 DataHPlaybackHints(storage->dataHandler, 0, 0, -1, (storage->dataSize * 1.15) / ((double)ic->duration / AV_TIME_BASE)); 527 476 } 528 } 529 530 /* now set the outflags, set to zero at the beginning of the function */ 531 if(outFlags) { 532 if(count > 1) 533 *outFlags |= movieImportResultUsedMultipleTracks; 534 535 /* set the finished flag */ 536 *outFlags |= movieImportResultComplete; 477 478 //import with idle. Decode a little bit of data now. 479 import_with_idle(storage, inFlags, outFlags, 10, 300); 480 } else { 481 //QuickTime didn't request import with idle, so do it all now. 482 import_with_idle(storage, inFlags, outFlags, 0, 0); 537 483 } 538 484 539 485 bail: 540 /* Free all the data structures used */ 541 if(ic) 542 av_close_input_file(ic); 543 if(map) 544 av_free(map); 486 if(result == noErr) 487 storage->movieLoadState == kMovieLoadStateLoaded; 488 else 489 storage->movieLoadState == kMovieLoadStateError; 545 490 546 491 return result; 547 492 } /* FFAvi_MovieImportDataRef */ 493 494 ComponentResult FFAvi_MovieImportSetIdleManager(ff_global_ptr storage, IdleManager im) { 495 storage->idleManager = im; 496 } 497 498 ComponentResult FFAvi_MovieImportIdle(ff_global_ptr storage, long inFlags, long *outFlags) { 499 return(import_with_idle(storage, inFlags | movieImportWithIdle, outFlags, 0, 1000)); 500 } 501 502 ComponentResult FFAvi_MovieImportGetLoadState(ff_global_ptr storage, long *importerLoadState) { 503 *importerLoadState = storage->movieLoadState; 504 return(noErr); 505 } 506 507 ComponentResult FFAvi_MovieImportGetMaxLoadedTime(ff_global_ptr storage, TimeValue *time) { 508 *time = storage->loadedTime; 509 return(noErr); 510 } trunk/ff_MovieImportDispatch.h
r60 r204 61 61 ComponentError (SetSettingsFromAtomContainer) 62 62 ComponentError (SetOffsetAndLimit64) 63 Component Error(Idle)63 ComponentCall (Idle) 64 64 ComponentCall (ValidateDataRef) 65 Component Error(GetLoadState)66 Component Error(GetMaxLoadedTime)65 ComponentCall (GetLoadState) 66 ComponentCall (GetMaxLoadedTime) 67 67 ComponentError (EstimateCompletionTime) 68 68 ComponentError (SetDontBlock) 69 69 ComponentError (GetDontBlock) 70 Component Error(SetIdleManager)70 ComponentCall (SetIdleManager) 71 71 ComponentError (SetNewMovieFlags) 72 72 ComponentCall (GetDestinationMediaType) trunk/ff_dataref.c
r194 r204 194 194 195 195 /* This is the public function to open bytecontext withs datarefs */ 196 OSStatus url_open_dataref(ByteIOContext *pb, Handle dataRef, OSType dataRefType )196 OSStatus url_open_dataref(ByteIOContext *pb, Handle dataRef, OSType dataRefType, DataHandler *dataHandler, Boolean *wideSupport, int64_t *dataSize) 197 197 { 198 198 URLContext *uc; … … 220 220 221 221 err = up->url_open(uc, uc->filename, URL_RDONLY); 222 222 223 if(err < 0) { 223 224 av_free(uc); … … 230 231 } 231 232 233 if(dataHandler) 234 *dataHandler = private->dh; 235 236 if(wideSupport) 237 *wideSupport = private->supportsWideOffsets; 238 239 if(dataSize) 240 *dataSize = private->size; 241 232 242 return noErr; 233 243 } /* url_open_dataref() */ trunk/ff_private.c
r196 r204 30 30 #include <CoreServices/CoreServices.h> 31 31 #include <AudioToolbox/AudioToolbox.h> 32 #include <QuickTime/QuickTime.h> 32 33 33 34 /* This routine checks if the system requirements are fullfilled */ … … 512 513 } /* prepare_movie() */ 513 514 515 int determine_header_offset(ff_global_ptr storage) { 516 AVFormatContext *formatContext; 517 AVPacket packet; 518 int result, i; 519 520 formatContext = storage->format_context; 521 result = noErr; 522 storage->header_offset = 0; 523 524 /* Seek backwards to get a manually read packet for file offset */ 525 if(formatContext->streams[0]->index_entries == NULL || storage->componentType == 'FLV ') 526 { 527 if (IS_AVI(storage->componentType)) 528 //Try to seek to the first frame; don't care if it fails 529 // Is this really needed for AVIs w/out an index? It seems to work fine without, 530 // and it seems that with it the first frame is skipped. 531 av_seek_frame(formatContext, -1, 0, 0); 532 storage->header_offset = 0; 533 } 534 else 535 { 536 result = av_seek_frame(formatContext, -1, 0, 0); 537 if(result < 0) goto bail; 538 539 formatContext->iformat->read_packet(formatContext, &packet); 540 /* read_packet will give the first decodable packet. However, that isn't necessarily 541 the first entry in the index, so look for an entry with a matching size. */ 542 for (i = 0; i < formatContext->streams[packet.stream_index]->nb_index_entries; i++) { 543 if (packet.size == formatContext->streams[packet.stream_index]->index_entries[i].size) { 544 storage->header_offset = packet.pos - formatContext->streams[packet.stream_index]->index_entries[i].pos; 545 break; 546 } 547 } 548 av_free_packet(&packet); 549 550 // seek back to the beginning, otherwise av_read_frame-based decoding will skip a few packets. 551 av_seek_frame(formatContext, -1, 0, 0); 552 } 553 554 bail: 555 return(result); 556 } 557 514 558 /* This function imports the avi represented by the AVFormatContext to the movie media represented 515 559 * in the map function. The aviheader_offset is used to calculate the packet offset from the 516 560 * beginning of the file. It returns whether it was successful or not (i.e. whether the file had an index) */ 517 short import_avi(AVFormatContext *ic, NCStream *map, int64_t aviheader_offset) 518 { 561 int import_using_index(ff_global_ptr storage, int *hadIndex, TimeValue *addedDuration) { 519 562 int j, k, l; 563 NCStream *map; 520 564 NCStream *ncstr; 565 AVFormatContext *ic; 521 566 AVStream *stream; 522 567 AVCodecContext *codec; 523 568 SampleReference64Ptr sampleRec; 524 int64_t offset,duration; 525 OSStatus err; 569 int64_t header_offset, offset, duration; 526 570 short flags; 527 short hadIndex = 0;528 571 int sampleNum; 572 ComponentResult result = noErr; 573 574 map = storage->stream_map; 575 ic = storage->format_context; 576 header_offset = storage->header_offset; 577 578 *hadIndex = 0; 579 580 //FLVs have unusable indexes, so don't even bother. 581 if(storage->componentType == 'FLV ') 582 goto bail; 529 583 530 584 /* process each stream in ic */ 531 585 for(j = 0; j < ic->nb_streams; j++) { 532 533 586 ncstr = &map[j]; 534 587 stream = ncstr->str; … … 539 592 continue; 540 593 594 /* no index, we might as well skip */ 595 if(stream->nb_index_entries == 0) 596 continue; 597 541 598 sampleNum = 0; 542 599 ncstr->sampleTable = calloc(stream->nb_index_entries, sizeof(SampleReference64Record)); … … 545 602 for(k = 0; k < stream->nb_index_entries; k++) { 546 603 547 hadIndex = 1;604 *hadIndex = 1; 548 605 549 606 /* file offset */ 550 offset = aviheader_offset + stream->index_entries[k].pos;607 offset = header_offset + stream->index_entries[k].pos; 551 608 552 609 /* flags */ … … 605 662 } 606 663 /* Add all of the samples to the media */ 607 err =AddMediaSampleReferences64(ncstr->media, ncstr->sampleHdl, sampleNum, ncstr->sampleTable, NULL);664 AddMediaSampleReferences64(ncstr->media, ncstr->sampleHdl, sampleNum, ncstr->sampleTable, NULL); 608 665 free(ncstr->sampleTable); 609 666 } 610 return hadIndex; 611 } /* import_avi() */ 612 613 /* This function imports the video file using standard av_read_frame() calls, 614 * which works on files that don't have an index */ 615 void import_without_index(AVFormatContext *ic, NCStream *map, int64_t aviheader_offset) 616 { 617 int i; 618 NCStream *ncstr; 667 668 if(*hadIndex == 0) 669 //No index, the remainder of this function will fail. 670 goto bail; 671 672 // insert media and set addedDuration; 673 for(j = 0; j < storage->map_count && result == noErr; j++) { 674 Media media = storage->stream_map[j].media; 675 if(media) { 676 Track track; 677 TimeRecord time; 678 TimeValue mediaDuration; 679 TimeScale mediaTimeScale; 680 TimeScale movieTimeScale; 681 682 mediaDuration = GetMediaDuration(media); 683 mediaTimeScale = GetMediaTimeScale(media); 684 movieTimeScale = GetMovieTimeScale(storage->movie); 685 686 /* we could handle this stream. 687 * convert the atTime parameter to track scale. 688 * FIXME: check if that's correct */ 689 time.value.hi = 0; 690 time.value.lo = storage->atTime; 691 time.scale = movieTimeScale; 692 time.base = NULL; 693 ConvertTimeScale(&time, mediaTimeScale); 694 695 track = GetMediaTrack(media); 696 result = InsertMediaIntoTrack(track, time.value.lo, 0, mediaDuration, fixed1); 697 698 if(result != noErr) 699 goto bail; 700 701 time.value.hi = 0; 702 time.value.lo = mediaDuration; 703 time.scale = mediaTimeScale; 704 time.base = NULL; 705 ConvertTimeScale(&time, movieTimeScale); 706 707 if(time.value.lo > *addedDuration) 708 *addedDuration = time.value.lo; 709 } 710 } 711 712 storage->loadedTime = *addedDuration; 713 714 bail: 715 return result; 716 } /* import_using_index() */ 717 718 /* Import function for movies that lack an index. 719 * Supports progressive importing, but will not idle if maxFrames == 0. 720 */ 721 ComponentResult import_with_idle(ff_global_ptr storage, long inFlags, long *outFlags, int minFrames, int maxFrames) { 722 SampleReference64Record sampleRec; 723 DataHandler dataHandler; 724 AVFormatContext *formatContext; 725 AVCodecContext *codecContext; 619 726 AVStream *stream; 620 AVCodecContext *codec; 621 SampleReference64Record sampleRec; 727 AVPacket packet; 728 NCStream *ncstream; 729 ComponentResult dataResult; //used for data handler operations that can fail. 730 ComponentResult result; 731 TimeValue minLoadedTime; 732 int64_t availableSize, margin; 733 long idling; 734 int readResult, framesProcessed, i; 622 735 short flags; 623 AVPacket pkt; 624 625 while(av_read_frame(ic, &pkt) == noErr) 626 { 627 ncstr = &map[pkt.stream_index]; 628 stream = ncstr->str; 629 codec = stream->codec; 630 736 737 dataHandler = storage->dataHandler; 738 formatContext = storage->format_context; 739 dataResult = noErr; 740 result = noErr; 741 minLoadedTime = 0; 742 availableSize = 0; 743 margin = 0; 744 idling = (inFlags & movieImportWithIdle); 745 framesProcessed = 0; 746 747 if(idling) { 748 //get the size of immediately available data 749 if(storage->dataHandlerSupportsWideOffsets) { 750 wide wideSize; 751 752 dataResult = DataHGetAvailableFileSize64(storage->dataHandler, &wideSize); 753 if(dataResult == noErr) availableSize = ((int64_t)wideSize.hi << 32) + wideSize.lo; 754 } else { 755 long longSize; 756 757 dataResult = DataHGetAvailableFileSize(storage->dataHandler, &longSize); 758 if(dataResult == noErr) availableSize = longSize; 759 } 760 } 761 762 // record stream durations before we add any samples so that we know what to tell InsertMediaIntoTrack later 763 for(i = 0; i < storage->map_count; i++) { 764 ncstream = &storage->stream_map[i]; 765 Media media = ncstream->media; 766 767 if(media) 768 ncstream->duration = GetMediaDuration(media); 769 } 770 771 while((readResult = av_read_frame(formatContext, &packet)) == 0) { 772 ncstream = &storage->stream_map[packet.stream_index]; 773 stream = ncstream->str; 774 codecContext = stream->codec; 631 775 flags = 0; 632 if((pkt.flags & PKT_FLAG_KEY) == 0) 776 777 if((packet.flags & PKT_FLAG_KEY) == 0) 633 778 flags |= mediaSampleNotSync; 634 779 635 780 memset(&sampleRec, 0, sizeof(sampleRec)); 636 sampleRec.dataOffset.hi = p kt.pos >> 32;637 sampleRec.dataOffset.lo = (uint32_t) pkt.pos;638 sampleRec.dataSize = p kt.size;781 sampleRec.dataOffset.hi = packet.pos >> 32; 782 sampleRec.dataOffset.lo = (uint32_t)packet.pos; 783 sampleRec.dataSize = packet.size; 639 784 sampleRec.sampleFlags = flags; 785 786 if(packet.size > storage->largestPacketSize) 787 storage->largestPacketSize = packet.size; 640 788 641 789 if(sampleRec.dataSize <= 0) 642 790 continue; 643 791 644 if (codec->codec_type == CODEC_TYPE_AUDIO && !ncstr->vbr)645 sampleRec.numberOfSamples = (p kt.size * ncstr->asbd.mFramesPerPacket) / ncstr->asbd.mBytesPerPacket;792 if(codecContext->codec_type == CODEC_TYPE_AUDIO && !ncstream->vbr) 793 sampleRec.numberOfSamples = (packet.size * ncstream->asbd.mFramesPerPacket) / ncstream->asbd.mBytesPerPacket; 646 794 else 647 sampleRec.numberOfSamples = 1; 648 649 // we have a sample waiting to be added; calculate the duration and add it 650 if (ncstr->lastSample.numberOfSamples > 0) { 651 ncstr->lastSample.durationPerSample = (pkt.pts - ncstr->lastpts) * ncstr->base.num; 652 AddMediaSampleReferences64(ncstr->media, ncstr->sampleHdl, 1, &ncstr->lastSample, NULL); 653 } 654 655 if (pkt.duration == 0) { 656 // no duration, we'll have to wait for the next packet to calculate it 795 sampleRec.numberOfSamples = 1; //packet.duration; 796 797 //add any samples waiting to be added 798 if(ncstream->lastSample.numberOfSamples > 0) { 799 //calculate the duration of the sample before adding it 800 ncstream->lastSample.durationPerSample = (packet.pts - ncstream->lastpts) * ncstream->base.num; 801 802 AddMediaSampleReferences64(ncstream->media, ncstream->sampleHdl, 1, &ncstream->lastSample, NULL); 803 } 804 805 if(packet.duration == 0) { 806 //no duration, we'll have to wait for the next packet to calculate it 657 807 // keep the duration of the last sample, so we can use it if it's the last frame 658 sampleRec.durationPerSample = ncstr->lastSample.durationPerSample; 659 ncstr->lastSample = sampleRec; 660 ncstr->lastpts = pkt.pts; 661 808 sampleRec.durationPerSample = ncstream->lastSample.durationPerSample; 809 ncstream->lastSample = sampleRec; 810 ncstream->lastpts = packet.pts; 662 811 } else { 663 ncstr->lastSample.numberOfSamples = 0; 664 if (codec->codec_type == CODEC_TYPE_AUDIO && !ncstr->vbr) 812 ncstream->lastSample.numberOfSamples = 0; 813 814 if(codecContext->codec_type == CODEC_TYPE_AUDIO && !ncstream->vbr) 665 815 sampleRec.durationPerSample = 1; 666 816 else 667 sampleRec.durationPerSample = pkt.duration * ncstr->base.num; 668 AddMediaSampleReferences64(ncstr->media, ncstr->sampleHdl, 1, &sampleRec, NULL); 669 } 670 #if 0 671 if(codec->codec_type == CODEC_TYPE_VIDEO) 672 { 673 if(pkt.duration == 0) 674 sampleRec.durationPerSample = map->base.num; 817 sampleRec.durationPerSample = ncstream->base.num * packet.duration; 818 819 AddMediaSampleReferences64(ncstream->media, ncstream->sampleHdl, 1, &sampleRec, NULL); 820 } 821 822 framesProcessed++; 823 824 //if we're idling, try really not to read past the end of available data 825 //otherwise we will cause blocking i/o. 826 if(idling && framesProcessed >= minFrames && availableSize > 0 && availableSize < storage->dataSize) { 827 margin = availableSize - (packet.pos + packet.size); 828 if(margin < (storage->largestPacketSize * 8)) { // 8x fudge factor for comfortable margin, could be tweaked. 829 av_free_packet(&packet); 830 break; 831 } 832 } 833 834 av_free_packet(&packet); 835 836 //stop processing if we've hit the max frame limit 837 if(maxFrames > 0 && framesProcessed >= maxFrames) 838 break; 839 } 840 841 if(readResult != 0) { 842 //if readResult != 0, we've hit the end of the stream. 843 //add any pending last frames. 844 for(i = 0; i < formatContext->nb_streams; i++) { 845 ncstream = &storage->stream_map[i]; 846 if(ncstream->lastSample.numberOfSamples > 0) 847 AddMediaSampleReferences64(ncstream->media, ncstream->sampleHdl, 1, &ncstream->lastSample, NULL); 848 } 849 } 850 851 for(i = 0; i < storage->map_count && result == noErr; i++) { 852 ncstream = &storage->stream_map[i]; 853 Media media = ncstream->media; 854 855 if(media) { 856 Track track = GetMediaTrack(media); 857 TimeScale mediaTimeScale = GetMediaTimeScale(media); 858 TimeValue prevDuration = ncstream->duration; 859 TimeValue mediaDuration = GetMediaDuration(media); 860 TimeValue addedDuration = mediaDuration - prevDuration; 861 TimeValue mediaLoadedTime = GetMovieTimeScale(storage->movie) * (double)mediaDuration / (double)mediaTimeScale; 862 863 if(minLoadedTime == 0 || mediaLoadedTime < minLoadedTime) 864 minLoadedTime = mediaLoadedTime; 865 866 if(addedDuration > 0) { 867 result = InsertMediaIntoTrack(track, -1, prevDuration, addedDuration, fixed1); 868 } 869 } 870 } 871 872 //set the loaded time to the length of the shortest track. 873 storage->loadedTime = minLoadedTime; 874 875 if(readResult != 0) { 876 //remove the placeholder track 877 if(storage->placeholderTrack != NULL) { 878 DisposeMovieTrack(storage->placeholderTrack); 879 storage->placeholderTrack = NULL; 880 } 881 882 //set the movie load state to complete, as well as mark the import output flag. 883 storage->movieLoadState = kMovieLoadStateComplete; 884 *outFlags |= movieImportResultComplete; 885 } else { 886 //if we're not yet done with the import, calculate the movie load state. 887 int64_t timeToCompleteFile; //time until the file should be completely available, in terms of AV_TIME_BASE 888 long dataRate; 889 890 dataResult = DataHGetDataRate(storage->dataHandler, 0, &dataRate); 891 if(dataResult == noErr) { 892 timeToCompleteFile = (AV_TIME_BASE * (storage->dataSize - availableSize)) / dataRate; 893 894 if(storage->loadedTime > (10 * GetMovieTimeScale(storage->movie)) && timeToCompleteFile < (storage->format_context->duration * .85)) 895 storage->movieLoadState = kMovieLoadStatePlaythroughOK; 675 896 else 676 sampleRec.durationPerSample = map->base.num * pkt.duration; 677 sampleRec.numberOfSamples = 1; 678 } 679 else if (codec->codec_type == CODEC_TYPE_AUDIO) 680 { 681 if(ncstr->vbr) { 682 if(codec->frame_size == ncstr->base.num) { 683 sampleRec.durationPerSample = codec->frame_size; 684 sampleRec.numberOfSamples = 1; 685 } else if (ncstr->asbd.mFormatID == kAudioFormatMPEG4AAC) { 686 /* AVI-mux GUI, the author of which created this hack in the first place, 687 * seems to special-case getting an AAC audio sample's duration this way */ 688 sampleRec.durationPerSample = ic->streams[pkt.stream_index]->time_base.num; 689 sampleRec.numberOfSamples = 1; 690 } else { 691
