Changeset 311

Show
Ignore:
Timestamp:
01/28/07 00:44:15 (2 years ago)
Author:
astrange
Message:

Import SSA via a temporary movie file.
This actually works.

(Creates one file per SSA subtitle opened, which persists until reboot.)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/MatroskaImportPrivate.cpp

    r310 r311  
    456456                 
    457457        } else if ((*imgDesc)->cType == kSubFormatUTF8) { 
    458                 mkvTrack.theTrack = CreatePlaintextSubTrack(theMovie, imgDesc, GetMovieTimeScale(theMovie), dataRef, dataRefType, kSubFormatUTF8); 
     458                Rect movieBox; 
     459                GetMovieBox(theMovie,&movieBox); 
     460                mkvTrack.theTrack = CreatePlaintextSubTrack(theMovie, imgDesc, GetMovieTimeScale(theMovie), dataRef, dataRefType, kSubFormatUTF8, NULL, movieBox); 
    459461                if (mkvTrack.theTrack == NULL) 
    460462                        return GetMoviesError(); 
  • trunk/SSADocument.m

    r310 r311  
    473473@end 
    474474 
     475//based on Apple sample code http://developer.apple.com/samplecode/QTKitCreateMovie/listing5.html 
     476 
     477static Movie CreateQuicktimeMovieFromTempFile(DataHandler * outDataHandler, OSErr *outErr, NSString **movieName) 
     478{ 
     479        *outErr = -1; 
     480        char *c_tempName = tempnam(NULL,"perian-subtitle-"); 
     481         
     482        // generate a name for our movie file 
     483        NSString *tempName = [NSString stringWithCString:c_tempName  
     484                                                                                        encoding:[NSString defaultCStringEncoding]]; 
     485        if (nil == tempName) goto nostring; 
     486        free(c_tempName); 
     487         
     488        Handle  dataRefH    = nil; 
     489        OSType  dataRefType; 
     490         
     491        // create a file data reference for our movie 
     492        *outErr = QTNewDataReferenceFromFullPathCFString((CFStringRef)tempName, 
     493                                                                                                         kQTNativeDefaultPathStyle, 
     494                                                                                                         0, 
     495                                                                                                         &dataRefH, 
     496                                                                                                         &dataRefType); 
     497        if (*outErr != noErr) goto nodataref; 
     498         
     499        // create a QuickTime movie from our file data reference 
     500        Movie  qtMovie  = nil; 
     501        CreateMovieStorage (dataRefH, 
     502                                                dataRefType, 
     503                                                'TVOD', 
     504                                                smSystemScript, 
     505                                                newMovieActive,  
     506                                                outDataHandler, 
     507                                                &qtMovie); 
     508        *outErr = GetMoviesError(); 
     509        if (*outErr != noErr) goto cantcreatemovstorage; 
     510         
     511        return qtMovie; 
     512         
     513        // error handling 
     514cantcreatemovstorage: 
     515                DisposeHandle(dataRefH); 
     516nodataref: 
     517nostring: 
     518                 
     519                return nil; 
     520} 
     521 
     522/* 
     523 We import SSA by creating a temporary movie, adding samples to it, and copying it to the current movie, which can't have samples added to it as it's read-only. 
     524  
     525 I tried to use an in-memory temporary, but it completely failed to work. 
     526  
     527 This works except for saving reference movies, which include a dependency on the temporary file. They will break when it's deleted upon restart. 
     528 I don't see any apparent workaround. 
     529 */ 
    475530ComponentResult LoadSubStationAlphaSubtitles(const FSRef *theDirectory, CFStringRef filename, Movie theMovie, Track *firstSubTrack) 
    476531{ 
    477532        ComponentResult err = noErr; 
    478         Handle dataRef = NULL; 
    479         OSType dataRefType = rAliasType; 
    480         HFSUniStr255 hfsFilename; 
    481         CFRange filenameLen; 
    482         Track theTrack = NULL; 
    483         Media theMedia = NULL; 
     533        Track theTrack = NULL, track2 = NULL; 
     534        Media theMedia = NULL, media2 = NULL; 
    484535        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    485536        SSADocument *ssa = [[SSADocument alloc] init]; 
    486537        static UInt8 path[PATH_MAX]; 
    487         Handle sampleHndl = NULL, headerHndl=NULL, drefHndl = NewHandle(sizeof(Handle)), drefDataH = NewHandle(0); 
    488         ComponentInstance dataHandler = NULL; 
    489         long filePos = 0; 
    490         long fileSize; 
     538        Handle sampleHndl = NULL, headerHndl=NULL; 
    491539        char *data = NULL; const char *header; 
    492540        int i, packetCount, sampleLen; 
    493541        ImageDescriptionHandle textDesc; 
     542        DataHandler tempStor; 
     543        Movie tempMovie; 
     544        OSErr oErr; 
     545        NSString *movieName; 
     546        Rect movieBox; 
    494547         
    495548        FSRefMakePath(theDirectory, path, PATH_MAX); 
     
    505558        PtrToHand(header, &headerHndl, sampleLen); 
    506559         
    507         *((Handle*)*drefHndl) = drefDataH; 
    508                  
    509         theTrack = CreatePlaintextSubTrack(theMovie, textDesc, 100, drefHndl, HandleDataHandlerSubType, (ssa->version==S_ASS) ? kSubFormatASS : kSubFormatSSA); 
     560        tempMovie = CreateQuicktimeMovieFromTempFile(&tempStor,&oErr,&movieName); 
     561 
     562        GetMovieBox(theMovie, &movieBox); 
     563         
     564        theTrack = CreatePlaintextSubTrack(tempMovie, textDesc, 100, NULL, 0, kSubFormatSSA, headerHndl, movieBox); 
    510565        if (theTrack == NULL) { 
    511566                err = GetMoviesError(); 
    512567                goto bail; 
    513568        } 
    514          
    515         AddImageDescriptionExtension(textDesc,headerHndl, (ssa->version==S_ASS) ? kSubFormatASS : kSubFormatSSA); 
    516  
     569                 
    517570        theMedia = GetTrackMedia(theTrack); 
    518571        if (theMedia == NULL) { 
     
    522575         
    523576        BeginMediaEdits(theMedia); 
    524          
     577 
    525578        for (i = 0; i < packetCount; i++) { 
    526579                SSAEvent *p = [ssa movPacket:i]; 
     580                TimeRecord movieStartTime = { SInt64ToWide(p->begin_time), 100, 0 }; 
    527581                const char *str = [p->line UTF8String]; 
    528582                sampleLen = strlen(str); 
     
    531585 
    532586                err=AddMediaSample(theMedia,sampleHndl,0,sampleLen, p->end_time - p->begin_time,(SampleDescriptionHandle)textDesc, 1, 0, NULL); 
    533                 if (err != noErr) {NSLog(@"a %d",GetMoviesError()); goto bail;} 
    534                 //note on -1: we sorted the subtitles already, so we know they can be added to the end of the track. 
    535                 InsertMediaIntoTrack(theTrack,-1,p->begin_time,p->end_time - p->begin_time,fixed1); 
    536                 if (err != noErr) NSLog(@"i %d",GetMoviesError()); 
     587                if (err != noErr) {goto bail;} 
    537588 
    538589                DisposeHandle(sampleHndl); 
     
    541592        EndMediaEdits(theMedia); 
    542593                 
     594        InsertMediaIntoTrack(theTrack,0,0,GetMediaDuration(theMedia),fixed1); 
     595        if (err != noErr) {goto bail;} 
     596 
     597        track2 = CreatePlaintextSubTrack(theMovie, textDesc, 100, NULL, 0, kSubFormatSSA, headerHndl, movieBox); 
     598         
     599        media2 = GetTrackMedia(track2); 
     600         
     601        BeginMediaEdits(media2); 
     602        err=InsertTrackSegment(theTrack,track2,0,GetTrackDuration(theTrack),0); 
     603        EndMediaEdits(media2); 
     604         
     605         
    543606        if (*firstSubTrack == NULL) 
    544                 *firstSubTrack = theTrack
     607                *firstSubTrack = track2
    545608        else 
    546                 SetTrackAlternate(*firstSubTrack, theTrack); 
    547          
    548         SetMediaLanguage(theMedia, GetFilenameLanguage(filename)); 
     609                SetTrackAlternate(*firstSubTrack, track2); 
     610         
     611        SetMediaLanguage(media2, GetFilenameLanguage(filename)); 
    549612         
    550613bail: 
    551                  
    552         [ssa release]; 
    553         [pool release]; 
    554614         
    555615        if (err) { 
     
    565625         
    566626        if (headerHndl) DisposeHandle((Handle)headerHndl); 
    567         //DisposeHandle((Handle)drefDataH); 
    568         DisposeHandle((Handle)drefHndl); 
     627        CloseMovieStorage(tempStor); 
     628        DisposeMovieTrack(theTrack); 
     629        DisposeMovie(tempMovie); 
     630        //unlink([movieName UTF8String]); 
     631         
     632        [ssa release]; 
     633        [pool release]; 
    569634         
    570635        return err; 
  • trunk/SubImport.c

    r310 r311  
    5858 
    5959Track CreatePlaintextSubTrack(Movie theMovie, ImageDescriptionHandle imgDesc,  
    60                               TimeScale timescale, Handle dataRef, OSType dataRefType, FourCharCode subType) 
    61 
    62         Rect movieBox; 
     60                              TimeScale timescale, Handle dataRef, OSType dataRefType, FourCharCode subType, Handle imageExtension, Rect movieBox) 
     61
    6362        Fixed trackWidth, trackHeight; 
    6463        Track theTrack; 
     
    6665 
    6766        // plain text subs have no size on their own 
    68         GetMovieBox(theMovie, &movieBox); 
    6967        trackWidth = IntToFixed(movieBox.right - movieBox.left); 
    7068        trackHeight = IntToFixed(movieBox.bottom - movieBox.top); 
     
    7876        (*imgDesc)->clutID = -1; 
    7977 
     78        if (imageExtension) AddImageDescriptionExtension(imgDesc, imageExtension, subType); 
     79 
    8080        theTrack = NewMovieTrack(theMovie, trackWidth, trackHeight, kNoVolume); 
    8181        if (theTrack != NULL) { 
     
    103103        Track theTrack = NULL; 
    104104        Media theMedia = NULL; 
     105        Rect movieBox; 
    105106 
    106107        ComponentInstance dataHandler = NULL; 
     
    139140        data[fileSize] = '\0'; 
    140141 
     142        GetMovieBox(theMovie, &movieBox); 
     143 
    141144        // millisecond accuracy 
    142         theTrack = CreatePlaintextSubTrack(theMovie, textDesc, 1000, dataRef, dataRefType, kSubFormatUTF8); 
     145        theTrack = CreatePlaintextSubTrack(theMovie, textDesc, 1000, dataRef, dataRefType, kSubFormatUTF8, NULL, movieBox); 
    143146        if (theTrack == NULL) { 
    144147                err = GetMoviesError(); 
  • trunk/SubImport.h

    r310 r311  
    2222 
    2323Track CreatePlaintextSubTrack(Movie theMovie, ImageDescriptionHandle imgDesc,  
    24                               TimeScale timescale, Handle dataRef, OSType dataRefType, FourCharCode subType); 
     24                              TimeScale timescale, Handle dataRef, OSType dataRefType, FourCharCode subType, Handle imageExtension, Rect movieBox); 
     25 
     26short GetFilenameLanguage(CFStringRef filename); 
    2527 
    2628#ifdef __cplusplus