Mercurial > libavformat.hg
comparison mov.c @ 3154:01f6f3c905db libavformat
move mov_build_index before mov_read_trak to avoid useless declaration
author | bcoudurier |
---|---|
date | Thu, 20 Mar 2008 15:57:11 +0000 |
parents | 4ded3fdf5c7c |
children | e22efe21156d |
comparison
equal
deleted
inserted
replaced
3153:4ded3fdf5c7c | 3154:01f6f3c905db |
---|---|
1085 sc->ctts_data[i].duration= duration; | 1085 sc->ctts_data[i].duration= duration; |
1086 | 1086 |
1087 sc->time_rate= ff_gcd(sc->time_rate, duration); | 1087 sc->time_rate= ff_gcd(sc->time_rate, duration); |
1088 } | 1088 } |
1089 return 0; | 1089 return 0; |
1090 } | |
1091 | |
1092 static void mov_build_index(MOVContext *mov, AVStream *st); | |
1093 | |
1094 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1095 { | |
1096 AVStream *st; | |
1097 MOVStreamContext *sc; | |
1098 int ret; | |
1099 | |
1100 st = av_new_stream(c->fc, c->fc->nb_streams); | |
1101 if (!st) return -2; | |
1102 sc = av_mallocz(sizeof(MOVStreamContext)); | |
1103 if (!sc) { | |
1104 av_free(st); | |
1105 return -1; | |
1106 } | |
1107 | |
1108 st->priv_data = sc; | |
1109 st->codec->codec_type = CODEC_TYPE_DATA; | |
1110 st->start_time = 0; /* XXX: check */ | |
1111 | |
1112 if ((ret = mov_read_default(c, pb, atom)) < 0) | |
1113 return ret; | |
1114 | |
1115 /* sanity checks */ | |
1116 if(!sc->stts_count || !sc->chunk_count || !sc->sample_to_chunk_sz || | |
1117 (!sc->sample_size && !sc->sample_count)){ | |
1118 av_log(c->fc, AV_LOG_ERROR, "missing mandatory atoms, broken header\n"); | |
1119 sc->sample_count = 0; //ignore track | |
1120 return 0; | |
1121 } | |
1122 if(!sc->time_rate) | |
1123 sc->time_rate=1; | |
1124 if(!sc->time_scale) | |
1125 sc->time_scale= c->time_scale; | |
1126 av_set_pts_info(st, 64, sc->time_rate, sc->time_scale); | |
1127 | |
1128 if (st->codec->codec_type == CODEC_TYPE_AUDIO && sc->stts_count == 1) | |
1129 st->codec->frame_size = av_rescale(sc->time_rate, st->codec->sample_rate, sc->time_scale); | |
1130 | |
1131 if(st->duration != AV_NOPTS_VALUE){ | |
1132 assert(st->duration % sc->time_rate == 0); | |
1133 st->duration /= sc->time_rate; | |
1134 } | |
1135 sc->ffindex = st->index; | |
1136 mov_build_index(c, st); | |
1137 | |
1138 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { | |
1139 if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0) | |
1140 av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening external essence: %s\n", | |
1141 st->index, strerror(errno)); | |
1142 } else | |
1143 sc->pb = c->fc->pb; | |
1144 | |
1145 switch (st->codec->codec_id) { | |
1146 #ifdef CONFIG_H261_DECODER | |
1147 case CODEC_ID_H261: | |
1148 #endif | |
1149 #ifdef CONFIG_H263_DECODER | |
1150 case CODEC_ID_H263: | |
1151 #endif | |
1152 #ifdef CONFIG_MPEG4_DECODER | |
1153 case CODEC_ID_MPEG4: | |
1154 #endif | |
1155 st->codec->width= 0; /* let decoder init width/height */ | |
1156 st->codec->height= 0; | |
1157 break; | |
1158 #ifdef CONFIG_LIBFAAD | |
1159 case CODEC_ID_AAC: | |
1160 #endif | |
1161 #ifdef CONFIG_VORBIS_DECODER | |
1162 case CODEC_ID_VORBIS: | |
1163 #endif | |
1164 case CODEC_ID_MP3ON4: | |
1165 st->codec->sample_rate= 0; /* let decoder init parameters properly */ | |
1166 break; | |
1167 } | |
1168 return 0; | |
1169 } | |
1170 | |
1171 static void mov_parse_udta_string(ByteIOContext *pb, char *str, int size) | |
1172 { | |
1173 uint16_t str_size = get_be16(pb); /* string length */; | |
1174 | |
1175 get_be16(pb); /* skip language */ | |
1176 get_buffer(pb, str, FFMIN(size, str_size)); | |
1177 } | |
1178 | |
1179 static int mov_read_udta(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1180 { | |
1181 uint64_t end = url_ftell(pb) + atom.size; | |
1182 | |
1183 while (url_ftell(pb) + 8 < end) { | |
1184 uint32_t tag_size = get_be32(pb); | |
1185 uint32_t tag = get_le32(pb); | |
1186 uint64_t next = url_ftell(pb) + tag_size - 8; | |
1187 | |
1188 if (next > end) // stop if tag_size is wrong | |
1189 break; | |
1190 | |
1191 switch (tag) { | |
1192 case MKTAG(0xa9,'n','a','m'): | |
1193 mov_parse_udta_string(pb, c->fc->title, sizeof(c->fc->title)); | |
1194 break; | |
1195 case MKTAG(0xa9,'w','r','t'): | |
1196 mov_parse_udta_string(pb, c->fc->author, sizeof(c->fc->author)); | |
1197 break; | |
1198 case MKTAG(0xa9,'c','p','y'): | |
1199 mov_parse_udta_string(pb, c->fc->copyright, sizeof(c->fc->copyright)); | |
1200 break; | |
1201 case MKTAG(0xa9,'i','n','f'): | |
1202 mov_parse_udta_string(pb, c->fc->comment, sizeof(c->fc->comment)); | |
1203 break; | |
1204 default: | |
1205 break; | |
1206 } | |
1207 | |
1208 url_fseek(pb, next, SEEK_SET); | |
1209 } | |
1210 | |
1211 return 0; | |
1212 } | |
1213 | |
1214 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1215 { | |
1216 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
1217 int version = get_byte(pb); | |
1218 | |
1219 get_be24(pb); /* flags */ | |
1220 /* | |
1221 MOV_TRACK_ENABLED 0x0001 | |
1222 MOV_TRACK_IN_MOVIE 0x0002 | |
1223 MOV_TRACK_IN_PREVIEW 0x0004 | |
1224 MOV_TRACK_IN_POSTER 0x0008 | |
1225 */ | |
1226 | |
1227 if (version == 1) { | |
1228 get_be64(pb); | |
1229 get_be64(pb); | |
1230 } else { | |
1231 get_be32(pb); /* creation time */ | |
1232 get_be32(pb); /* modification time */ | |
1233 } | |
1234 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/ | |
1235 get_be32(pb); /* reserved */ | |
1236 st->start_time = 0; /* check */ | |
1237 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */ | |
1238 get_be32(pb); /* reserved */ | |
1239 get_be32(pb); /* reserved */ | |
1240 | |
1241 get_be16(pb); /* layer */ | |
1242 get_be16(pb); /* alternate group */ | |
1243 get_be16(pb); /* volume */ | |
1244 get_be16(pb); /* reserved */ | |
1245 | |
1246 url_fskip(pb, 36); /* display matrix */ | |
1247 | |
1248 /* those are fixed-point */ | |
1249 get_be32(pb); /* track width */ | |
1250 get_be32(pb); /* track height */ | |
1251 | |
1252 return 0; | |
1253 } | |
1254 | |
1255 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */ | |
1256 /* like the files created with Adobe Premiere 5.0, for samples see */ | |
1257 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */ | |
1258 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1259 { | |
1260 int err; | |
1261 | |
1262 if (atom.size < 8) | |
1263 return 0; /* continue */ | |
1264 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */ | |
1265 url_fskip(pb, atom.size - 4); | |
1266 return 0; | |
1267 } | |
1268 atom.type = get_le32(pb); | |
1269 atom.offset += 8; | |
1270 atom.size -= 8; | |
1271 if (atom.type != MKTAG('m', 'd', 'a', 't')) { | |
1272 url_fskip(pb, atom.size); | |
1273 return 0; | |
1274 } | |
1275 err = mov_read_mdat(c, pb, atom); | |
1276 return err; | |
1277 } | |
1278 | |
1279 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1280 { | |
1281 #ifdef CONFIG_ZLIB | |
1282 ByteIOContext ctx; | |
1283 uint8_t *cmov_data; | |
1284 uint8_t *moov_data; /* uncompressed data */ | |
1285 long cmov_len, moov_len; | |
1286 int ret; | |
1287 | |
1288 get_be32(pb); /* dcom atom */ | |
1289 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' )) | |
1290 return -1; | |
1291 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) { | |
1292 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !"); | |
1293 return -1; | |
1294 } | |
1295 get_be32(pb); /* cmvd atom */ | |
1296 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' )) | |
1297 return -1; | |
1298 moov_len = get_be32(pb); /* uncompressed size */ | |
1299 cmov_len = atom.size - 6 * 4; | |
1300 | |
1301 cmov_data = av_malloc(cmov_len); | |
1302 if (!cmov_data) | |
1303 return -1; | |
1304 moov_data = av_malloc(moov_len); | |
1305 if (!moov_data) { | |
1306 av_free(cmov_data); | |
1307 return -1; | |
1308 } | |
1309 get_buffer(pb, cmov_data, cmov_len); | |
1310 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) | |
1311 return -1; | |
1312 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0) | |
1313 return -1; | |
1314 atom.type = MKTAG( 'm', 'o', 'o', 'v' ); | |
1315 atom.offset = 0; | |
1316 atom.size = moov_len; | |
1317 #ifdef DEBUG | |
1318 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); } | |
1319 #endif | |
1320 ret = mov_read_default(c, &ctx, atom); | |
1321 av_free(moov_data); | |
1322 av_free(cmov_data); | |
1323 return ret; | |
1324 #else | |
1325 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n"); | |
1326 return -1; | |
1327 #endif | |
1328 } | |
1329 | |
1330 /* edit list atom */ | |
1331 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1332 { | |
1333 MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data; | |
1334 int i, edit_count; | |
1335 | |
1336 get_byte(pb); /* version */ | |
1337 get_be24(pb); /* flags */ | |
1338 edit_count= sc->edit_count = get_be32(pb); /* entries */ | |
1339 | |
1340 for(i=0; i<edit_count; i++){ | |
1341 int time; | |
1342 get_be32(pb); /* Track duration */ | |
1343 time = get_be32(pb); /* Media time */ | |
1344 get_be32(pb); /* Media rate */ | |
1345 if (time != 0) | |
1346 av_log(c->fc, AV_LOG_WARNING, "edit list not starting at 0, " | |
1347 "a/v desync might occur, patch welcome\n"); | |
1348 } | |
1349 dprintf(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, sc->edit_count); | |
1350 return 0; | |
1351 } | |
1352 | |
1353 static const MOVParseTableEntry mov_default_parse_table[] = { | |
1354 /* mp4 atoms */ | |
1355 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco }, | |
1356 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */ | |
1357 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, | |
1358 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_dref }, | |
1359 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default }, | |
1360 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst }, | |
1361 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda }, | |
1362 { MKTAG( 'f', 'i', 'e', 'l' ), mov_read_extradata }, | |
1363 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp }, | |
1364 { MKTAG( 'g', 'l', 'b', 'l' ), mov_read_glbl }, | |
1365 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr }, | |
1366 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_extradata }, | |
1367 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat }, | |
1368 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd }, | |
1369 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default }, | |
1370 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default }, | |
1371 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov }, | |
1372 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd }, | |
1373 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */ | |
1374 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_extradata }, /* alac specific atom */ | |
1375 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_glbl }, | |
1376 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default }, | |
1377 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco }, | |
1378 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc }, | |
1379 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */ | |
1380 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */ | |
1381 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */ | |
1382 { MKTAG( 's', 't', 't', 's' ), mov_read_stts }, | |
1383 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */ | |
1384 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak }, | |
1385 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_udta }, | |
1386 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave }, | |
1387 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds }, | |
1388 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */ | |
1389 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov }, | |
1390 { 0, NULL } | |
1391 }; | |
1392 | |
1393 /* XXX: is it sufficient ? */ | |
1394 static int mov_probe(AVProbeData *p) | |
1395 { | |
1396 unsigned int offset; | |
1397 uint32_t tag; | |
1398 int score = 0; | |
1399 | |
1400 /* check file header */ | |
1401 offset = 0; | |
1402 for(;;) { | |
1403 /* ignore invalid offset */ | |
1404 if ((offset + 8) > (unsigned int)p->buf_size) | |
1405 return score; | |
1406 tag = AV_RL32(p->buf + offset + 4); | |
1407 switch(tag) { | |
1408 /* check for obvious tags */ | |
1409 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */ | |
1410 case MKTAG( 'm', 'o', 'o', 'v' ): | |
1411 case MKTAG( 'm', 'd', 'a', 't' ): | |
1412 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */ | |
1413 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */ | |
1414 return AVPROBE_SCORE_MAX; | |
1415 /* those are more common words, so rate then a bit less */ | |
1416 case MKTAG( 'e', 'd', 'i', 'w' ): /* xdcam files have reverted first tags */ | |
1417 case MKTAG( 'w', 'i', 'd', 'e' ): | |
1418 case MKTAG( 'f', 'r', 'e', 'e' ): | |
1419 case MKTAG( 'j', 'u', 'n', 'k' ): | |
1420 case MKTAG( 'p', 'i', 'c', 't' ): | |
1421 return AVPROBE_SCORE_MAX - 5; | |
1422 case MKTAG(0x82,0x82,0x7f,0x7d ): | |
1423 case MKTAG( 'f', 't', 'y', 'p' ): | |
1424 case MKTAG( 's', 'k', 'i', 'p' ): | |
1425 case MKTAG( 'u', 'u', 'i', 'd' ): | |
1426 offset = AV_RB32(p->buf+offset) + offset; | |
1427 /* if we only find those cause probedata is too small at least rate them */ | |
1428 score = AVPROBE_SCORE_MAX - 50; | |
1429 break; | |
1430 default: | |
1431 /* unrecognized tag */ | |
1432 return score; | |
1433 } | |
1434 } | |
1435 return score; | |
1436 } | 1090 } |
1437 | 1091 |
1438 static void mov_build_index(MOVContext *mov, AVStream *st) | 1092 static void mov_build_index(MOVContext *mov, AVStream *st) |
1439 { | 1093 { |
1440 MOVStreamContext *sc = st->priv_data; | 1094 MOVStreamContext *sc = st->priv_data; |
1541 out: | 1195 out: |
1542 /* adjust sample count to avindex entries */ | 1196 /* adjust sample count to avindex entries */ |
1543 sc->sample_count = st->nb_index_entries; | 1197 sc->sample_count = st->nb_index_entries; |
1544 } | 1198 } |
1545 | 1199 |
1200 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1201 { | |
1202 AVStream *st; | |
1203 MOVStreamContext *sc; | |
1204 int ret; | |
1205 | |
1206 st = av_new_stream(c->fc, c->fc->nb_streams); | |
1207 if (!st) return -2; | |
1208 sc = av_mallocz(sizeof(MOVStreamContext)); | |
1209 if (!sc) { | |
1210 av_free(st); | |
1211 return -1; | |
1212 } | |
1213 | |
1214 st->priv_data = sc; | |
1215 st->codec->codec_type = CODEC_TYPE_DATA; | |
1216 st->start_time = 0; /* XXX: check */ | |
1217 | |
1218 if ((ret = mov_read_default(c, pb, atom)) < 0) | |
1219 return ret; | |
1220 | |
1221 /* sanity checks */ | |
1222 if(!sc->stts_count || !sc->chunk_count || !sc->sample_to_chunk_sz || | |
1223 (!sc->sample_size && !sc->sample_count)){ | |
1224 av_log(c->fc, AV_LOG_ERROR, "missing mandatory atoms, broken header\n"); | |
1225 sc->sample_count = 0; //ignore track | |
1226 return 0; | |
1227 } | |
1228 if(!sc->time_rate) | |
1229 sc->time_rate=1; | |
1230 if(!sc->time_scale) | |
1231 sc->time_scale= c->time_scale; | |
1232 av_set_pts_info(st, 64, sc->time_rate, sc->time_scale); | |
1233 | |
1234 if (st->codec->codec_type == CODEC_TYPE_AUDIO && sc->stts_count == 1) | |
1235 st->codec->frame_size = av_rescale(sc->time_rate, st->codec->sample_rate, sc->time_scale); | |
1236 | |
1237 if(st->duration != AV_NOPTS_VALUE){ | |
1238 assert(st->duration % sc->time_rate == 0); | |
1239 st->duration /= sc->time_rate; | |
1240 } | |
1241 sc->ffindex = st->index; | |
1242 mov_build_index(c, st); | |
1243 | |
1244 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { | |
1245 if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0) | |
1246 av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening external essence: %s\n", | |
1247 st->index, strerror(errno)); | |
1248 } else | |
1249 sc->pb = c->fc->pb; | |
1250 | |
1251 switch (st->codec->codec_id) { | |
1252 #ifdef CONFIG_H261_DECODER | |
1253 case CODEC_ID_H261: | |
1254 #endif | |
1255 #ifdef CONFIG_H263_DECODER | |
1256 case CODEC_ID_H263: | |
1257 #endif | |
1258 #ifdef CONFIG_MPEG4_DECODER | |
1259 case CODEC_ID_MPEG4: | |
1260 #endif | |
1261 st->codec->width= 0; /* let decoder init width/height */ | |
1262 st->codec->height= 0; | |
1263 break; | |
1264 #ifdef CONFIG_LIBFAAD | |
1265 case CODEC_ID_AAC: | |
1266 #endif | |
1267 #ifdef CONFIG_VORBIS_DECODER | |
1268 case CODEC_ID_VORBIS: | |
1269 #endif | |
1270 case CODEC_ID_MP3ON4: | |
1271 st->codec->sample_rate= 0; /* let decoder init parameters properly */ | |
1272 break; | |
1273 } | |
1274 return 0; | |
1275 } | |
1276 | |
1277 static void mov_parse_udta_string(ByteIOContext *pb, char *str, int size) | |
1278 { | |
1279 uint16_t str_size = get_be16(pb); /* string length */; | |
1280 | |
1281 get_be16(pb); /* skip language */ | |
1282 get_buffer(pb, str, FFMIN(size, str_size)); | |
1283 } | |
1284 | |
1285 static int mov_read_udta(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1286 { | |
1287 uint64_t end = url_ftell(pb) + atom.size; | |
1288 | |
1289 while (url_ftell(pb) + 8 < end) { | |
1290 uint32_t tag_size = get_be32(pb); | |
1291 uint32_t tag = get_le32(pb); | |
1292 uint64_t next = url_ftell(pb) + tag_size - 8; | |
1293 | |
1294 if (next > end) // stop if tag_size is wrong | |
1295 break; | |
1296 | |
1297 switch (tag) { | |
1298 case MKTAG(0xa9,'n','a','m'): | |
1299 mov_parse_udta_string(pb, c->fc->title, sizeof(c->fc->title)); | |
1300 break; | |
1301 case MKTAG(0xa9,'w','r','t'): | |
1302 mov_parse_udta_string(pb, c->fc->author, sizeof(c->fc->author)); | |
1303 break; | |
1304 case MKTAG(0xa9,'c','p','y'): | |
1305 mov_parse_udta_string(pb, c->fc->copyright, sizeof(c->fc->copyright)); | |
1306 break; | |
1307 case MKTAG(0xa9,'i','n','f'): | |
1308 mov_parse_udta_string(pb, c->fc->comment, sizeof(c->fc->comment)); | |
1309 break; | |
1310 default: | |
1311 break; | |
1312 } | |
1313 | |
1314 url_fseek(pb, next, SEEK_SET); | |
1315 } | |
1316 | |
1317 return 0; | |
1318 } | |
1319 | |
1320 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1321 { | |
1322 AVStream *st = c->fc->streams[c->fc->nb_streams-1]; | |
1323 int version = get_byte(pb); | |
1324 | |
1325 get_be24(pb); /* flags */ | |
1326 /* | |
1327 MOV_TRACK_ENABLED 0x0001 | |
1328 MOV_TRACK_IN_MOVIE 0x0002 | |
1329 MOV_TRACK_IN_PREVIEW 0x0004 | |
1330 MOV_TRACK_IN_POSTER 0x0008 | |
1331 */ | |
1332 | |
1333 if (version == 1) { | |
1334 get_be64(pb); | |
1335 get_be64(pb); | |
1336 } else { | |
1337 get_be32(pb); /* creation time */ | |
1338 get_be32(pb); /* modification time */ | |
1339 } | |
1340 st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/ | |
1341 get_be32(pb); /* reserved */ | |
1342 st->start_time = 0; /* check */ | |
1343 (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */ | |
1344 get_be32(pb); /* reserved */ | |
1345 get_be32(pb); /* reserved */ | |
1346 | |
1347 get_be16(pb); /* layer */ | |
1348 get_be16(pb); /* alternate group */ | |
1349 get_be16(pb); /* volume */ | |
1350 get_be16(pb); /* reserved */ | |
1351 | |
1352 url_fskip(pb, 36); /* display matrix */ | |
1353 | |
1354 /* those are fixed-point */ | |
1355 get_be32(pb); /* track width */ | |
1356 get_be32(pb); /* track height */ | |
1357 | |
1358 return 0; | |
1359 } | |
1360 | |
1361 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */ | |
1362 /* like the files created with Adobe Premiere 5.0, for samples see */ | |
1363 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */ | |
1364 static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1365 { | |
1366 int err; | |
1367 | |
1368 if (atom.size < 8) | |
1369 return 0; /* continue */ | |
1370 if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */ | |
1371 url_fskip(pb, atom.size - 4); | |
1372 return 0; | |
1373 } | |
1374 atom.type = get_le32(pb); | |
1375 atom.offset += 8; | |
1376 atom.size -= 8; | |
1377 if (atom.type != MKTAG('m', 'd', 'a', 't')) { | |
1378 url_fskip(pb, atom.size); | |
1379 return 0; | |
1380 } | |
1381 err = mov_read_mdat(c, pb, atom); | |
1382 return err; | |
1383 } | |
1384 | |
1385 static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1386 { | |
1387 #ifdef CONFIG_ZLIB | |
1388 ByteIOContext ctx; | |
1389 uint8_t *cmov_data; | |
1390 uint8_t *moov_data; /* uncompressed data */ | |
1391 long cmov_len, moov_len; | |
1392 int ret; | |
1393 | |
1394 get_be32(pb); /* dcom atom */ | |
1395 if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' )) | |
1396 return -1; | |
1397 if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) { | |
1398 av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !"); | |
1399 return -1; | |
1400 } | |
1401 get_be32(pb); /* cmvd atom */ | |
1402 if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' )) | |
1403 return -1; | |
1404 moov_len = get_be32(pb); /* uncompressed size */ | |
1405 cmov_len = atom.size - 6 * 4; | |
1406 | |
1407 cmov_data = av_malloc(cmov_len); | |
1408 if (!cmov_data) | |
1409 return -1; | |
1410 moov_data = av_malloc(moov_len); | |
1411 if (!moov_data) { | |
1412 av_free(cmov_data); | |
1413 return -1; | |
1414 } | |
1415 get_buffer(pb, cmov_data, cmov_len); | |
1416 if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) | |
1417 return -1; | |
1418 if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0) | |
1419 return -1; | |
1420 atom.type = MKTAG( 'm', 'o', 'o', 'v' ); | |
1421 atom.offset = 0; | |
1422 atom.size = moov_len; | |
1423 #ifdef DEBUG | |
1424 // { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); } | |
1425 #endif | |
1426 ret = mov_read_default(c, &ctx, atom); | |
1427 av_free(moov_data); | |
1428 av_free(cmov_data); | |
1429 return ret; | |
1430 #else | |
1431 av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n"); | |
1432 return -1; | |
1433 #endif | |
1434 } | |
1435 | |
1436 /* edit list atom */ | |
1437 static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |
1438 { | |
1439 MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data; | |
1440 int i, edit_count; | |
1441 | |
1442 get_byte(pb); /* version */ | |
1443 get_be24(pb); /* flags */ | |
1444 edit_count= sc->edit_count = get_be32(pb); /* entries */ | |
1445 | |
1446 for(i=0; i<edit_count; i++){ | |
1447 int time; | |
1448 get_be32(pb); /* Track duration */ | |
1449 time = get_be32(pb); /* Media time */ | |
1450 get_be32(pb); /* Media rate */ | |
1451 if (time != 0) | |
1452 av_log(c->fc, AV_LOG_WARNING, "edit list not starting at 0, " | |
1453 "a/v desync might occur, patch welcome\n"); | |
1454 } | |
1455 dprintf(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, sc->edit_count); | |
1456 return 0; | |
1457 } | |
1458 | |
1459 static const MOVParseTableEntry mov_default_parse_table[] = { | |
1460 /* mp4 atoms */ | |
1461 { MKTAG( 'c', 'o', '6', '4' ), mov_read_stco }, | |
1462 { MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */ | |
1463 { MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, | |
1464 { MKTAG( 'd', 'r', 'e', 'f' ), mov_read_dref }, | |
1465 { MKTAG( 'e', 'd', 't', 's' ), mov_read_default }, | |
1466 { MKTAG( 'e', 'l', 's', 't' ), mov_read_elst }, | |
1467 { MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda }, | |
1468 { MKTAG( 'f', 'i', 'e', 'l' ), mov_read_extradata }, | |
1469 { MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp }, | |
1470 { MKTAG( 'g', 'l', 'b', 'l' ), mov_read_glbl }, | |
1471 { MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr }, | |
1472 { MKTAG( 'j', 'p', '2', 'h' ), mov_read_extradata }, | |
1473 { MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat }, | |
1474 { MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd }, | |
1475 { MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default }, | |
1476 { MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default }, | |
1477 { MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov }, | |
1478 { MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd }, | |
1479 { MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */ | |
1480 { MKTAG( 'a', 'l', 'a', 'c' ), mov_read_extradata }, /* alac specific atom */ | |
1481 { MKTAG( 'a', 'v', 'c', 'C' ), mov_read_glbl }, | |
1482 { MKTAG( 's', 't', 'b', 'l' ), mov_read_default }, | |
1483 { MKTAG( 's', 't', 'c', 'o' ), mov_read_stco }, | |
1484 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc }, | |
1485 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */ | |
1486 { MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */ | |
1487 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */ | |
1488 { MKTAG( 's', 't', 't', 's' ), mov_read_stts }, | |
1489 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */ | |
1490 { MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak }, | |
1491 { MKTAG( 'u', 'd', 't', 'a' ), mov_read_udta }, | |
1492 { MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave }, | |
1493 { MKTAG( 'e', 's', 'd', 's' ), mov_read_esds }, | |
1494 { MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */ | |
1495 { MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov }, | |
1496 { 0, NULL } | |
1497 }; | |
1498 | |
1499 /* XXX: is it sufficient ? */ | |
1500 static int mov_probe(AVProbeData *p) | |
1501 { | |
1502 unsigned int offset; | |
1503 uint32_t tag; | |
1504 int score = 0; | |
1505 | |
1506 /* check file header */ | |
1507 offset = 0; | |
1508 for(;;) { | |
1509 /* ignore invalid offset */ | |
1510 if ((offset + 8) > (unsigned int)p->buf_size) | |
1511 return score; | |
1512 tag = AV_RL32(p->buf + offset + 4); | |
1513 switch(tag) { | |
1514 /* check for obvious tags */ | |
1515 case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */ | |
1516 case MKTAG( 'm', 'o', 'o', 'v' ): | |
1517 case MKTAG( 'm', 'd', 'a', 't' ): | |
1518 case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */ | |
1519 case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */ | |
1520 return AVPROBE_SCORE_MAX; | |
1521 /* those are more common words, so rate then a bit less */ | |
1522 case MKTAG( 'e', 'd', 'i', 'w' ): /* xdcam files have reverted first tags */ | |
1523 case MKTAG( 'w', 'i', 'd', 'e' ): | |
1524 case MKTAG( 'f', 'r', 'e', 'e' ): | |
1525 case MKTAG( 'j', 'u', 'n', 'k' ): | |
1526 case MKTAG( 'p', 'i', 'c', 't' ): | |
1527 return AVPROBE_SCORE_MAX - 5; | |
1528 case MKTAG(0x82,0x82,0x7f,0x7d ): | |
1529 case MKTAG( 'f', 't', 'y', 'p' ): | |
1530 case MKTAG( 's', 'k', 'i', 'p' ): | |
1531 case MKTAG( 'u', 'u', 'i', 'd' ): | |
1532 offset = AV_RB32(p->buf+offset) + offset; | |
1533 /* if we only find those cause probedata is too small at least rate them */ | |
1534 score = AVPROBE_SCORE_MAX - 50; | |
1535 break; | |
1536 default: | |
1537 /* unrecognized tag */ | |
1538 return score; | |
1539 } | |
1540 } | |
1541 return score; | |
1542 } | |
1543 | |
1546 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) | 1544 static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) |
1547 { | 1545 { |
1548 MOVContext *mov = s->priv_data; | 1546 MOVContext *mov = s->priv_data; |
1549 ByteIOContext *pb = s->pb; | 1547 ByteIOContext *pb = s->pb; |
1550 int i, err; | 1548 int i, err; |