Mercurial > libavformat.hg
comparison movenc.c @ 659:6d7c0e6d929e libavformat
Sony PSP variation of MP4 patch by <tjcannell AT blueyonder DOT co DOT uk>
author | mmu_man |
---|---|
date | Thu, 27 Jan 2005 14:48:15 +0000 |
parents | 5b9575f5b6e8 |
children | ff3b403d0498 |
comparison
equal
deleted
inserted
replaced
658:0624def73c76 | 659:6d7c0e6d929e |
---|---|
28 #define globalTimescale 1000 | 28 #define globalTimescale 1000 |
29 | 29 |
30 #define MODE_MP4 0 | 30 #define MODE_MP4 0 |
31 #define MODE_MOV 1 | 31 #define MODE_MOV 1 |
32 #define MODE_3GP 2 | 32 #define MODE_3GP 2 |
33 #define MODE_PSP 3 // example working PSP command line: | |
34 // ffmpeg -i testinput.avi -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4 | |
33 | 35 |
34 typedef struct MOVIentry { | 36 typedef struct MOVIentry { |
35 unsigned int flags, pos, size; | 37 unsigned int flags, pos, size; |
36 unsigned int samplesInChunk; | 38 unsigned int samplesInChunk; |
37 char key_frame; | 39 char key_frame; |
55 int vosLen; | 57 int vosLen; |
56 uint8_t *vosData; | 58 uint8_t *vosData; |
57 MOVIentry** cluster; | 59 MOVIentry** cluster; |
58 } MOVTrack; | 60 } MOVTrack; |
59 | 61 |
60 typedef struct { | 62 typedef struct MOVContext { |
61 int mode; | 63 int mode; |
62 long time; | 64 long time; |
63 int nb_streams; | 65 int nb_streams; |
64 int mdat_written; | 66 int mdat_written; |
65 offset_t mdat_pos; | 67 offset_t mdat_pos; |
393 | 395 |
394 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic | 396 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic |
395 { | 397 { |
396 int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0; | 398 int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0; |
397 int pos = url_ftell(pb); | 399 int pos = url_ftell(pb); |
400 void *vosDataBackup=track->vosData; | |
401 int vosLenBackup=track->vosLen; | |
402 | |
403 // we should be able to have these passed in, via vosData, then we wouldn't need to attack this routine at all | |
404 static const char PSPAACData[]={0x13,0x10}; | |
405 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 }; | |
406 | |
407 | |
408 if (track->mode == MODE_PSP) // fails on psp if this is not here | |
409 { | |
410 if (track->enc->codec_id == CODEC_ID_AAC) | |
411 { | |
412 track->vosLen = 2; | |
413 track->vosData = PSPAACData; | |
414 } | |
415 | |
416 if (track->enc->codec_id == CODEC_ID_MPEG4) | |
417 { | |
418 track->vosLen = 28; | |
419 track->vosData = PSPMP4Data; | |
420 } | |
421 } | |
398 | 422 |
399 put_be32(pb, 0); // size | 423 put_be32(pb, 0); // size |
400 put_tag(pb, "esds"); | 424 put_tag(pb, "esds"); |
401 put_be32(pb, 0); // Version | 425 put_be32(pb, 0); // Version |
402 | 426 |
421 | 445 |
422 put_byte(pb, 0x0); // Buffersize DB (24 bits) | 446 put_byte(pb, 0x0); // Buffersize DB (24 bits) |
423 put_be16(pb, 0x0dd2); // Buffersize DB | 447 put_be16(pb, 0x0dd2); // Buffersize DB |
424 | 448 |
425 // TODO: find real values for these | 449 // TODO: find real values for these |
426 put_be32(pb, 0x0002e918); // maxbitrate | 450 put_be32(pb, track->enc->bit_rate); // maxbitrate |
427 put_be32(pb, 0x00017e6b); // avg bitrate | 451 put_be32(pb, track->enc->bit_rate); // avg bitrate |
428 | 452 |
429 if (track->vosLen) | 453 if (track->vosLen) |
430 { | 454 { |
431 // DecoderSpecific info descriptor | 455 // DecoderSpecific info descriptor |
432 putDescr(pb, 0x05, track->vosLen); | 456 putDescr(pb, 0x05, track->vosLen); |
433 put_buffer(pb, track->vosData, track->vosLen); | 457 put_buffer(pb, track->vosData, track->vosLen); |
434 } | 458 } |
459 | |
460 track->vosData = vosDataBackup; | |
461 track->vosLen = vosLenBackup; | |
435 | 462 |
436 // SL descriptor | 463 // SL descriptor |
437 putDescr(pb, 0x06, 1); | 464 putDescr(pb, 0x06, 1); |
438 put_byte(pb, 0x02); | 465 put_byte(pb, 0x02); |
439 return updateSize (pb, pos); | 466 return updateSize (pb, pos); |
709 put_be32(pb, 0); | 736 put_be32(pb, 0); |
710 } | 737 } |
711 return 0x5c; | 738 return 0x5c; |
712 } | 739 } |
713 | 740 |
741 // This box seems important for the psp playback ... without it the movie seems to hang | |
742 static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track) | |
743 { | |
744 int64_t maxTrackLenTemp; | |
745 put_be32(pb, 0x24); /* size */ | |
746 put_tag(pb, "edts"); | |
747 put_be32(pb, 0x1c); /* size */ | |
748 put_tag(pb, "elst"); | |
749 put_be32(pb, 0x0); | |
750 put_be32(pb, 0x1); | |
751 | |
752 maxTrackLenTemp = ((int64_t)globalTimescale*(int64_t)track->trackDuration)/(int64_t)track->timescale; | |
753 put_be32(pb, (long)maxTrackLenTemp); /* duration ... doesn't seem to effect psp */ | |
754 | |
755 put_be32(pb, 0x0); | |
756 put_be32(pb, 0x00010000); | |
757 return 0x24; | |
758 } | |
759 | |
760 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it) | |
761 static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov) | |
762 { | |
763 put_be32(pb, 0x34); /* size ... reports as 28 in mp4box! */ | |
764 put_tag(pb, "uuid"); | |
765 put_tag(pb, "USMT"); | |
766 put_be32(pb, 0x21d24fce); | |
767 put_be32(pb, 0xbb88695c); | |
768 put_be32(pb, 0xfac9c740); | |
769 put_be32(pb, 0x1c); // another size here! | |
770 put_tag(pb, "MTDT"); | |
771 put_be32(pb, 0x00010012); | |
772 put_be32(pb, 0x0a); | |
773 put_be32(pb, 0x55c40000); | |
774 put_be32(pb, 0x1); | |
775 put_be32(pb, 0x0); | |
776 return 0x34; | |
777 } | |
778 | |
714 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track) | 779 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track) |
715 { | 780 { |
716 int pos = url_ftell(pb); | 781 int pos = url_ftell(pb); |
717 put_be32(pb, 0); /* size */ | 782 put_be32(pb, 0); /* size */ |
718 put_tag(pb, "trak"); | 783 put_tag(pb, "trak"); |
719 mov_write_tkhd_tag(pb, track); | 784 mov_write_tkhd_tag(pb, track); |
785 if (track->mode == MODE_PSP) | |
786 mov_write_edts_tag(pb, track); // PSP Movies require edts box | |
720 mov_write_mdia_tag(pb, track); | 787 mov_write_mdia_tag(pb, track); |
788 if (track->mode == MODE_PSP) | |
789 mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box | |
721 return updateSize(pb, pos); | 790 return updateSize(pb, pos); |
722 } | 791 } |
723 | 792 |
724 /* TODO: Not sorted out, but not necessary either */ | 793 /* TODO: Not sorted out, but not necessary either */ |
725 static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov) | 794 static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov) |
1137 put_be32(pb, 0x14 ); /* size */ | 1206 put_be32(pb, 0x14 ); /* size */ |
1138 put_tag(pb, "ftyp"); | 1207 put_tag(pb, "ftyp"); |
1139 | 1208 |
1140 if ( mov->mode == MODE_3GP ) | 1209 if ( mov->mode == MODE_3GP ) |
1141 put_tag(pb, "3gp4"); | 1210 put_tag(pb, "3gp4"); |
1211 else if ( mov->mode == MODE_PSP ) | |
1212 put_tag(pb, "MSNV"); | |
1142 else | 1213 else |
1143 put_tag(pb, "isom"); | 1214 put_tag(pb, "isom"); |
1144 | 1215 |
1145 put_be32(pb, 0x200 ); | 1216 put_be32(pb, 0x200 ); |
1146 | 1217 |
1147 if ( mov->mode == MODE_3GP ) | 1218 if ( mov->mode == MODE_3GP ) |
1148 put_tag(pb, "3gp4"); | 1219 put_tag(pb, "3gp4"); |
1220 else if ( mov->mode == MODE_PSP ) | |
1221 put_tag(pb, "MSNV"); | |
1149 else | 1222 else |
1150 put_tag(pb, "mp41"); | 1223 put_tag(pb, "mp41"); |
1151 | 1224 |
1152 return 0x14; | 1225 return 0x14; |
1226 } | |
1227 | |
1228 int mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s) | |
1229 { | |
1230 MOVContext *mov = s->priv_data; | |
1231 int AudioRate = s->streams[1]->codec.sample_rate; | |
1232 int FrameRate = ((s->streams[0]->codec.frame_rate) * (0x10000))/ (s->streams[0]->codec.frame_rate_base); | |
1233 | |
1234 //printf("audiorate = %d\n",AudioRate); | |
1235 //printf("framerate = %d / %d = 0x%x\n",s->streams[0]->codec.frame_rate,s->streams[0]->codec.frame_rate_base,FrameRate); | |
1236 | |
1237 put_be32(pb, 0x94 ); /* size */ | |
1238 put_tag(pb, "uuid"); | |
1239 put_tag(pb, "PROF"); | |
1240 | |
1241 put_be32(pb, 0x21d24fce ); /* 96 bit UUID */ | |
1242 put_be32(pb, 0xbb88695c ); | |
1243 put_be32(pb, 0xfac9c740 ); | |
1244 | |
1245 put_be32(pb, 0x0 ); /* ? */ | |
1246 put_be32(pb, 0x3 ); /* 3 sections ? */ | |
1247 | |
1248 put_be32(pb, 0x14 ); /* size */ | |
1249 put_tag(pb, "FPRF"); | |
1250 put_be32(pb, 0x0 ); /* ? */ | |
1251 put_be32(pb, 0x0 ); /* ? */ | |
1252 put_be32(pb, 0x0 ); /* ? */ | |
1253 | |
1254 put_be32(pb, 0x2c ); /* size */ | |
1255 put_tag(pb, "APRF"); /* audio */ | |
1256 put_be32(pb, 0x0 ); | |
1257 put_be32(pb, 0x2 ); | |
1258 put_tag(pb, "mp4a"); | |
1259 put_be32(pb, 0x20f ); | |
1260 put_be32(pb, 0x0 ); | |
1261 put_be32(pb, 0x40 ); | |
1262 put_be32(pb, 0x40 ); | |
1263 put_be32(pb, AudioRate ); //24000 ... audio rate? | |
1264 put_be32(pb, 0x2 ); | |
1265 | |
1266 put_be32(pb, 0x34 ); /* size */ | |
1267 put_tag(pb, "VPRF"); /* video */ | |
1268 put_be32(pb, 0x0 ); | |
1269 put_be32(pb, 0x1 ); | |
1270 put_tag(pb, "mp4v"); | |
1271 put_be32(pb, 0x103 ); | |
1272 put_be32(pb, 0x0 ); | |
1273 put_be32(pb, 0xc0 ); | |
1274 put_be32(pb, 0xc0 ); | |
1275 put_be32(pb, FrameRate); // was 0xefc29 | |
1276 put_be32(pb, FrameRate ); // was 0xefc29 | |
1277 put_be16(pb, s->streams[0]->codec.width); | |
1278 put_be16(pb, s->streams[0]->codec.height); | |
1279 put_be32(pb, 0x010001 ); | |
1280 | |
1281 return 0x94; | |
1153 } | 1282 } |
1154 | 1283 |
1155 static int mov_write_header(AVFormatContext *s) | 1284 static int mov_write_header(AVFormatContext *s) |
1156 { | 1285 { |
1157 ByteIOContext *pb = &s->pb; | 1286 ByteIOContext *pb = &s->pb; |
1182 mov->mode = MODE_MP4; | 1311 mov->mode = MODE_MP4; |
1183 | 1312 |
1184 if (s->oformat != NULL) { | 1313 if (s->oformat != NULL) { |
1185 if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP; | 1314 if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP; |
1186 else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV; | 1315 else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV; |
1187 | 1316 else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP; |
1188 if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 ) | 1317 |
1318 if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 || mov->mode == MODE_PSP ) | |
1189 mov_write_ftyp_tag(pb,s); | 1319 mov_write_ftyp_tag(pb,s); |
1320 if ( mov->mode == MODE_PSP ) | |
1321 mov_write_uuidprof_tag(pb,s); | |
1190 } | 1322 } |
1191 | 1323 |
1192 for (i=0; i<MAX_STREAMS; i++) { | 1324 for (i=0; i<MAX_STREAMS; i++) { |
1193 mov->tracks[i].mode = mov->mode; | 1325 mov->tracks[i].mode = mov->mode; |
1194 } | 1326 } |
1358 mov_write_header, | 1490 mov_write_header, |
1359 mov_write_packet, | 1491 mov_write_packet, |
1360 mov_write_trailer, | 1492 mov_write_trailer, |
1361 }; | 1493 }; |
1362 | 1494 |
1495 static AVOutputFormat psp_oformat = { | |
1496 "psp", | |
1497 "psp mp4 format", | |
1498 NULL, | |
1499 "mp4,psp", | |
1500 sizeof(MOVContext), | |
1501 CODEC_ID_AAC, | |
1502 CODEC_ID_MPEG4, | |
1503 mov_write_header, | |
1504 mov_write_packet, | |
1505 mov_write_trailer, | |
1506 }; | |
1507 | |
1363 int movenc_init(void) | 1508 int movenc_init(void) |
1364 { | 1509 { |
1365 av_register_output_format(&mov_oformat); | 1510 av_register_output_format(&mov_oformat); |
1366 av_register_output_format(&_3gp_oformat); | 1511 av_register_output_format(&_3gp_oformat); |
1367 av_register_output_format(&mp4_oformat); | 1512 av_register_output_format(&mp4_oformat); |
1513 av_register_output_format(&psp_oformat); | |
1368 return 0; | 1514 return 0; |
1369 } | 1515 } |