source: branches/perian-1.1/CommonUtils.c @ 960

Revision 960, 10.0 KB checked in by astrange, 6 years ago (diff)

Change experimental QT flags and debug logging to be defaults options.
Improve logging, and make log files work in Deployment too.

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
14typedef 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
22static 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
159short 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
174short 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 */
190uint8_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 */
196uint8_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 */
202uint8_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
216static 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
230static 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
237ComponentResult 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
271int 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
289static const CFStringRef defaultFrameDroppingWhiteList[] = {
290        CFSTR("QuickTime Player"),
291        CFSTR("NicePlayer"),
292        CFSTR("Movie Time"),
293        CFSTR("Front Row"),
294        CFSTR("Finder")
295};
296
297static int findNameInList(CFStringRef loadingApp, const CFStringRef *names, int count)
298{
299        int i;
300
301        for (i = 0; i < count; i++) {
302                if (CFStringCompare(loadingApp, names[i], 0) == kCFCompareEqualTo) return 1;
303        }
304
305        return 0;
306}
307
308int IsFrameDroppingEnabled()
309{
310        static int enabled = -1;
311       
312        if (enabled == -1) {
313                ProcessSerialNumber myProcess;
314                GetCurrentProcess(&myProcess);
315                CFDictionaryRef processInformation;
316               
317        processInformation = ProcessInformationCopyDictionary(&myProcess, kProcessDictionaryIncludeAllInformationMask);
318       
319        if (!processInformation) enabled = FALSE;
320                else {
321            CFArrayRef list = CFPreferencesCopyAppValue(CFSTR("FrameDroppingWhiteList"), CFSTR("org.perian.Perian"));
322            CFStringRef path = CFDictionaryGetValue(processInformation, kCFBundleExecutableKey);
323            CFRange entireRange = CFRangeMake(0, CFStringGetLength(path)), basename;
324           
325            CFStringFindWithOptions(path, CFSTR("/"), entireRange, kCFCompareBackwards, &basename);
326           
327            basename.location += 1; //advance past "/"
328            basename.length = entireRange.length - basename.location;
329           
330            CFStringRef myProcessName = CFStringCreateWithSubstring(NULL, path, basename);
331           
332            if (list) {
333                int count = CFArrayGetCount(list);
334                CFStringRef names[count];
335               
336                CFArrayGetValues(list, CFRangeMake(0, count), (void *)names);
337                enabled = findNameInList(myProcessName, names, count);
338                CFRelease(list);
339            } else {
340                int count = sizeof(defaultFrameDroppingWhiteList)/sizeof(defaultFrameDroppingWhiteList[0]);
341                enabled = findNameInList(myProcessName, defaultFrameDroppingWhiteList, count);
342            }
343            CFRelease(myProcessName);
344            CFRelease(processInformation);
345        }
346        }
347       
348        return enabled;
349}
Note: See TracBrowser for help on using the repository browser.