This adds OPAtom support and proper seeking. D-10 and non-seekable OP1a streams still use the old demuxing/seeking code.
Unified · Split
| @@ -197,6 +197,9 @@ typedef struct { · 196 unmodified lines | ||
| 197 | 197 | int parsing_backward; |
| 198 | 198 | int64_t last_forward_tell; |
| 199 | 199 | int last_forward_partition; |
| 200 | + int current_edit_unit; | |
| 201 | + int current_stream; | |
| 202 | + int d10; | |
| 200 | 203 | } MXFContext; |
| 201 | 204 | |
| 202 | 205 | enum MXFWrappingScheme { |
| @@ -372,7 +375,7 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv · 169 unmodified lines | ||
| 372 | 375 | return 0; |
| 373 | 376 | } |
| 374 | 377 | |
| 375 | −static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 378 | +static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) | |
| 376 | 379 | { |
| 377 | 380 | KLVPacket klv; |
| 378 | 381 | |
| @@ -418,6 +421,65 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) · 39 unmodified lines | ||
| 418 | 421 | return AVERROR_EOF; |
| 419 | 422 | } |
| 420 | 423 | |
| 424 | +static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 425 | +{ | |
| 426 | + MXFContext *mxf = s->priv_data; | |
| 427 | + AVIndexEntry *e; | |
| 428 | + int ret; | |
| 429 | + int64_t ret64; | |
| 430 | + KLVPacket klv; | |
| 431 | + AVStream *st; | |
| 432 | + | |
| 433 | + /* TODO: better logic for this? | |
| 434 | + * only files that lack all index segments prior to the essence need this */ | |
| 435 | + if (!s->pb->seekable && mxf->op != OPAtom || mxf->d10) | |
| 436 | + return mxf_read_packet_old(s, pkt); | |
| 437 | + | |
| 438 | + if (mxf->current_stream >= s->nb_streams) { | |
| 439 | + mxf->current_edit_unit++; | |
| 440 | + mxf->current_stream = 0; | |
| 441 | + } | |
| 442 | + | |
| 443 | + st = s->streams[mxf->current_stream]; | |
| 444 | + | |
| 445 | + if (mxf->current_edit_unit >= st->nb_index_entries) | |
| 446 | + return AVERROR_EOF; | |
| 447 | + | |
| 448 | + e = &st->index_entries[mxf->current_edit_unit]; | |
| 449 | + | |
| 450 | + if ((ret64 = avio_seek(s->pb, e->pos, SEEK_SET)) < 0) | |
| 451 | + return ret64; | |
| 452 | + | |
| 453 | + if (mxf->op == OPAtom) { | |
| 454 | + /* OPAtom - no KL, just essence */ | |
| 455 | + if ((ret = av_get_packet(s->pb, pkt, e->size)) != e->size) | |
| 456 | + return ret < 0 ? ret : AVERROR_EOF; | |
| 457 | + } else { | |
| 458 | + /* read KL, read L bytes of essence */ | |
| 459 | + if ((ret = klv_read_packet(&klv, s->pb)) < 0) | |
| 460 | + return ret; | |
| 461 | + | |
| 462 | + /* untested, but looks OK */ | |
| 463 | + if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { | |
| 464 | + int res = mxf_decrypt_triplet(s, pkt, &klv); | |
| 465 | + if (res < 0) { | |
| 466 | + av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n"); | |
| 467 | + return -1; | |
| 468 | + } | |
| 469 | + return 0; | |
| 470 | + } | |
| 471 | + | |
| 472 | + if ((ret = av_get_packet(s->pb, pkt, klv.length)) != klv.length) | |
| 473 | + return ret < 0 ? ret : AVERROR_EOF; | |
| 474 | + | |
| 475 | + pkt->pos = e->pos; | |
| 476 | + } | |
| 477 | + | |
| 478 | + pkt->stream_index = mxf->current_stream++; | |
| 479 | + | |
| 480 | + return 0; | |
| 481 | +} | |
| 482 | + | |
| 421 | 483 | static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) |
| 422 | 484 | { |
| 423 | 485 | MXFContext *mxf = arg; |
| @@ -925,6 +987,8 @@ static const MXFCodecUL mxf_essence_container_uls[] = { · 501 unmodified lines | ||
| 925 | 987 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, |
| 926 | 988 | }; |
| 927 | 989 | |
| 990 | +static UID mxf_d10_ul = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }; | |
| 991 | + | |
| 928 | 992 | static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments) |
| 929 | 993 | { |
| 930 | 994 | int i, j, nb_segments = 0; |
| @@ -1252,6 +1316,11 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 321 unmodified lines | ||
| 1252 | 1316 | } |
| 1253 | 1317 | } |
| 1254 | 1318 | } |
| 1319 | + | |
| 1320 | + /* HACK: revert to the old demuxing/seeking scode for D-10 for now */ | |
| 1321 | + if (mxf_match_uid(essence_container_ul, mxf_d10_ul, 14)) | |
| 1322 | + mxf->d10 = 1; | |
| 1323 | + | |
| 1255 | 1324 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ |
| 1256 | 1325 | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); |
| 1257 | 1326 | st->codec->codec_id = codec_ul->id; |
| @@ -1291,8 +1360,8 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 33 unmodified lines | ||
| 1291 | 1360 | } |
| 1292 | 1361 | } |
| 1293 | 1362 | if (st->codec->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) { |
| 1294 | − av_log(mxf->fc, AV_LOG_WARNING, "only frame wrapped mappings are correctly supported\n"); | |
| 1295 | − st->need_parsing = AVSTREAM_PARSE_FULL; | |
| 1363 | + /* TODO: decode timestamps */ | |
| 1364 | + st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; | |
| 1296 | 1365 | } |
| 1297 | 1366 | |
| 1298 | 1367 | if ((ret = mxf_parse_index(mxf, material_track->track_id, st))) |
| @@ -1659,7 +1728,11 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti · 360 unmodified lines | ||
| 1659 | 1728 | { |
| 1660 | 1729 | AVStream *st = s->streams[stream_index]; |
| 1661 | 1730 | int64_t seconds; |
| 1731 | + MXFContext* mxf = s->priv_data; | |
| 1732 | + int64_t seekpos; | |
| 1733 | + int index; | |
| 1662 | 1734 | |
| 1735 | + if (mxf->d10) { | |
| 1663 | 1736 | if (!s->bit_rate) |
| 1664 | 1737 | return -1; |
| 1665 | 1738 | if (sample_time < 0) |
| @@ -1668,6 +1741,27 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti · 2 unmodified lines | ||
| 1668 | 1741 | if (avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET) < 0) |
| 1669 | 1742 | return -1; |
| 1670 | 1743 | ff_update_cur_dts(s, st, sample_time); |
| 1744 | + } else { | |
| 1745 | + if (st->nb_index_entries <= 0) | |
| 1746 | + return -1; | |
| 1747 | + | |
| 1748 | + index = av_index_search_timestamp(st, sample_time, flags); | |
| 1749 | + | |
| 1750 | + av_dlog(s, "stream %d, timestamp %"PRId64", sample %d\n", st->index, sample_time, index); | |
| 1751 | + | |
| 1752 | + if (index < 0) { | |
| 1753 | + if (sample_time < st->index_entries[0].timestamp) | |
| 1754 | + index = 0; | |
| 1755 | + else | |
| 1756 | + return -1; | |
| 1757 | + } | |
| 1758 | + | |
| 1759 | + seekpos = st->index_entries[index].pos; | |
| 1760 | + av_update_cur_dts(s, st, st->index_entries[index].timestamp); | |
| 1761 | + mxf->current_edit_unit = st->index_entries[index].timestamp; | |
| 1762 | + mxf->current_stream = 0; | |
| 1763 | + avio_seek(s->pb, seekpos, SEEK_SET); | |
| 1764 | + } | |
| 1671 | 1765 | return 0; |
| 1672 | 1766 | } |
| 1673 | 1767 | |
| @@ -2,52 +2,47 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 · 1 unmodified line | ||
| 2 | 2 | ret: 0 st:-1 flags:0 ts:-1.000000 |
| 3 | 3 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 4 | 4 | ret: 0 st:-1 flags:1 ts: 1.894167 |
| 5 | −ret:-1 | |
| 5 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 6 | 6 | ret: 0 st: 0 flags:0 ts: 0.800000 |
| 7 | −ret:-1 | |
| 7 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 8 | 8 | ret: 0 st: 0 flags:1 ts:-0.320000 |
| 9 | 9 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 10 | −ret: 0 st: 1 flags:0 ts: 2.560000 | |
| 11 | −ret:-1 | |
| 10 | +ret:-1 st: 1 flags:0 ts: 2.560000 | |
| 12 | 11 | ret: 0 st: 1 flags:1 ts: 1.480000 |
| 13 | −ret:-1 | |
| 12 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 14 | 13 | ret: 0 st:-1 flags:0 ts: 0.365002 |
| 15 | −ret: 0 st: 0 flags:1 dts: 0.360000 pts: NOPTS pos: 6144 size: 24801 | |
| 14 | +ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 211968 size: 24787 | |
| 16 | 15 | ret: 0 st:-1 flags:1 ts:-0.740831 |
| 17 | 16 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 18 | −ret: 0 st: 0 flags:0 ts: 2.160000 | |
| 19 | −ret:-1 | |
| 17 | +ret:-1 st: 0 flags:0 ts: 2.160000 | |
| 20 | 18 | ret: 0 st: 0 flags:1 ts: 1.040000 |
| 21 | −ret:-1 | |
| 19 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 22 | 20 | ret: 0 st: 1 flags:0 ts:-0.040000 |
| 23 | 21 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 24 | 22 | ret: 0 st: 1 flags:1 ts: 2.840000 |
| 25 | −ret:-1 | |
| 26 | −ret: 0 st:-1 flags:0 ts: 1.730004 | |
| 27 | −ret:-1 | |
| 23 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 24 | +ret:-1 st:-1 flags:0 ts: 1.730004 | |
| 28 | 25 | ret: 0 st:-1 flags:1 ts: 0.624171 |
| 29 | −ret:-1 | |
| 26 | +ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 211968 size: 24787 | |
| 30 | 27 | ret: 0 st: 0 flags:0 ts:-0.480000 |
| 31 | 28 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 32 | 29 | ret: 0 st: 0 flags:1 ts: 2.400000 |
| 33 | −ret:-1 | |
| 34 | −ret: 0 st: 1 flags:0 ts: 1.320000 | |
| 35 | −ret:-1 | |
| 30 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 31 | +ret:-1 st: 1 flags:0 ts: 1.320000 | |
| 36 | 32 | ret: 0 st: 1 flags:1 ts: 0.200000 |
| 37 | −ret: 0 st: 0 flags:1 dts: 0.200000 pts: NOPTS pos: 6144 size: 24801 | |
| 33 | +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | |
| 38 | 34 | ret: 0 st:-1 flags:0 ts:-0.904994 |
| 39 | 35 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 40 | 36 | ret: 0 st:-1 flags:1 ts: 1.989173 |
| 41 | −ret:-1 | |
| 37 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 42 | 38 | ret: 0 st: 0 flags:0 ts: 0.880000 |
| 43 | −ret:-1 | |
| 39 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 44 | 40 | ret: 0 st: 0 flags:1 ts:-0.240000 |
| 45 | 41 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 46 | −ret: 0 st: 1 flags:0 ts: 2.680000 | |
| 47 | −ret:-1 | |
| 42 | +ret:-1 st: 1 flags:0 ts: 2.680000 | |
| 48 | 43 | ret: 0 st: 1 flags:1 ts: 1.560000 |
| 49 | −ret:-1 | |
| 44 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 50 | 45 | ret: 0 st:-1 flags:0 ts: 0.460008 |
| 51 | −ret: 0 st: 0 flags:1 dts: 0.480000 pts: NOPTS pos: 6144 size: 24801 | |
| 46 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 52 | 47 | ret: 0 st:-1 flags:1 ts:-0.645825 |
| 53 | 48 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |