source: trunk/SSADocument.m @ 338

Revision 338, 19.2 KB checked in by astrange, 7 years ago (diff)

Mark VobSub? decoder thread-safe (closes #95).
Handle SSA BackColour? properly.
More of the traditional subtitle and mkv files, including possibly fixing VobSub?.

Line 
1/*
2 *  SSARenderCodec.m
3 *  Copyright (c) 2007 Perian Project
4 *
5 *  This program is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation;
8 *  version 2.1 of the License.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 *
19 */
20
21#import "SSADocument.h"
22#import "Categories.h"
23#include "SubImport.h"
24
25@implementation SSADocument
26
27// This line contains the default style, for SRT files.
28
29static ssastyleline SSA_DefaultStyle = (ssastyleline){
30        @"Default",@"Helvetica",
31        32 * (96./72.),
32{{1,1,1,1},{1,1,1,1},{0,0,0,1},{0,0,0,1}}, // white on black
33        1,0,0,0,
34        100,100,0,0,
35        0,1.5,1.5,
36        2,1,0,
37        10,10,10,
38        NULL, NULL
39};
40
41-(void)dealloc
42{
43        int i;
44        if (disposedefaultstyle) free(defaultstyle);
45        for (i=0; i < stylecount; i++) {ATSUDisposeStyle(styles[i].atsustyle); ATSUDisposeTextLayout(styles[i].layout);}
46       
47        [_lines release];
48        [header release];
49        [super dealloc];
50}
51
52static ATSURGBAlphaColor SSAParseColor(NSString *c)
53{
54        const char *c_ = [c UTF8String];
55        unsigned char r, g, b, a;
56        unsigned int rgb;
57       
58        if (c_[0] == '&') {
59                rgb = strtoul(&c_[2],NULL,16);
60        } else {
61                rgb = strtol(c_,NULL,0);
62        }
63       
64        a = (rgb >> 24) & 0xff;
65        b = (rgb >> 16) & 0xff;
66        g = (rgb >> 8) & 0xff;
67        r = rgb & 0xff;
68
69        a = 255-a;
70       
71        return (ATSURGBAlphaColor){(float)r/255.,(float)g/255.,(float)b/255.,(float)a/255.};
72}
73
74-(void)setupHeaders:(NSDictionary*)hDict width:(float)width height:(float)height
75{
76        NSString *field;
77        float rX=-1, rY=-1, aspect = width / height;
78        if (field = [hDict objectForKey:@"PlayResX"]) rX = [field doubleValue];
79        if (field = [hDict objectForKey:@"PlayResY"]) rY = [field doubleValue];
80        if (rX > 0 && rY == -1) {
81                rY = rX / aspect;
82        } else if (rX == -1 && rY > 0) {
83                rX = rY * aspect;
84        } else if (rX == -1 && rY == -1) {
85                rX = 384; //magic numbers are ssa defaults
86                rY = 288;
87        }
88       
89        resX = rX; resY = rY;
90       
91        timescale = (field = [hDict objectForKey:@"Timer"])? [field doubleValue] / 100. : 1.;
92        collisiontype = Normal;
93        if ((field = [hDict objectForKey:@"Collisions"]) && [field isEqualToString:@"Reverse"]) collisiontype = Reverse;
94        if (field = [hDict objectForKey:@"ScriptType"]) {
95                if ([field isEqualToString:@"v4.00+"]) version = S_ASS;
96                else version = S_SSA;
97        }
98}
99
100int SSA2ASSAlignment(int a)
101{
102        if (a >= 7 && a <= 9) return a-3;
103        if (a >= 4 && a <= 6) return a+3;
104        if (a > 9 || a < 1) return 2;
105        return a;
106}
107
108-(void) makeATSUStylesForSSAStyle:(ssastyleline *)s
109{
110        {
111                ATSUAttributeTag tags[] = {kATSUFontTag, kATSUFontMatrixTag, kATSUStyleRenderingOptionsTag, kATSUSizeTag, kATSUTrackingTag, kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag, kATSUStyleStrikeThroughTag};
112                ByteCount                sizes[] = {sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(ATSStyleRenderingOptions), sizeof(Fixed), sizeof(Fixed), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean)};
113                ATSUFontID      font;
114                CGAffineTransform matrix;
115                ATSStyleRenderingOptions opt = kATSStyleApplyAntiAliasing;
116                Fixed size, tracking;
117               
118                ATSUAttributeValuePtr vals[] = {&font, &matrix, &opt, &size, &tracking, &s->bold, &s->italic, &s->underline, &s->strikeout};
119                char fname[256] = {0};
120                ByteCount fl = 256;
121               
122                font = FMGetFontFromATSFontRef(ATSFontFindFromName((CFStringRef)s->font,kATSOptionFlagsDefault));
123                //ATSUFindFontName(font,kFontFullName,kFontMacintoshPlatform,kFontNoScriptCode,kFontNoLanguage,fl,(char*)fname,&fl,NULL);
124                //kFontUnicodePlatform and MicrosoftPlatform are both pretty broken. asian fonts aren't found sometimes. this is an apple bug.
125               
126                if (font == kInvalidFont)
127                        font = FMGetFontFromATSFontRef(ATSFontFindFromName((CFStringRef)@"Helvetica",kATSOptionFlagsDefault));
128                //else NSLog(@"found font \"%s\" for name \"%@\"",fname,s->font);
129               
130                matrix = CGAffineTransformMakeScale(s->scalex/100.,s->scaley/100.);
131               
132                float scalesize = s->fsize * (72./96.);
133                size = FloatToFixed(scalesize); // scale from Windows 96 dpi size
134               
135                tracking = FloatToFixed(s->tracking); // i am really not sure about this!
136               
137                ATSUCreateStyle(&s->atsustyle);
138                ATSUSetAttributes(s->atsustyle,sizeof(vals) / sizeof(ATSUAttributeValuePtr),tags,sizes,vals);
139               
140                ATSUFontFeatureType             ftype[] = {kLigaturesType,kLigaturesType};
141                ATSUFontFeatureSelector fsel[] = {kCommonLigaturesOnSelector,kRareLigaturesOnSelector};
142               
143                ATSUSetFontFeatures(s->atsustyle,sizeof(fsel) / sizeof(ATSUFontFeatureSelector),ftype,fsel);
144        }
145       
146        {
147                ATSUAttributeTag tags[] = {kATSULineFlushFactorTag, kATSULineRotationTag, kATSULineWidthTag};
148                ByteCount                sizes[] = {sizeof(Fract), sizeof(Fract), sizeof(ATSUTextMeasurement)};
149                Fract alignment, rotation = FloatToFract(s->angle);
150                ATSUTextMeasurement width;
151                ATSUAttributeValuePtr vals[] = {&alignment, &rotation, &width};
152               
153                switch(s->halign) {
154                        case S_LeftAlign:
155                                alignment = FloatToFract(0.);
156                                break;
157                        case S_CenterAlign: default:
158                                alignment = kATSUCenterAlignment; 
159                                break;
160                        case S_RightAlign:
161                                alignment = FloatToFract(1.);
162                }
163               
164                s->usablewidth = resX - s->marginl - s->marginr;
165                width = IntToFixed(s->usablewidth);
166                ATSUCreateTextLayout(&s->layout);
167                ATSUSetLayoutControls(s->layout,sizeof(vals) / sizeof(ATSUAttributeValuePtr),tags,sizes,vals);
168        }
169}
170
171#define fv(sn, fn) if (field = [style objectForKey:@"" # sn]) s.fn = [field doubleValue];
172#define iv(sn, fn) if (field = [style objectForKey:@"" # sn]) s.fn = [field intValue];
173#define sv(sn, fn) if (field = [style objectForKey:@"" # sn]) s.fn = [field retain];
174#define cv(sn, fn) if (field = [style objectForKey:@"" # sn]) s.color.fn = SSAParseColor(field);
175#define bv(sn, fn) if (field = [style objectForKey:@"" # sn]) s.fn = [field intValue] != 0;
176
177-(void)setupStyles:(NSDictionary*)sDict
178{
179        defaultstyle = NULL;
180
181        if ([sDict count] > 0) {
182                NSEnumerator *sEnum = [sDict objectEnumerator];
183                NSDictionary *style; int i=0;
184               
185                stylecount = [sDict count];
186                styles = malloc(sizeof(ssastyleline[stylecount]));
187                while (style = [sEnum nextObject]) {
188                        ssastyleline s = {0}; NSString *field;
189                       
190                        s.scalex = s.scaley = 100;
191                       
192                        sv(Name, name)
193                                sv(Fontname, font)
194                                fv(Fontsize, fsize)
195                                cv(PrimaryColour, primary)
196                                cv(SecondaryColour, secondary)
197                                cv(OutlineColour, outline)
198                        //      cv(TertiaryColour, outline)
199                                cv(BackColour, outline)
200                                cv(BackColour, shadow)
201                                bv(Bold, bold)
202                                bv(Italic, italic)
203                                bv(Underline, underline)
204                                bv(StrikeOut, strikeout)
205                                fv(ScaleX, scalex)
206                                fv(ScaleY, scaley)
207                                fv(Spacing, tracking)
208                                fv(Angle, angle)
209                                iv(BorderStyle, borderstyle)
210                                fv(Outline, outline)
211                                fv(Shadow, shadow)
212                                iv(Alignment, alignment)
213                                iv(MarginL, marginl)
214                                iv(MarginR, marginr)
215                                iv(MarginV, marginv)
216                               
217                                if ([s.font length] > 512) s.font = @"Helvetica";
218                       
219                        if (version == S_SSA) s.alignment = SSA2ASSAlignment(s.alignment);
220                        switch (s.alignment) {case 1: case 4: case 7: s.halign = S_LeftAlign; break; case 2: case 5: case 8: default: s.halign = S_CenterAlign; break; case 3: case 6: case 9: s.halign = S_RightAlign;}
221                        switch (s.alignment) {case 1: case 2: case 3: default: s.valign = S_BottomAlign; break; case 4: case 5: case 6: s.valign = S_MiddleAlign; break; case 7: case 8: case 9: s.valign = S_TopAlign;}
222                       
223                        [self makeATSUStylesForSSAStyle:&s];
224                       
225                        styles[i] = s;
226                        if (!defaultstyle && [styles[i].name isEqualToString:@"Default"]) {defaultstyle = &styles[i]; disposedefaultstyle = NO;}
227                        i++;
228                }
229        }
230       
231        if (!defaultstyle) {
232                disposedefaultstyle = YES;
233                defaultstyle = malloc(sizeof(ssastyleline));
234                *defaultstyle = SSA_DefaultStyle;
235                [self makeATSUStylesForSSAStyle:defaultstyle];
236        }
237}
238
239-(SubLine *)movPacket:(int)i
240{
241        return [_lines objectAtIndex:i];
242}
243
244static unsigned ParseSSATime(NSString *str)
245{
246        int h,m,s,ms;
247        const char *cs = [str UTF8String];
248       
249        sscanf(cs,"%d:%d:%d.%d",&h,&m,&s,&ms);
250        return ms + s * 100 + m * 100 * 60 + h * 100 * 60 * 60;
251}
252
253static BOOL isinrange(unsigned base, unsigned test_s, unsigned test_e)
254{
255        return (base >= test_s) && (base < test_e);
256}
257
258static NSString *oneMKVPacket(NSDictionary *s)
259{
260        return [NSString stringWithFormat:@"%d,%d,%@,%@,%0.4d,%0.4d,%0.4d,%@,%@\n",
261                [[s objectForKey:@"ReadOrder"] intValue],
262                [[s objectForKey:@"Layer"] intValue],
263                [s objectForKey:@"Style"],
264                [s objectForKey:@"Name"],
265                [[s objectForKey:@"MarginL"] intValue],
266                [[s objectForKey:@"MarginR"] intValue],
267                [[s objectForKey:@"MarginV"] intValue],
268                [s objectForKey:@"Effect"],
269                [s objectForKey:@"Text"]];     
270}
271
272-(NSArray *)serializeSubLines:(NSMutableArray*)linesa
273{
274        int num = [linesa count], i;
275        NSMutableArray *outa = [[NSMutableArray alloc] init];
276        SubtitleSerializer *serializer = [[SubtitleSerializer alloc] init];
277        SubLine *sl;
278       
279        for (i = 0; i < num; i++) {
280                NSDictionary *l = [linesa objectAtIndex:i];;
281                NSString *s,*e;
282                SubLine *li;
283               
284                s = [l objectForKey:@"Start"];
285                e = [l objectForKey:@"End"];
286               
287                li = [[[SubLine alloc] initWithLine:oneMKVPacket(l) start:ParseSSATime(s) end:ParseSSATime(e)] autorelease];
288               
289                if (timescale != 1.) {
290                        li->begin_time *= timescale;
291                        li->end_time *= timescale;
292                }
293
294                [serializer addLine:li];
295        }
296       
297        [serializer setFinished:YES];
298       
299        while (sl = [serializer getSerializedPacket]) {
300                [outa addObject:sl];
301        }
302       
303        [serializer release];
304        return outa;
305}
306
307-(void) loadFile:(NSString*)path
308{
309        NSString *ssa = [[NSString stringFromUnknownEncodingFile:path] stringByStandardizingNewlines];
310        if (!ssa) return;
311        NSArray *lines = [ssa componentsSeparatedByString:@"\n"];
312        NSEnumerator *lenum = [lines objectEnumerator];
313        NSString *nextLine, *styleType, *ns;
314        NSArray *format;
315        NSMutableDictionary *headers, *styleDict;
316        NSMutableArray *doclines;
317        NSCharacterSet *ws = [NSCharacterSet whitespaceCharacterSet];
318        unichar cai;
319        int formatc;
320        int readorder = 0;
321       
322        headers = [[NSMutableDictionary alloc] init];
323        styleDict = [NSMutableDictionary dictionary];
324        doclines = [NSMutableArray array];
325       
326        if (![(NSString*)[lenum nextObject] isEqualToString:@"[Script Info]"]) return;
327        while (1) {
328                ns = (NSString*)[lenum nextObject];
329                if (!ns || [ns length] == 0) continue;
330                else {
331                        cai = [ns characterAtIndex:0];
332                       
333                        if (cai == ';') continue;
334                        else if (cai == '[') {nextLine = ns; break;}
335                        NSArray *pair = [ns pairSeparatedByString:@": "];
336                        if ([pair count] == 2) [headers setObject:[(NSString*)[pair objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] forKey:[pair objectAtIndex:0]];
337                }
338               
339        }
340       
341        [self setupHeaders:headers width:640 height:480];
342
343        while (![nextLine isEqualToString:@"[Events]"]) nextLine = [lenum nextObject];
344        while ([nextLine length] == 0) nextLine = [lenum nextObject];
345        nextLine = [lenum nextObject];
346       
347        NSArray *pair = [nextLine pairSeparatedByString:@": "];
348        NSString *formatstring = (version == S_ASS) ?
349                @"Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
350                                                                                                                                 :
351                @"Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text";
352       
353        if ([pair count] == 2 && [(NSString*)[pair objectAtIndex:0] isEqualToString:@"Format"]) {formatstring = (NSString*)[pair objectAtIndex:1]; ns = [lenum nextObject];} else ns = nextLine;
354        format = [[formatstring stringByTrimmingCharactersInSet:ws] componentsSeparatedByString:@", "];
355        formatc = [format count];
356       
357        while (1) {
358                if (!ns) break;
359                else if ([ns length] != 0) {
360                        pair = [ns pairSeparatedByString:@": "];
361                        if ([pair count] == 2 && [(NSString*)[pair objectAtIndex:0] isEqualToString:@"Dialogue"]) {
362                                NSArray *curl = [(NSString*)[pair objectAtIndex:1] componentsSeparatedByString:@"," count:formatc];
363                                int count = MIN([format count], [curl count]), i;
364                                NSMutableDictionary *lDict = [NSMutableDictionary dictionary];
365                                for (i=0; i < count; i++) [lDict setObject:[curl objectAtIndex:i] forKey:[format objectAtIndex:i]];
366                                [lDict setObject:[NSString stringWithFormat:@"%d",readorder++] forKey:@"ReadOrder"];
367                                [doclines addObject:lDict];
368                        }
369                }
370                ns = [lenum nextObject];
371        }
372       
373        _lines = [self serializeSubLines:doclines];
374       
375        header = [[ssa substringToIndex:[ssa rangeOfString:@"[Events]" options:NSLiteralSearch].location] retain];
376}
377
378-(void) loadHeader:(NSString*)ssa width:(float)width height:(float)height
379{
380        NSError *err;
381        NSStringEncoding se = NSUTF8StringEncoding;
382        if (!ssa) return;
383        NSArray *lines = [[ssa stringByStandardizingNewlines] componentsSeparatedByString:@"\n"];
384        NSEnumerator *lenum = [lines objectEnumerator];
385        NSString *nextLine, *styleType, *ns;
386        NSArray *format;
387        NSMutableDictionary *headers, *styleDict;
388        NSMutableArray *doclines;
389        NSCharacterSet *ws = [NSCharacterSet whitespaceCharacterSet];
390        unichar cai;
391        int formatc;
392        int readorder = 0;
393       
394        headers = [[NSMutableDictionary alloc] init];
395        styleDict = [NSMutableDictionary dictionary];
396        doclines = [NSMutableArray array];
397       
398        nextLine = [[lenum nextObject] stringByTrimmingCharactersInSet:ws];
399       
400        if (![nextLine isEqualToString:@"[Script Info]"]) {
401                NSLog(@"\"%@\" is not a valid SSA header?",nextLine);
402                return;
403        }
404        while (1) {
405                ns = (NSString*)[lenum nextObject];
406                if (!ns || [ns length] == 0) continue;
407                else {
408                        cai = [ns characterAtIndex:0];
409                       
410                        if (cai == ';') continue;
411                        else if (cai == '[') {nextLine = ns; break;}
412                        NSArray *pair = [ns pairSeparatedByString:@": "];
413                        if ([pair count] == 2) [headers setObject:[(NSString*)[pair objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] forKey:[pair objectAtIndex:0]];
414                }
415               
416        }
417       
418        [self setupHeaders:headers width:width height:height];
419       
420        while (!([nextLine isEqualToString:@"[V4 Styles]"] || [nextLine isEqualToString:@"[V4+ Styles]"])) nextLine = [lenum nextObject];
421        styleType = nextLine;
422        while ([nextLine length] == 0) nextLine = [lenum nextObject];
423        nextLine = [lenum nextObject];
424       
425        NSArray *pair = [nextLine pairSeparatedByString:@": "];
426        NSString *formatstring = ([styleType isEqualToString:@"[V4+ Styles]"]) ?
427                @"Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"
428                                                                                                                                                   :
429                @"Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding";
430       
431        if ([pair count] == 2 && [(NSString*)[pair objectAtIndex:0] isEqualToString:@"Format"]) {formatstring = (NSString*)[pair objectAtIndex:1]; ns = [lenum nextObject];} else ns = nextLine;
432       
433        format = [[formatstring stringByTrimmingCharactersInSet:ws] componentsSeparatedByString:@", "];
434        formatc = [format count];
435       
436        while (1) {
437                if (!ns) break;
438                else if ([ns length] != 0) {
439                        cai = [ns characterAtIndex:0];
440                       
441                        if (cai == '[') {nextLine = ns; break;}
442                        if (cai != ';' && cai != '!') {
443                                NSArray *pair = [ns pairSeparatedByString:@": "];
444                                if ([pair count] == 2) {
445                                        NSArray *style = [(NSString*)[pair objectAtIndex:1] componentsSeparatedByString:@"," count:formatc]; // bug in SSA: font names with , break it
446                                        int count = MIN([format count], [style count]), i;
447                                        NSMutableDictionary *styled = [NSMutableDictionary dictionary];
448                                        for (i=0; i < count; i++) [styled setObject:[style objectAtIndex:i] forKey:[format objectAtIndex:i]];
449                                        [styleDict setObject:styled forKey:[styled objectForKey:@"Name"]];
450                                }
451                        }
452                }
453                ns = [lenum nextObject];
454        }
455       
456        [self setupStyles:styleDict];
457}
458
459-(void)loadDefaultsWithWidth:(float)width height:(float)height
460{
461        stylecount = 0;
462        styles = malloc(0);
463        defaultstyle = malloc(sizeof(ssastyleline));
464        *defaultstyle = SSA_DefaultStyle;
465        disposedefaultstyle = YES;
466        resX = (width / height) * 480.; resY = 480;
467        timescale = 1;
468        collisiontype = Normal;
469        version = S_ASS;
470       
471        [self makeATSUStylesForSSAStyle:defaultstyle];
472}
473
474-(NSString*)header
475{
476        return header;
477}
478
479-(unsigned)packetCount
480{
481        return [_lines count];
482}
483@end
484
485ComponentResult LoadSubStationAlphaSubtitles(const FSRef *theDirectory, CFStringRef filename, Movie theMovie, Track *firstSubTrack)
486{
487        ComponentResult err = noErr;
488        Track theTrack = NULL;
489        Media theMedia = NULL;
490        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
491        SSADocument *ssa = [[SSADocument alloc] init];
492        Handle sampleHndl = NULL, headerHndl=NULL, drefHndl;
493        Ptr initData = NewPtr(0);
494        const char *header;
495        int i, packetCount, sampleLen;
496        ImageDescriptionHandle textDesc;
497        Rect movieBox;
498        UInt32 emptyDataRefExtension[2];
499        TimeScale movieTimeScale = GetMovieTimeScale(theMovie);
500        UInt8 *path = malloc(PATH_MAX);
501
502        FSRefMakePath(theDirectory, path, PATH_MAX);
503       
504        [ssa loadFile:[[NSString stringWithUTF8String:(char*)path] stringByAppendingPathComponent:(NSString*)filename]];
505       
506        free(path);
507       
508        packetCount = [ssa packetCount];
509       
510        textDesc = (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
511       
512        header = [[ssa header] UTF8String];
513        sampleLen = strlen(header);
514        PtrToHand(header, &headerHndl, sampleLen);
515       
516        drefHndl = NewHandleClear(sizeof(Handle) + 1);
517       
518        /* Explanation of next three lines:
519         * The magic 'data' atom, added to an in-memory data handler, allows its data to be saved by value to a reference movie.
520         * It does this by saving the whole thing in the MOV header.
521         * This is imperfectly documented.
522         */
523        emptyDataRefExtension[0] = EndianU32_NtoB(sizeof(UInt32)*2);
524        emptyDataRefExtension[1] = EndianU32_NtoB(kDataRefExtensionInitializationData);
525       
526        PtrAndHand(&emptyDataRefExtension[0], drefHndl, sizeof(emptyDataRefExtension));
527               
528        GetMovieBox(theMovie,&movieBox);
529        theTrack = CreatePlaintextSubTrack(theMovie, textDesc, 100, drefHndl, HandleDataHandlerSubType, 'SSA ', headerHndl, movieBox);
530        if (theTrack == NULL) {
531                err = GetMoviesError();
532                goto bail;
533        }
534       
535        theMedia = GetTrackMedia(theTrack);
536        if (theMedia == NULL) {
537                err = GetMoviesError();
538                goto bail;
539        }
540       
541        BeginMediaEdits(theMedia);
542       
543        for (i = 0; i < packetCount; i++) {
544                SubLine *p = [ssa movPacket:i];
545                TimeRecord movieStartTime = {SInt64ToWide(p->begin_time), 100, 0};
546                TimeValue sampleTime;
547                const char *str = [p->line UTF8String];
548                sampleLen = strlen(str);
549               
550                PtrToHand(str,&sampleHndl,sampleLen);
551
552                err=AddMediaSample(theMedia,sampleHndl,0,sampleLen, p->end_time - p->begin_time,(SampleDescriptionHandle)textDesc, 1, 0, &sampleTime);
553                if (err != noErr) {NSLog(@"error adding %d-%d",p->begin_time, p->end_time); err = GetMoviesError(); goto loopend;}
554               
555                ConvertTimeScale(&movieStartTime, movieTimeScale);
556
557                err = InsertMediaIntoTrack(theTrack, movieStartTime.value.lo, sampleTime, p->end_time - p->begin_time, fixed1);
558                if (err != noErr) {err = GetMoviesError(); goto bail;}
559
560loopend:
561                DisposeHandle(sampleHndl);
562        }
563       
564        sampleHndl = NULL;
565       
566        EndMediaEdits(theMedia);
567       
568        if (*firstSubTrack == NULL)
569                *firstSubTrack = theTrack;
570        else
571                SetTrackAlternate(*firstSubTrack, theTrack);
572       
573        SetMediaLanguage(theMedia, GetFilenameLanguage(filename));
574       
575bail:
576
577        [ssa release];
578        [pool release];
579       
580        if (err) {
581                if (theMedia)
582                        DisposeTrackMedia(theMedia);
583               
584                if (theTrack)
585                        DisposeMovieTrack(theTrack);
586        }
587       
588        if (textDesc)
589                DisposeHandle((Handle) textDesc);
590       
591        if (headerHndl) DisposeHandle((Handle)headerHndl);
592        if (sampleHndl) DisposeHandle(sampleHndl);
593        DisposeHandle((Handle)drefHndl);
594       
595        return err;
596}
Note: See TracBrowser for help on using the repository browser.