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;