Commit dcfdb046 authored by Benjamin Larsson's avatar Benjamin Larsson

Fix for title field in PSP compatible mp4 files. Patch by

Olivier, oandrieu <at> gmail.com.

Originally committed as revision 4889 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 29f7ae79
...@@ -433,28 +433,6 @@ static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic ...@@ -433,28 +433,6 @@ static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
{ {
int decoderSpecificInfoLen; int decoderSpecificInfoLen;
offset_t pos = url_ftell(pb); 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; decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
...@@ -497,8 +475,6 @@ static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic ...@@ -497,8 +475,6 @@ static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
put_buffer(pb, track->vosData, track->vosLen); put_buffer(pb, track->vosData, track->vosLen);
} }
track->vosData = vosDataBackup;
track->vosLen = vosLenBackup;
// SL descriptor // SL descriptor
putDescr(pb, 0x06, 1); putDescr(pb, 0x06, 1);
...@@ -1182,6 +1158,68 @@ static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov, ...@@ -1182,6 +1158,68 @@ static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
return updateSize(pb, pos); 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, static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
AVFormatContext *s) AVFormatContext *s)
{ {
...@@ -1224,6 +1262,9 @@ static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov, ...@@ -1224,6 +1262,9 @@ static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
} }
} }
if (mov->mode == MODE_PSP)
mov_write_uuidusmt_tag(pb, s);
else
mov_write_udta_tag(pb, mov, s); mov_write_udta_tag(pb, mov, s);
return updateSize(pb, pos); return updateSize(pb, pos);
...@@ -1241,7 +1282,7 @@ int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov) ...@@ -1241,7 +1282,7 @@ int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
} }
/* TODO: This needs to be more general */ /* 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; MOVContext *mov = s->priv_data;
...@@ -1267,17 +1308,14 @@ int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s) ...@@ -1267,17 +1308,14 @@ int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
put_tag(pb, "MSNV"); put_tag(pb, "MSNV");
else else
put_tag(pb, "mp41"); put_tag(pb, "mp41");
return 0x14;
} }
static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s) static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
{ {
int AudioRate = s->streams[1]->codec->sample_rate; AVCodecContext *VideoCodec = s->streams[0]->codec;
int FrameRate = ((s->streams[0]->codec->time_base.den) * (0x10000))/ (s->streams[0]->codec->time_base.num); AVCodecContext *AudioCodec = s->streams[1]->codec;
int AudioRate = AudioCodec->sample_rate;
//printf("audiorate = %d\n",AudioRate); int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
//printf("framerate = %d / %d = 0x%x\n",s->streams[0]->codec->time_base.den,s->streams[0]->codec->time_base.num,FrameRate);
put_be32(pb, 0x94 ); /* size */ put_be32(pb, 0x94 ); /* size */
put_tag(pb, "uuid"); put_tag(pb, "uuid");
...@@ -1299,29 +1337,29 @@ static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s) ...@@ -1299,29 +1337,29 @@ static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
put_be32(pb, 0x2c ); /* size */ put_be32(pb, 0x2c ); /* size */
put_tag(pb, "APRF"); /* audio */ put_tag(pb, "APRF"); /* audio */
put_be32(pb, 0x0 ); put_be32(pb, 0x0 );
put_be32(pb, 0x2 ); put_be32(pb, 0x2 ); /* TrackID */
put_tag(pb, "mp4a"); put_tag(pb, "mp4a");
put_be32(pb, 0x20f ); put_be32(pb, 0x20f );
put_be32(pb, 0x0 ); put_be32(pb, 0x0 );
put_be32(pb, 0x40 ); put_be32(pb, AudioCodec->bit_rate / 1000);
put_be32(pb, 0x40 ); put_be32(pb, AudioCodec->bit_rate / 1000);
put_be32(pb, AudioRate ); //24000 ... audio rate? put_be32(pb, AudioRate );
put_be32(pb, 0x2 ); put_be32(pb, AudioCodec->channels );
put_be32(pb, 0x34 ); /* size */ put_be32(pb, 0x34 ); /* size */
put_tag(pb, "VPRF"); /* video */ put_tag(pb, "VPRF"); /* video */
put_be32(pb, 0x0 ); put_be32(pb, 0x0 );
put_be32(pb, 0x1 ); put_be32(pb, 0x1 ); /* TrackID */
put_tag(pb, "mp4v"); put_tag(pb, "mp4v");
put_be32(pb, 0x103 ); put_be32(pb, 0x103 );
put_be32(pb, 0x0 ); put_be32(pb, 0x0 );
put_be32(pb, 0xc0 ); put_be32(pb, VideoCodec->bit_rate / 1000);
put_be32(pb, 0xc0 ); put_be32(pb, VideoCodec->bit_rate / 1000);
put_be32(pb, FrameRate); // was 0xefc29 put_be32(pb, FrameRate);
put_be32(pb, FrameRate ); // was 0xefc29 put_be32(pb, FrameRate);
put_be16(pb, s->streams[0]->codec->width); put_be16(pb, VideoCodec->width);
put_be16(pb, s->streams[0]->codec->height); put_be16(pb, VideoCodec->height);
put_be32(pb, 0x010001 ); put_be32(pb, 0x010001); /* ? */
} }
static int mov_write_header(AVFormatContext *s) static int mov_write_header(AVFormatContext *s)
...@@ -1567,7 +1605,7 @@ static AVOutputFormat psp_oformat = { ...@@ -1567,7 +1605,7 @@ static AVOutputFormat psp_oformat = {
mov_write_header, mov_write_header,
mov_write_packet, mov_write_packet,
mov_write_trailer, mov_write_trailer,
// .flags = AVFMT_GLOBALHEADER, .flags = AVFMT_GLOBALHEADER,
}; };
static AVOutputFormat _3g2_oformat = { static AVOutputFormat _3g2_oformat = {
......
...@@ -75,6 +75,8 @@ stddev: 12.32 PSNR:26.31 bytes:7602176 ...@@ -75,6 +75,8 @@ stddev: 12.32 PSNR:26.31 bytes:7602176
899452 ./data/a-mpeg4-Q.avi 899452 ./data/a-mpeg4-Q.avi
af59c063ed644c7dc4151a0a2debbddd *./data/out.yuv af59c063ed644c7dc4151a0a2debbddd *./data/out.yuv
stddev: 5.69 PSNR:33.00 bytes:7602176 stddev: 5.69 PSNR:33.00 bytes:7602176
cf8be7607ebef72bbe3c6c40467cb741 *./data/a-mpeg4-PSP.mp4
407373 ./data/a-mpeg4-PSP.mov
dd193b592a02864d612c64cbbf5e1258 *./data/a-error-mpeg4-adv.avi dd193b592a02864d612c64cbbf5e1258 *./data/a-error-mpeg4-adv.avi
766682 ./data/a-error-mpeg4-adv.avi 766682 ./data/a-error-mpeg4-adv.avi
e90b201e20563ec7817f5dc4276902ed *./data/out.yuv e90b201e20563ec7817f5dc4276902ed *./data/out.yuv
......
...@@ -56,6 +56,7 @@ else ...@@ -56,6 +56,7 @@ else
do_h263=y do_h263=y
do_h263p=y do_h263p=y
do_mpeg4=y do_mpeg4=y
do_mp4psp=y
do_huffyuv=y do_huffyuv=y
do_mjpeg=y do_mjpeg=y
do_ljpeg=y do_ljpeg=y
...@@ -338,6 +339,13 @@ do_ffmpeg $file -y -qscale 7 -flags +mv4+qpel -mbd 2 -bf 2 -cmp 1 -subcmp 2 -f p ...@@ -338,6 +339,13 @@ do_ffmpeg $file -y -qscale 7 -flags +mv4+qpel -mbd 2 -bf 2 -cmp 1 -subcmp 2 -f p
do_ffmpeg $raw_dst -y -i $file -f rawvideo $raw_dst do_ffmpeg $raw_dst -y -i $file -f rawvideo $raw_dst
fi fi
###################################
if [ -n "$do_mp4psp" ] ; then
# mp4 PSP style
file=${outfile}mpeg4-PSP.mp4
do_ffmpeg $file -y -b 768 -s 320x240 -f psp -ar 24000 -ab 32 -i $raw_src $file
fi
################################### ###################################
if [ -n "$do_error" ] ; then if [ -n "$do_error" ] ; then
# damaged mpeg4 # damaged mpeg4
......
...@@ -75,6 +75,8 @@ bb7f7889f0694a1c499041f3ee5e234d *./data/a-mpeg4-Q.avi ...@@ -75,6 +75,8 @@ bb7f7889f0694a1c499041f3ee5e234d *./data/a-mpeg4-Q.avi
164998 ./data/a-mpeg4-Q.avi 164998 ./data/a-mpeg4-Q.avi
b078f22c66083f0537bd3581509684d8 *./data/out.yuv b078f22c66083f0537bd3581509684d8 *./data/out.yuv
stddev: 4.01 PSNR:36.05 bytes:7602176 stddev: 4.01 PSNR:36.05 bytes:7602176
5eb32583799d9ea27d364e381f19f022 *./data/a-mpeg4-PSP.mp4
321946 ./data/a-mpeg4-PSP.mov
74b9ddde044f90c8ee25042e9faaef68 *./data/a-error-mpeg4-adv.avi 74b9ddde044f90c8ee25042e9faaef68 *./data/a-error-mpeg4-adv.avi
177212 ./data/a-error-mpeg4-adv.avi 177212 ./data/a-error-mpeg4-adv.avi
9fa0943825f364d6fb700dc75cf5d8bb *./data/out.yuv 9fa0943825f364d6fb700dc75cf5d8bb *./data/out.yuv
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment