finally found what those >138 codes were... crappy compressed 5bit ascii. this gets...
authorFrançois Revol <revol@free.fr>
Fri, 30 Dec 2005 20:34:08 +0000 (20:34 +0000)
committerFrançois Revol <revol@free.fr>
Fri, 30 Dec 2005 20:34:08 +0000 (20:34 +0000)
Originally committed as revision 4792 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/mov.c
libavformat/movenc.c

index c5ddec3e20ebf1d13e92386fa08d2e04ea317ef5..8bf364f6426db79fba7e1d7c62c86fc911f9b917 100644 (file)
@@ -151,6 +151,8 @@ static const CodecTag mov_audio_tags[] = {
 
 /* map numeric codes from mdhd atom to ISO 639 */
 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
+/* http://developer.apple.com/documentation/mac/Text/Text-368.html */
+/* deprecated by putting the code as 3*5bit ascii */
 static const char *mov_mdhd_language_map[] = { 
 /* 0-9 */
 "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor", 
@@ -353,24 +355,54 @@ void print_atom(const char *str, MOV_atom_t atom)
 #define print_atom(a,b)
 #endif
 
-const char *ff_mov_lang_to_iso639(int code)
+static int ff_mov_lang_to_iso639(int code, char *to)
 {
+    int i;
+    /* is it the mangled iso code? */
+    /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
+    if (code > 138) {
+        for (i = 2; i >= 0; i--) {
+            to[i] = 0x60 + (code & 0x1f);
+            code >>= 5;
+        }
+        return 1;
+    }
+    /* old fashion apple lang code */
     if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
-        return NULL;
+        return 0;
     if (!mov_mdhd_language_map[code])
-        return NULL;
-    return mov_mdhd_language_map[code];
+        return 0;
+    strncpy(to, mov_mdhd_language_map[code], 4);
+    return 1;
 }
 
-extern int ff_mov_iso639_to_lang(const char *lang); /* for movenc.c */
-int ff_mov_iso639_to_lang(const char *lang)
+extern int ff_mov_iso639_to_lang(const char *lang, int mp4); /* for movenc.c */
+int ff_mov_iso639_to_lang(const char *lang, int mp4)
 {
-    int i;
-    for (i = 0; i < (sizeof(mov_mdhd_language_map)/sizeof(char *)); i++) {
+    int i, code = 0;
+    
+    /* old way, only for QT? */
+    for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
         if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
             return i;
     }
-    return -1;
+    /* XXX:can we do that in mov too? */
+    if (!mp4)
+        return 0;
+    /* handle undefined as such */
+    if (lang[0] == '\0')
+        lang = "und";
+    /* 5bit ascii */
+    for (i = 0; i < 3; i++) {
+        unsigned char c = (unsigned char)lang[i];
+        if (c < 0x60)
+            return 0;
+        if (c > 0x60 + 0x1f)
+            return 0;
+        code <<= 5;
+        code |= (c - 0x60);
+    }
+    return code;
 }
 
 static int mov_read_leaf(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
@@ -675,7 +707,6 @@ static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
 {
     int version;
     int lang;
-    const char *iso639;
     print_atom("mdhd", atom);
 
     version = get_byte(pb); /* version */
@@ -697,9 +728,7 @@ static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
     c->fc->streams[c->fc->nb_streams-1]->duration = (version==1)?get_be64(pb):get_be32(pb); /* duration */
 
     lang = get_be16(pb); /* language */
-    iso639 = ff_mov_lang_to_iso639(lang);
-    if (iso639)
-        strncpy(c->fc->streams[c->fc->nb_streams-1]->language, iso639, 4);
+    ff_mov_lang_to_iso639(lang, c->fc->streams[c->fc->nb_streams-1]->language);
     get_be16(pb); /* quality */
 
     return 0;
index 1c721d7200333675d16fc16ad0073b54b8345e54..a340644b7927c54ca165feffe3759a27c70a7b41 100644 (file)
@@ -52,6 +52,7 @@ typedef struct MOVIndex {
     long        sampleCount;
     long        sampleDuration;
     int         hasKeyframes;
+    int         language;
     int         trackID;
     AVCodecContext *enc;
 
@@ -72,6 +73,9 @@ typedef struct MOVContext {
 
 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
 
+/* output language code from iso639 language name */
+extern int ff_mov_iso639_to_lang(const char *lang, int mp4);
+
 const CodecTag ff_mov_obj_type[] = {
     { CODEC_ID_MPEG4     ,  32 },
     { CODEC_ID_AAC       ,  64 },
@@ -701,7 +705,7 @@ static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
     put_be32(pb, track->time); /* modification time */
     put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
     put_be32(pb, track->trackDuration); /* duration */
-    put_be16(pb, 0); /* language, 0 = english */
+    put_be16(pb, track->language); /* language */
     put_be16(pb, 0); /* reserved (quality) */
     return 32;
 }
@@ -1331,6 +1335,8 @@ static int mov_write_header(AVFormatContext *s)
                     av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
             }
         }
+        /* don't know yet if mp4 or not */
+        mov->tracks[i].language = ff_mov_iso639_to_lang(s->streams[i]->language, 1);
     }
 
     /* Default mode == MP4 */