root/branches/perian-1.1/CommonUtils.c

Revision 931, 10.1 kB (checked in by astrange, 2 weeks ago)

Release the right process information variable, update the changelog, and disable interlaced h264 decoding code for some small optimization.

Line 
1 /*
2  *  CommonUtils.c
3  *  Perian
4  *
5  *  Created by David Conrad on 10/13/06.
6  *  Copyright 2006 Perian Project. All rights reserved.
7  *
8  */
9
10 #include "avcodec.h"
11 #include "CommonUtils.h"
12 #import <Carbon/Carbon.h>
13
14 typedef struct LanguageTriplet {
15         char twoChar[3];
16         char threeChar[4];      // (ISO 639-2 3 char code)
17         short qtLang;
18 } LanguageTriplet;
19
20 // don't think there's a function already to do ISO 639-1/2 -> language code
21 // that SetMediaLanguage() accepts
22 static const LanguageTriplet ISO_QTLanguages[] = {
23         { "",   "und", langUnspecified },
24         { "af", "afr", langAfrikaans },
25         { "sq", "alb", langAlbanian },
26         { "sq", "sqi", langAlbanian },
27         { "am", "amh", langAmharic },
28         { "ar", "ara", langArabic },
29         { "hy", "arm", langArmenian },
30         { "hy", "hye", langArmenian },
31         { "as", "asm", langAssamese },
32         { "ay", "aym", langAymara },
33         { "az", "aze", langAzerbaijani },
34         { "eu", "baq", langBasque },
35         { "eu", "eus", langBasque },
36         { "bn", "ben", langBengali },
37         { "br", "bre", langBreton },
38         { "bg", "bul", langBulgarian },
39         { "my", "bur", langBurmese },
40         { "my", "mya", langBurmese },
41         { "ca", "cat", langCatalan },
42         { "zh", "chi", langTradChinese },
43         { "zh", "zho", langTradChinese },
44         { "cs", "cze", langCzech },
45         { "cs", "ces", langCzech },
46         { "da", "dan", langDanish },
47         { "nl", "dut", langDutch },
48         { "nl", "nld", langDutch },
49         { "dz", "dzo", langDzongkha },
50         { "en", "eng", langEnglish },
51         { "eo", "epo", langEsperanto },
52         { "et", "est", langEstonian },
53         { "fo", "fao", langFaroese },
54         { "fi", "fin", langFinnish },
55         { "fr", "fre", langFrench },
56         { "fr", "fra", langFrench },
57         { "ka", "geo", langGeorgian },
58         { "ka", "kat", langGeorgian },
59         { "de", "ger", langGerman },
60         { "de", "deu", langGerman },
61         { "gl", "glg", langGalician },
62         { "gd", "gla", langScottishGaelic },
63         { "ga", "gle", langIrishGaelic },
64         { "gv", "glv", langManxGaelic },
65         { "",   "grc", langGreekAncient },
66         { "el", "gre", langGreek },
67         { "el", "ell", langGreek },
68         { "gn", "grn", langGuarani },
69         { "gu", "guj", langGujarati },
70         { "he", "heb", langHebrew },
71         { "hi", "hin", langHindi },
72         { "hu", "hun", langHungarian },
73         { "is", "ice", langIcelandic },
74         { "is", "isl", langIcelandic },
75         { "id", "ind", langIndonesian },
76         { "it", "ita", langItalian },
77         { "jv", "jav", langJavaneseRom },
78         { "ja", "jpn", langJapanese },
79         { "kl", "kal", langGreenlandic },
80         { "kn", "kan", langKannada },
81         { "ks", "kas", langKashmiri },
82         { "kk", "kaz", langKazakh },
83         { "km", "khm", langKhmer },
84         { "rw", "kin", langKinyarwanda },
85         { "ky", "kir", langKirghiz },
86         { "ko", "kor", langKorean },
87         { "ku", "kur", langKurdish },
88         { "lo", "lao", langLao },
89         { "la", "lat", langLatin },
90         { "lv", "lav", langLatvian },
91         { "lt", "lit", langLithuanian },
92         { "mk", "mac", langMacedonian },
93         { "mk", "mkd", langMacedonian },
94         { "ml", "mal", langMalayalam },
95         { "mr", "mar", langMarathi },
96         { "ms", "may", langMalayRoman },
97         { "ms", "msa", langMalayRoman },
98         { "mg", "mlg", langMalagasy },
99         { "mt", "mlt", langMaltese },
100         { "mo", "mol", langMoldavian },
101         { "mn", "mon", langMongolian },
102         { "ne", "nep", langNepali },
103         { "nb", "nob", langNorwegian },         // Norwegian Bokmal
104         { "no", "nor", langNorwegian },
105         { "nn", "nno", langNynorsk },
106         { "ny", "nya", langNyanja },
107         { "or", "ori", langOriya },
108         { "om", "orm", langOromo },
109         { "pa", "pan", langPunjabi },
110         { "fa", "per", langPersian },
111         { "fa", "fas", langPersian },
112         { "pl", "pol", langPolish },
113         { "pt", "por", langPortuguese },
114         { "qu", "que", langQuechua },
115         { "ro", "rum", langRomanian },
116         { "ro", "ron", langRomanian },
117         { "rn", "run", langRundi },
118         { "ru", "rus", langRussian },
119         { "sa", "san", langSanskrit },
120         { "sr", "scc", langSerbian },
121         { "sr", "srp", langSerbian },
122         { "hr", "scr", langCroatian },
123         { "hr", "hrv", langCroatian },
124         { "si", "sin", langSinhalese },
125         { "",   "sit", langTibetan },           // Sino-Tibetan (Other)
126         { "sk", "slo", langSlovak },
127         { "sk", "slk", langSlovak },
128         { "sl", "slv", langSlovenian },
129         { "se", "sme", langSami },
130         { "",   "smi", langSami },                      // Sami languages (Other)
131         { "sd", "snd", langSindhi },
132         { "so", "som", langSomali },
133         { "es", "spa", langSpanish },
134         { "su", "sun", langSundaneseRom },
135         { "sw", "swa", langSwahili },
136         { "sv", "swe", langSwedish },
137         { "ta", "tam", langTamil },
138         { "tt", "tat", langTatar },
139         { "te", "tel", langTelugu },
140         { "tg", "tgk", langTajiki },
141         { "tl", "tgl", langTagalog },
142         { "th", "tha", langThai },
143         { "bo", "tib", langTibetan },
144         { "bo", "bod", langTibetan },
145         { "ti", "tir", langTigrinya },
146         { "",   "tog", langTongan },            // Tonga (Nyasa, Tonga Islands)
147         { "tr", "tur", langTurkish },
148         { "tk", "tuk", langTurkmen },
149         { "ug", "uig", langUighur },
150         { "uk", "ukr", langUkrainian },
151         { "ur", "urd", langUrdu },
152         { "uz", "uzb", langUzbek },
153         { "vi", "vie", langVietnamese },
154         { "cy", "wel", langWelsh },
155         { "cy", "cym", langWelsh },
156         { "yi", "yid", langYiddish }
157 };
158
159 short ISO639_1ToQTLangCode(const char *lang)
160 {
161         int i;
162        
163         if (strlen(lang) != 2)
164                 return langUnspecified;
165        
166         for (i = 0; i < sizeof(ISO_QTLanguages) / sizeof(LanguageTriplet); i++) {
167                 if (strcasecmp(lang, ISO_QTLanguages[i].twoChar) == 0)
168                         return ISO_QTLanguages[i].qtLang;
169         }
170        
171         return langUnspecified;
172 }
173
174 short ISO639_2ToQTLangCode(const char *lang)
175 {
176         int i;
177        
178         if (strlen(lang) != 3)
179                 return langUnspecified;
180        
181         for (i = 0; i < sizeof(ISO_QTLanguages) / sizeof(LanguageTriplet); i++) {
182                 if (strcasecmp(lang, ISO_QTLanguages[i].threeChar) == 0)
183                         return ISO_QTLanguages[i].qtLang;
184         }
185        
186         return langUnspecified;
187 }
188
189 /* write the int32_t data to target & then return a pointer which points after that data */
190 uint8_t *write_int32(uint8_t *target, int32_t data)
191 {
192         return write_data(target, (uint8_t*)&data, sizeof(data));
193 } /* write_int32() */
194
195 /* write the int16_t data to target & then return a pointer which points after that data */
196 uint8_t *write_int16(uint8_t *target, int16_t data)
197 {
198         return write_data(target, (uint8_t*)&data, sizeof(data));
199 } /* write_int16() */
200
201 /* write the data to the target adress & then return a pointer which points after the written data */
202 uint8_t *write_data(uint8_t *target, uint8_t* data, int32_t data_size)
203 {
204         if(data_size > 0)
205                 memcpy(target, data, data_size);
206         return (target + data_size);
207 } /* write_data() */
208
209
210
211 #define MP4ESDescrTag                   0x03
212 #define MP4DecConfigDescrTag            0x04
213 #define MP4DecSpecificDescrTag          0x05
214
215 // based off of mov_mp4_read_descr_len from mov.c in ffmpeg's libavformat
216 static int readDescrLen(UInt8 **buffer)
217 {
218         int len = 0;
219         int count = 4;
220         while (count--) {
221                 int c = *(*buffer)++;
222                 len = (len << 7) | (c & 0x7f);
223                 if (!(c & 0x80))
224                         break;
225         }
226         return len;
227 }
228
229 // based off of mov_mp4_read_descr from mov.c in ffmpeg's libavformat
230 static int readDescr(UInt8 **buffer, int *tag)
231 {
232         *tag = *(*buffer)++;
233         return readDescrLen(buffer);
234 }
235
236 // based off of mov_read_esds from mov.c in ffmpeg's libavformat
237 ComponentResult ReadESDSDescExt(Handle descExt, UInt8 **buffer, int *size)
238 {
239         UInt8 *esds = (UInt8 *) *descExt;
240         int tag, len;
241        
242         *size = 0;
243        
244         esds += 4;              // version + flags
245         len = readDescr(&esds, &tag);
246         esds += 2;              // ID
247         if (tag == MP4ESDescrTag)
248                 esds++;         // priority
249        
250         len = readDescr(&esds, &tag);
251         if (tag == MP4DecConfigDescrTag) {
252                 esds++;         // object type id
253                 esds++;         // stream type
254                 esds += 3;      // buffer size db
255                 esds += 4;      // max bitrate
256                 esds += 4;      // average bitrate
257                
258                 len = readDescr(&esds, &tag);
259                 if (tag == MP4DecSpecificDescrTag) {
260                         *buffer = calloc(1, len + FF_INPUT_BUFFER_PADDING_SIZE);
261                         if (*buffer) {
262                                 memcpy(*buffer, esds, len);
263                                 *size = len;
264                         }
265                 }
266         }
267        
268         return noErr;
269 }
270
271 int isImageDescriptionExtensionPresent(ImageDescriptionHandle desc, long type)
272 {
273         ImageDescriptionPtr d = *desc;
274         int offset = sizeof(ImageDescription);
275         uint8_t *p = (uint8_t *)d;
276        
277         //read next description, need 8 bytes for size and type
278         while(offset < d->idSize - 8)
279         {
280                 long len = *(p+offset) << 24 | *(p+offset+1) << 16 | *(p+offset+2) << 8 | *(p+offset+3);
281                 long rtype = *(p+offset + 4) << 24 | *(p+offset+5) << 16 | *(p+offset+6) << 8 | *(p+offset+7);
282                 if(rtype == type && offset + len <= d->idSize)
283                         return 1;
284                 offset += len;
285         }
286         return 0;
287 }
288
289 static const CFStringRef defaultFrameDroppingWhiteList[] = {
290         CFSTR("QuickTime Player"),
291         CFSTR("NicePlayer"),
292         CFSTR("Movie Time")
293 };
294
295 static int findNameInList(CFStringRef loadingApp, const CFStringRef *names, int count)
296 {
297         int i;
298
299         for (i = 0; i < count; i++) {
300                 if (CFStringCompare(loadingApp, names[i], 0) == kCFCompareEqualTo) return 1;
301         }
302
303         return 0;
304 }
305
306 int IsFrameDroppingEnabled()
307 {
308         static int enabled = -1;
309        
310         if (enabled == -1) {
311                 ProcessSerialNumber myProcess;
312                 GetCurrentProcess(&myProcess);
313                 CFDictionaryRef processInformation;
314                
315         processInformation = ProcessInformationCopyDictionary(&myProcess, kProcessDictionaryIncludeAllInformationMask);
316        
317         if (!processInformation) enabled = FALSE;
318                 else {
319             CFArrayRef list = CFPreferencesCopyAppValue(CFSTR("FrameDroppingWhiteList"), CFSTR("org.perian.Perian"));
320             CFStringRef path = CFDictionaryGetValue(processInformation, kCFBundleExecutableKey);
321             CFRange entireRange = CFRangeMake(0, CFStringGetLength(path)), basename;
322            
323             CFStringFindWithOptions(path, CFSTR("/"), entireRange, kCFCompareBackwards, &basename);
324            
325             basename.location += 1; //advance past "/"
326             basename.length = entireRange.length - basename.location;
327            
328             CFStringRef myProcessName = CFStringCreateWithSubstring(NULL, path, basename);
329            
330             if (list) {
331                 int count = CFArrayGetCount(list);
332                 CFStringRef names[count];
333                
334                 CFArrayGetValues(list, CFRangeMake(0, count), (void *)names);
335                 enabled = findNameInList(myProcessName, names, count);
336                 CFRelease(list);
337             } else {
338                 int count = sizeof(defaultFrameDroppingWhiteList)/sizeof(defaultFrameDroppingWhiteList[0]);
339                 enabled = findNameInList(myProcessName, defaultFrameDroppingWhiteList, count);
340             }
341             //Codecprintf(NULL, "Frame Dropping enabled is %d for %s\n", enabled, CFStringGetCStringPtr(myProcessName, kCFStringEncodingMacRoman));
342             CFRelease(myProcessName);
343             CFRelease(processInformation);
344         }
345         }
346        
347         return enabled;
348 }
Note: See TracBrowser for help on using the browser.