changeset 911:343ddd5b793c libavformat

Fix for title field in PSP compatible mp4 files. Patch by Olivier, oandrieu <at> gmail.com.
author banan
date Tue, 24 Jan 2006 08:03:42 +0000
parents d92e6d673ef5
children 844bc9093aa3
files movenc.c
diffstat 1 files changed, 84 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/movenc.c	Mon Jan 23 14:28:50 2006 +0000
+++ b/movenc.c	Tue Jan 24 08:03:42 2006 +0000
@@ -433,28 +433,6 @@
 {
     int decoderSpecificInfoLen;
     offset_t pos = url_ftell(pb);
-    void *vosDataBackup=track->vosData;
-    int vosLenBackup=track->vosLen;
-
-    // we should be able to have these passed in, via vosData, then we wouldn't need to attack this routine at all
-    static const char PSPAACData[]={0x13,0x10};
-    static const char PSPMP4Data[]={0x00,0x00,0x01,0xB0,0x03,0x00,0x00,0x01,0xB5,0x09,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x20,0x00,0x84,0x5D,0x4C,0x28,0x50,0x20,0xF0,0xA3,0x1F };
-
-
-    if (track->mode == MODE_PSP)  // fails on psp if this is not here
-    {
-        if (track->enc->codec_id == CODEC_ID_AAC)
-        {
-            track->vosLen = 2;
-            track->vosData = (uint8_t *) PSPAACData;
-        }
-
-        if (track->enc->codec_id == CODEC_ID_MPEG4)
-        {
-            track->vosLen = 28;
-            track->vosData = (uint8_t *) PSPMP4Data;
-        }
-    }
 
     decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
 
@@ -497,8 +475,6 @@
         put_buffer(pb, track->vosData, track->vosLen);
     }
 
-    track->vosData = vosDataBackup;
-    track->vosLen = vosLenBackup;
 
     // SL descriptor
     putDescr(pb, 0x06, 1);
@@ -1182,6 +1158,68 @@
     return updateSize(pb, pos);
 }
 
+
+static size_t ascii_to_wc (ByteIOContext *pb, char *b, size_t n)
+{
+    size_t i;
+    unsigned char c;
+    for (i = 0; i < n - 1; i++) {
+        c = b[i];
+        if (! (0x20 <= c && c <= 0x7f ))
+            c = 0x3f;  /* '?' */
+        put_be16(pb, c);
+    }
+    put_be16(pb, 0x00);
+    return 2*n;
+}
+
+static uint16_t language_code (char *str)
+{
+    return ((((str[0]-'a') & 0x1F)<<10) + (((str[1]-'a') & 0x1F)<<5) + ((str[2]-'a') & 0x1F));
+}
+
+static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
+{
+    size_t len, size;
+    offset_t pos, curpos;
+
+    size = 0;
+    if (s->title[0]) {
+        pos = url_ftell(pb);
+        put_be32(pb, 0); /* size placeholder*/
+        put_tag(pb, "uuid");
+        put_tag(pb, "USMT");
+        put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
+        put_be32(pb, 0xbb88695c );
+        put_be32(pb, 0xfac9c740 );
+        size += 24;
+
+        put_be32(pb, 0); /* size placeholder*/
+        put_tag(pb, "MTDT");
+        put_be16(pb, 1);
+        size += 10;
+
+        // Title
+        len = strlen(s->title)+1;
+        put_be16(pb, len*2+10);             /* size */
+        put_be32(pb, 0x01);                 /* type */
+        put_be16(pb, language_code("und")); /* language */
+        put_be16(pb, 0x01);                 /* ? */
+        ascii_to_wc (pb, s->title, len);
+        size += len*2+10;
+
+        // size
+        curpos = url_ftell(pb);
+        url_fseek(pb, pos, SEEK_SET);
+        put_be32(pb, size);
+        url_fseek(pb, pos+24, SEEK_SET);
+        put_be32(pb, size-24);
+        url_fseek(pb, curpos, SEEK_SET);
+    }
+
+    return size;
+}
+
 static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
                               AVFormatContext *s)
 {
@@ -1224,6 +1262,9 @@
         }
     }
 
+    if (mov->mode == MODE_PSP)
+        mov_write_uuidusmt_tag(pb, s);
+    else
     mov_write_udta_tag(pb, mov, s);
 
     return updateSize(pb, pos);
@@ -1241,7 +1282,7 @@
 }
 
 /* TODO: This needs to be more general */
-int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
+static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
 {
     MOVContext *mov = s->priv_data;
 
@@ -1267,17 +1308,14 @@
         put_tag(pb, "MSNV");
     else
         put_tag(pb, "mp41");
-
-    return 0x14;
 }
 
 static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
 {
-    int AudioRate = s->streams[1]->codec->sample_rate;
-    int FrameRate = ((s->streams[0]->codec->time_base.den) * (0x10000))/ (s->streams[0]->codec->time_base.num);
-
-    //printf("audiorate = %d\n",AudioRate);
-    //printf("framerate = %d / %d = 0x%x\n",s->streams[0]->codec->time_base.den,s->streams[0]->codec->time_base.num,FrameRate);
+    AVCodecContext *VideoCodec = s->streams[0]->codec;
+    AVCodecContext *AudioCodec = s->streams[1]->codec;
+    int AudioRate = AudioCodec->sample_rate;
+    int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
 
     put_be32(pb, 0x94 ); /* size */
     put_tag(pb, "uuid");
@@ -1299,29 +1337,29 @@
     put_be32(pb, 0x2c );  /* size */
     put_tag(pb, "APRF");   /* audio */
     put_be32(pb, 0x0 );
-    put_be32(pb, 0x2 );
+    put_be32(pb, 0x2 );   /* TrackID */
     put_tag(pb, "mp4a");
     put_be32(pb, 0x20f );
     put_be32(pb, 0x0 );
-    put_be32(pb, 0x40 );
-    put_be32(pb, 0x40 );
-    put_be32(pb, AudioRate ); //24000   ... audio rate?
-    put_be32(pb, 0x2 );
+    put_be32(pb, AudioCodec->bit_rate / 1000);
+    put_be32(pb, AudioCodec->bit_rate / 1000);
+    put_be32(pb, AudioRate );
+    put_be32(pb, AudioCodec->channels );
 
     put_be32(pb, 0x34 );  /* size */
     put_tag(pb, "VPRF");   /* video */
     put_be32(pb, 0x0 );
-    put_be32(pb, 0x1 );
+    put_be32(pb, 0x1 );    /* TrackID */
     put_tag(pb, "mp4v");
     put_be32(pb, 0x103 );
     put_be32(pb, 0x0 );
-    put_be32(pb, 0xc0 );
-    put_be32(pb, 0xc0 );
-    put_be32(pb, FrameRate);  // was 0xefc29
-    put_be32(pb, FrameRate );  // was 0xefc29
-    put_be16(pb, s->streams[0]->codec->width);
-    put_be16(pb, s->streams[0]->codec->height);
-    put_be32(pb, 0x010001 );
+    put_be32(pb, VideoCodec->bit_rate / 1000);
+    put_be32(pb, VideoCodec->bit_rate / 1000);
+    put_be32(pb, FrameRate);
+    put_be32(pb, FrameRate);
+    put_be16(pb, VideoCodec->width);
+    put_be16(pb, VideoCodec->height);
+    put_be32(pb, 0x010001); /* ? */
 }
 
 static int mov_write_header(AVFormatContext *s)
@@ -1567,7 +1605,7 @@
     mov_write_header,
     mov_write_packet,
     mov_write_trailer,
-//    .flags = AVFMT_GLOBALHEADER,
+    .flags = AVFMT_GLOBALHEADER,
 };
 
 static AVOutputFormat _3g2_oformat = {