Mercurial > libavformat.hg
comparison movenc.c @ 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 | 4e7a66723f1d |
comparison
equal
deleted
inserted
replaced
910:d92e6d673ef5 | 911:343ddd5b793c |
---|---|
431 | 431 |
432 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic | 432 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic |
433 { | 433 { |
434 int decoderSpecificInfoLen; | 434 int decoderSpecificInfoLen; |
435 offset_t pos = url_ftell(pb); | 435 offset_t pos = url_ftell(pb); |
436 void *vosDataBackup=track->vosData; | |
437 int vosLenBackup=track->vosLen; | |
438 | |
439 // we should be able to have these passed in, via vosData, then we wouldn't need to attack this routine at all | |
440 static const char PSPAACData[]={0x13,0x10}; | |
441 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 }; | |
442 | |
443 | |
444 if (track->mode == MODE_PSP) // fails on psp if this is not here | |
445 { | |
446 if (track->enc->codec_id == CODEC_ID_AAC) | |
447 { | |
448 track->vosLen = 2; | |
449 track->vosData = (uint8_t *) PSPAACData; | |
450 } | |
451 | |
452 if (track->enc->codec_id == CODEC_ID_MPEG4) | |
453 { | |
454 track->vosLen = 28; | |
455 track->vosData = (uint8_t *) PSPMP4Data; | |
456 } | |
457 } | |
458 | 436 |
459 decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0; | 437 decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0; |
460 | 438 |
461 put_be32(pb, 0); // size | 439 put_be32(pb, 0); // size |
462 put_tag(pb, "esds"); | 440 put_tag(pb, "esds"); |
495 // DecoderSpecific info descriptor | 473 // DecoderSpecific info descriptor |
496 putDescr(pb, 0x05, track->vosLen); | 474 putDescr(pb, 0x05, track->vosLen); |
497 put_buffer(pb, track->vosData, track->vosLen); | 475 put_buffer(pb, track->vosData, track->vosLen); |
498 } | 476 } |
499 | 477 |
500 track->vosData = vosDataBackup; | |
501 track->vosLen = vosLenBackup; | |
502 | 478 |
503 // SL descriptor | 479 // SL descriptor |
504 putDescr(pb, 0x06, 1); | 480 putDescr(pb, 0x06, 1); |
505 put_byte(pb, 0x02); | 481 put_byte(pb, 0x02); |
506 return updateSize (pb, pos); | 482 return updateSize (pb, pos); |
1180 } | 1156 } |
1181 | 1157 |
1182 return updateSize(pb, pos); | 1158 return updateSize(pb, pos); |
1183 } | 1159 } |
1184 | 1160 |
1161 | |
1162 static size_t ascii_to_wc (ByteIOContext *pb, char *b, size_t n) | |
1163 { | |
1164 size_t i; | |
1165 unsigned char c; | |
1166 for (i = 0; i < n - 1; i++) { | |
1167 c = b[i]; | |
1168 if (! (0x20 <= c && c <= 0x7f )) | |
1169 c = 0x3f; /* '?' */ | |
1170 put_be16(pb, c); | |
1171 } | |
1172 put_be16(pb, 0x00); | |
1173 return 2*n; | |
1174 } | |
1175 | |
1176 static uint16_t language_code (char *str) | |
1177 { | |
1178 return ((((str[0]-'a') & 0x1F)<<10) + (((str[1]-'a') & 0x1F)<<5) + ((str[2]-'a') & 0x1F)); | |
1179 } | |
1180 | |
1181 static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s) | |
1182 { | |
1183 size_t len, size; | |
1184 offset_t pos, curpos; | |
1185 | |
1186 size = 0; | |
1187 if (s->title[0]) { | |
1188 pos = url_ftell(pb); | |
1189 put_be32(pb, 0); /* size placeholder*/ | |
1190 put_tag(pb, "uuid"); | |
1191 put_tag(pb, "USMT"); | |
1192 put_be32(pb, 0x21d24fce ); /* 96 bit UUID */ | |
1193 put_be32(pb, 0xbb88695c ); | |
1194 put_be32(pb, 0xfac9c740 ); | |
1195 size += 24; | |
1196 | |
1197 put_be32(pb, 0); /* size placeholder*/ | |
1198 put_tag(pb, "MTDT"); | |
1199 put_be16(pb, 1); | |
1200 size += 10; | |
1201 | |
1202 // Title | |
1203 len = strlen(s->title)+1; | |
1204 put_be16(pb, len*2+10); /* size */ | |
1205 put_be32(pb, 0x01); /* type */ | |
1206 put_be16(pb, language_code("und")); /* language */ | |
1207 put_be16(pb, 0x01); /* ? */ | |
1208 ascii_to_wc (pb, s->title, len); | |
1209 size += len*2+10; | |
1210 | |
1211 // size | |
1212 curpos = url_ftell(pb); | |
1213 url_fseek(pb, pos, SEEK_SET); | |
1214 put_be32(pb, size); | |
1215 url_fseek(pb, pos+24, SEEK_SET); | |
1216 put_be32(pb, size-24); | |
1217 url_fseek(pb, curpos, SEEK_SET); | |
1218 } | |
1219 | |
1220 return size; | |
1221 } | |
1222 | |
1185 static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov, | 1223 static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov, |
1186 AVFormatContext *s) | 1224 AVFormatContext *s) |
1187 { | 1225 { |
1188 int i; | 1226 int i; |
1189 offset_t pos = url_ftell(pb); | 1227 offset_t pos = url_ftell(pb); |
1222 if(mov->tracks[i].entry > 0) { | 1260 if(mov->tracks[i].entry > 0) { |
1223 mov_write_trak_tag(pb, &(mov->tracks[i])); | 1261 mov_write_trak_tag(pb, &(mov->tracks[i])); |
1224 } | 1262 } |
1225 } | 1263 } |
1226 | 1264 |
1265 if (mov->mode == MODE_PSP) | |
1266 mov_write_uuidusmt_tag(pb, s); | |
1267 else | |
1227 mov_write_udta_tag(pb, mov, s); | 1268 mov_write_udta_tag(pb, mov, s); |
1228 | 1269 |
1229 return updateSize(pb, pos); | 1270 return updateSize(pb, pos); |
1230 } | 1271 } |
1231 | 1272 |
1239 put_tag(pb, "mdat"); | 1280 put_tag(pb, "mdat"); |
1240 return 0; | 1281 return 0; |
1241 } | 1282 } |
1242 | 1283 |
1243 /* TODO: This needs to be more general */ | 1284 /* TODO: This needs to be more general */ |
1244 int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s) | 1285 static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s) |
1245 { | 1286 { |
1246 MOVContext *mov = s->priv_data; | 1287 MOVContext *mov = s->priv_data; |
1247 | 1288 |
1248 put_be32(pb, 0x14 ); /* size */ | 1289 put_be32(pb, 0x14 ); /* size */ |
1249 put_tag(pb, "ftyp"); | 1290 put_tag(pb, "ftyp"); |
1265 put_tag(pb, "3g2a"); | 1306 put_tag(pb, "3g2a"); |
1266 else if ( mov->mode == MODE_PSP ) | 1307 else if ( mov->mode == MODE_PSP ) |
1267 put_tag(pb, "MSNV"); | 1308 put_tag(pb, "MSNV"); |
1268 else | 1309 else |
1269 put_tag(pb, "mp41"); | 1310 put_tag(pb, "mp41"); |
1270 | |
1271 return 0x14; | |
1272 } | 1311 } |
1273 | 1312 |
1274 static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s) | 1313 static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s) |
1275 { | 1314 { |
1276 int AudioRate = s->streams[1]->codec->sample_rate; | 1315 AVCodecContext *VideoCodec = s->streams[0]->codec; |
1277 int FrameRate = ((s->streams[0]->codec->time_base.den) * (0x10000))/ (s->streams[0]->codec->time_base.num); | 1316 AVCodecContext *AudioCodec = s->streams[1]->codec; |
1278 | 1317 int AudioRate = AudioCodec->sample_rate; |
1279 //printf("audiorate = %d\n",AudioRate); | 1318 int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num); |
1280 //printf("framerate = %d / %d = 0x%x\n",s->streams[0]->codec->time_base.den,s->streams[0]->codec->time_base.num,FrameRate); | |
1281 | 1319 |
1282 put_be32(pb, 0x94 ); /* size */ | 1320 put_be32(pb, 0x94 ); /* size */ |
1283 put_tag(pb, "uuid"); | 1321 put_tag(pb, "uuid"); |
1284 put_tag(pb, "PROF"); | 1322 put_tag(pb, "PROF"); |
1285 | 1323 |
1297 put_be32(pb, 0x0 ); /* ? */ | 1335 put_be32(pb, 0x0 ); /* ? */ |
1298 | 1336 |
1299 put_be32(pb, 0x2c ); /* size */ | 1337 put_be32(pb, 0x2c ); /* size */ |
1300 put_tag(pb, "APRF"); /* audio */ | 1338 put_tag(pb, "APRF"); /* audio */ |
1301 put_be32(pb, 0x0 ); | 1339 put_be32(pb, 0x0 ); |
1302 put_be32(pb, 0x2 ); | 1340 put_be32(pb, 0x2 ); /* TrackID */ |
1303 put_tag(pb, "mp4a"); | 1341 put_tag(pb, "mp4a"); |
1304 put_be32(pb, 0x20f ); | 1342 put_be32(pb, 0x20f ); |
1305 put_be32(pb, 0x0 ); | 1343 put_be32(pb, 0x0 ); |
1306 put_be32(pb, 0x40 ); | 1344 put_be32(pb, AudioCodec->bit_rate / 1000); |
1307 put_be32(pb, 0x40 ); | 1345 put_be32(pb, AudioCodec->bit_rate / 1000); |
1308 put_be32(pb, AudioRate ); //24000 ... audio rate? | 1346 put_be32(pb, AudioRate ); |
1309 put_be32(pb, 0x2 ); | 1347 put_be32(pb, AudioCodec->channels ); |
1310 | 1348 |
1311 put_be32(pb, 0x34 ); /* size */ | 1349 put_be32(pb, 0x34 ); /* size */ |
1312 put_tag(pb, "VPRF"); /* video */ | 1350 put_tag(pb, "VPRF"); /* video */ |
1313 put_be32(pb, 0x0 ); | 1351 put_be32(pb, 0x0 ); |
1314 put_be32(pb, 0x1 ); | 1352 put_be32(pb, 0x1 ); /* TrackID */ |
1315 put_tag(pb, "mp4v"); | 1353 put_tag(pb, "mp4v"); |
1316 put_be32(pb, 0x103 ); | 1354 put_be32(pb, 0x103 ); |
1317 put_be32(pb, 0x0 ); | 1355 put_be32(pb, 0x0 ); |
1318 put_be32(pb, 0xc0 ); | 1356 put_be32(pb, VideoCodec->bit_rate / 1000); |
1319 put_be32(pb, 0xc0 ); | 1357 put_be32(pb, VideoCodec->bit_rate / 1000); |
1320 put_be32(pb, FrameRate); // was 0xefc29 | 1358 put_be32(pb, FrameRate); |
1321 put_be32(pb, FrameRate ); // was 0xefc29 | 1359 put_be32(pb, FrameRate); |
1322 put_be16(pb, s->streams[0]->codec->width); | 1360 put_be16(pb, VideoCodec->width); |
1323 put_be16(pb, s->streams[0]->codec->height); | 1361 put_be16(pb, VideoCodec->height); |
1324 put_be32(pb, 0x010001 ); | 1362 put_be32(pb, 0x010001); /* ? */ |
1325 } | 1363 } |
1326 | 1364 |
1327 static int mov_write_header(AVFormatContext *s) | 1365 static int mov_write_header(AVFormatContext *s) |
1328 { | 1366 { |
1329 ByteIOContext *pb = &s->pb; | 1367 ByteIOContext *pb = &s->pb; |
1565 CODEC_ID_AAC, | 1603 CODEC_ID_AAC, |
1566 CODEC_ID_MPEG4, | 1604 CODEC_ID_MPEG4, |
1567 mov_write_header, | 1605 mov_write_header, |
1568 mov_write_packet, | 1606 mov_write_packet, |
1569 mov_write_trailer, | 1607 mov_write_trailer, |
1570 // .flags = AVFMT_GLOBALHEADER, | 1608 .flags = AVFMT_GLOBALHEADER, |
1571 }; | 1609 }; |
1572 | 1610 |
1573 static AVOutputFormat _3g2_oformat = { | 1611 static AVOutputFormat _3g2_oformat = { |
1574 "3g2", | 1612 "3g2", |
1575 "3gp2 format", | 1613 "3gp2 format", |