| @@ -58,6 +58,8 @@ · 57 unmodified lines |
| 58 | 58 | #include "internal.h" |
| 59 | 59 | #include "avio_internal.h" |
| 60 | 60 | #include "demux.h" |
| 61 | +#include "iamf_parse.h" |
| 62 | +#include "iamf_reader.h" |
| 61 | 63 | #include "dovi_isom.h" |
| 62 | 64 | #include "riff.h" |
| 63 | 65 | #include "isom.h" |
| @@ -212,6 +214,7 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len) · 148 unmodified lines |
| 212 | 214 | } |
| 213 | 215 | st = c->fc->streams[c->fc->nb_streams - 1]; |
| 214 | 216 | st->priv_data = sc; |
| 217 | + sc->id = st->id; |
| 215 | 218 | sc->refcount = 1; |
| 216 | 219 | |
| 217 | 220 | if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) { |
| @@ -836,6 +839,183 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 618 unmodified lines |
| 836 | 839 | return 0; |
| 837 | 840 | } |
| 838 | 841 | |
| 842 | +static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
| 843 | +{ |
| 844 | + AVStream *st; |
| 845 | + MOVStreamContext *sc; |
| 846 | + FFIOContext b; |
| 847 | + AVIOContext *descriptor_pb; |
| 848 | + AVDictionary *metadata; |
| 849 | + IAMFContext *iamf; |
| 850 | + int64_t start_time, duration; |
| 851 | + unsigned descriptors_size; |
| 852 | + int nb_frames, disposition; |
| 853 | + int version, ret; |
| 854 | + |
| 855 | + if (atom.size < 5) |
| 856 | + return AVERROR_INVALIDDATA; |
| 857 | + |
| 858 | + if (c->fc->nb_streams < 1) |
| 859 | + return 0; |
| 860 | + |
| 861 | + version = avio_r8(pb); |
| 862 | + if (version != 1) { |
| 863 | + av_log(c->fc, AV_LOG_ERROR, "%s configurationVersion %d", |
| 864 | + version < 1 ? "invalid" : "unsupported", version); |
| 865 | + return AVERROR_INVALIDDATA; |
| 866 | + } |
| 867 | + |
| 868 | + descriptors_size = ffio_read_leb(pb); |
| 869 | + if (!descriptors_size || descriptors_size > INT_MAX) |
| 870 | + return AVERROR_INVALIDDATA; |
| 871 | + |
| 872 | + st = c->fc->streams[c->fc->nb_streams - 1]; |
| 873 | + sc = st->priv_data; |
| 874 | + |
| 875 | + sc->iamf = av_mallocz(sizeof(*sc->iamf)); |
| 876 | + if (!sc->iamf) |
| 877 | + return AVERROR(ENOMEM); |
| 878 | + iamf = &sc->iamf->iamf; |
| 879 | + |
| 880 | + st->codecpar->extradata = av_malloc(descriptors_size); |
| 881 | + if (!st->codecpar->extradata) |
| 882 | + return AVERROR(ENOMEM); |
| 883 | + st->codecpar->extradata_size = descriptors_size; |
| 884 | + |
| 885 | + ret = avio_read(pb, st->codecpar->extradata, descriptors_size); |
| 886 | + if (ret != descriptors_size) |
| 887 | + return ret < 0 ? ret : AVERROR_INVALIDDATA; |
| 888 | + |
| 889 | + ffio_init_read_context(&b, st->codecpar->extradata, descriptors_size); |
| 890 | + descriptor_pb = &b.pub; |
| 891 | + |
| 892 | + ret = ff_iamfdec_read_descriptors(iamf, descriptor_pb, descriptors_size, c->fc); |
| 893 | + if (ret < 0) |
| 894 | + return ret; |
| 895 | + |
| 896 | + metadata = st->metadata; |
| 897 | + st->metadata = NULL; |
| 898 | + start_time = st->start_time; |
| 899 | + nb_frames = st->nb_frames; |
| 900 | + duration = st->duration; |
| 901 | + disposition = st->disposition; |
| 902 | + |
| 903 | + for (int i = 0; i < iamf->nb_audio_elements; i++) { |
| 904 | + IAMFAudioElement *audio_element = iamf->audio_elements[i]; |
| 905 | + AVStreamGroup *stg = |
| 906 | + avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL); |
| 907 | + |
| 908 | + if (!stg) { |
| 909 | + ret = AVERROR(ENOMEM); |
| 910 | + goto fail; |
| 911 | + } |
| 912 | + |
| 913 | + av_iamf_audio_element_free(&stg->params.iamf_audio_element); |
| 914 | + stg->id = audio_element->audio_element_id; |
| 915 | + /* Transfer ownership */ |
| 916 | + stg->params.iamf_audio_element = audio_element->element; |
| 917 | + audio_element->element = NULL; |
| 918 | + |
| 919 | + for (int j = 0; j < audio_element->nb_substreams; j++) { |
| 920 | + IAMFSubStream *substream = &audio_element->substreams[j]; |
| 921 | + AVStream *stream; |
| 922 | + |
| 923 | + if (!i && !j) { |
| 924 | + if (audio_element->layers[0].substream_count != 1) |
| 925 | + st->disposition &= ~AV_DISPOSITION_DEFAULT; |
| 926 | + stream = st; |
| 927 | + } else |
| 928 | + stream = avformat_new_stream(c->fc, NULL); |
| 929 | + if (!stream) { |
| 930 | + ret = AVERROR(ENOMEM); |
| 931 | + goto fail; |
| 932 | + } |
| 933 | + |
| 934 | + stream->start_time = start_time; |
| 935 | + stream->nb_frames = nb_frames; |
| 936 | + stream->duration = duration; |
| 937 | + stream->disposition = disposition; |
| 938 | + if (stream != st) { |
| 939 | + stream->priv_data = sc; |
| 940 | + sc->refcount++; |
| 941 | + } |
| 942 | + |
| 943 | + if (i || j) { |
| 944 | + stream->disposition |= AV_DISPOSITION_DEPENDENT; |
| 945 | + if (audio_element->layers[0].substream_count == 1) |
| 946 | + stream->disposition &= ~AV_DISPOSITION_DEFAULT; |
| 947 | + } |
| 948 | + |
| 949 | + ret = avcodec_parameters_copy(stream->codecpar, substream->codecpar); |
| 950 | + if (ret < 0) |
| 951 | + goto fail; |
| 952 | + |
| 953 | + stream->id = substream->audio_substream_id; |
| 954 | + |
| 955 | + avpriv_set_pts_info(st, 64, 1, sc->time_scale); |
| 956 | + |
| 957 | + ret = avformat_stream_group_add_stream(stg, stream); |
| 958 | + if (ret < 0) |
| 959 | + goto fail; |
| 960 | + } |
| 961 | + |
| 962 | + ret = av_dict_copy(&stg->metadata, metadata, 0); |
| 963 | + if (ret < 0) |
| 964 | + goto fail; |
| 965 | + } |
| 966 | + |
| 967 | + for (int i = 0; i < iamf->nb_mix_presentations; i++) { |
| 968 | + IAMFMixPresentation *mix_presentation = iamf->mix_presentations[i]; |
| 969 | + const AVIAMFMixPresentation *mix = mix_presentation->cmix; |
| 970 | + AVStreamGroup *stg = |
| 971 | + avformat_stream_group_create(c->fc, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, NULL); |
| 972 | + |
| 973 | + if (!stg) { |
| 974 | + ret = AVERROR(ENOMEM); |
| 975 | + goto fail; |
| 976 | + } |
| 977 | + |
| 978 | + av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation); |
| 979 | + stg->id = mix_presentation->mix_presentation_id; |
| 980 | + /* Transfer ownership */ |
| 981 | + stg->params.iamf_mix_presentation = mix_presentation->mix; |
| 982 | + mix_presentation->mix = NULL; |
| 983 | + |
| 984 | + for (int j = 0; j < mix->nb_submixes; j++) { |
| 985 | + const AVIAMFSubmix *submix = mix->submixes[j]; |
| 986 | + |
| 987 | + for (int k = 0; k < submix->nb_elements; k++) { |
| 988 | + const AVIAMFSubmixElement *submix_element = submix->elements[k]; |
| 989 | + const AVStreamGroup *audio_element = NULL; |
| 990 | + |
| 991 | + for (int l = 0; l < c->fc->nb_stream_groups; l++) |
| 992 | + if (c->fc->stream_groups[l]->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT && |
| 993 | + c->fc->stream_groups[l]->id == submix_element->audio_element_id) { |
| 994 | + audio_element = c->fc->stream_groups[l]; |
| 995 | + break; |
| 996 | + } |
| 997 | + av_assert0(audio_element); |
| 998 | + |
| 999 | + for (int l = 0; l < audio_element->nb_streams; l++) { |
| 1000 | + ret = avformat_stream_group_add_stream(stg, audio_element->streams[l]); |
| 1001 | + if (ret < 0 && ret != AVERROR(EEXIST)) |
| 1002 | + goto fail; |
| 1003 | + } |
| 1004 | + } |
| 1005 | + } |
| 1006 | + |
| 1007 | + ret = av_dict_copy(&stg->metadata, metadata, 0); |
| 1008 | + if (ret < 0) |
| 1009 | + goto fail; |
| 1010 | + } |
| 1011 | + |
| 1012 | + ret = 0; |
| 1013 | +fail: |
| 1014 | + av_dict_free(&metadata); |
| 1015 | + |
| 1016 | + return ret; |
| 1017 | +} |
| 1018 | + |
| 839 | 1019 | static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
| 840 | 1020 | { |
| 841 | 1021 | AVStream *st; |
| @@ -1331,7 +1511,7 @@ static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st, · 489 unmodified lines |
| 1331 | 1511 | // If the stream is referenced by any sidx, limit the search |
| 1332 | 1512 | // to fragments that referenced this stream in the sidx |
| 1333 | 1513 | if (sc->has_sidx) { |
| 1334 | | − frag_stream_info = get_frag_stream_info(frag_index, index, dst_st->id); |
| 1514 | + frag_stream_info = get_frag_stream_info(frag_index, index, sc->id); |
| 1335 | 1515 | if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) |
| 1336 | 1516 | return frag_stream_info->sidx_pts; |
| 1337 | 1517 | if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE) |
| @@ -1342,9 +1522,11 @@ static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st, · 4 unmodified lines |
| 1342 | 1522 | for (i = 0; i < frag_index->item[index].nb_stream_info; i++) { |
| 1343 | 1523 | AVStream *frag_stream = NULL; |
| 1344 | 1524 | frag_stream_info = &frag_index->item[index].stream_info[i]; |
| 1345 | | − for (j = 0; j < s->nb_streams; j++) |
| 1346 | | − if (s->streams[j]->id == frag_stream_info->id) |
| 1525 | + for (j = 0; j < s->nb_streams; j++) { |
| 1526 | + MOVStreamContext *sc2 = s->streams[j]->priv_data; |
| 1527 | + if (sc2->id == frag_stream_info->id) |
| 1347 | 1528 | frag_stream = s->streams[j]; |
| 1529 | + } |
| 1348 | 1530 | if (!frag_stream) { |
| 1349 | 1531 | av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n"); |
| 1350 | 1532 | continue; |
| @@ -1410,12 +1592,13 @@ static int update_frag_index(MOVContext *c, int64_t offset) · 59 unmodified lines |
| 1410 | 1592 | |
| 1411 | 1593 | for (i = 0; i < c->fc->nb_streams; i++) { |
| 1412 | 1594 | // Avoid building frag index if streams lack track id. |
| 1413 | | − if (c->fc->streams[i]->id < 0) { |
| 1595 | + MOVStreamContext *sc = c->fc->streams[i]->priv_data; |
| 1596 | + if (sc->id < 0) { |
| 1414 | 1597 | av_free(frag_stream_info); |
| 1415 | 1598 | return AVERROR_INVALIDDATA; |
| 1416 | 1599 | } |
| 1417 | 1600 | |
| 1418 | | − frag_stream_info[i].id = c->fc->streams[i]->id; |
| 1601 | + frag_stream_info[i].id = sc->id; |
| 1419 | 1602 | frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE; |
| 1420 | 1603 | frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE; |
| 1421 | 1604 | frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE; |
| @@ -3210,7 +3393,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 1788 unmodified lines |
| 3210 | 3393 | "All samples in data stream index:id [%d:%d] have zero " |
| 3211 | 3394 | "duration, stream set to be discarded by default. Override " |
| 3212 | 3395 | "using AVStream->discard or -discard for ffmpeg command.\n", |
| 3213 | | − st->index, st->id); |
| 3396 | + st->index, sc->id); |
| 3214 | 3397 | st->discard = AVDISCARD_ALL; |
| 3215 | 3398 | } |
| 3216 | 3399 | sc->track_end = duration; |
| @@ -4590,6 +4773,50 @@ static void fix_timescale(MOVContext *c, MOVStreamContext *sc) · 1373 unmodified lines |
| 4590 | 4773 | } |
| 4591 | 4774 | } |
| 4592 | 4775 | |
| 4776 | +static int mov_update_iamf_streams(MOVContext *c, const AVStream *st) |
| 4777 | +{ |
| 4778 | + const MOVStreamContext *sc = st->priv_data; |
| 4779 | + const IAMFContext *iamf = &sc->iamf->iamf; |
| 4780 | + |
| 4781 | + for (int i = 0; i < iamf->nb_audio_elements; i++) { |
| 4782 | + const AVStreamGroup *stg = NULL; |
| 4783 | + |
| 4784 | + for (int j = 0; j < c->fc->nb_stream_groups; j++) |
| 4785 | + if (c->fc->stream_groups[j]->id == iamf->audio_elements[i]->audio_element_id) |
| 4786 | + stg = c->fc->stream_groups[j]; |
| 4787 | + av_assert0(stg); |
| 4788 | + |
| 4789 | + for (int j = 0; j < stg->nb_streams; j++) { |
| 4790 | + const FFStream *sti = cffstream(st); |
| 4791 | + AVStream *out = stg->streams[j]; |
| 4792 | + FFStream *out_sti = ffstream(stg->streams[j]); |
| 4793 | + |
| 4794 | + out->codecpar->bit_rate = 0; |
| 4795 | + |
| 4796 | + if (out == st) |
| 4797 | + continue; |
| 4798 | + |
| 4799 | + out->time_base = st->time_base; |
| 4800 | + out->start_time = st->start_time; |
| 4801 | + out->duration = st->duration; |
| 4802 | + out->nb_frames = st->nb_frames; |
| 4803 | + out->discard = st->discard; |
| 4804 | + |
| 4805 | + av_assert0(!out_sti->index_entries); |
| 4806 | + out_sti->index_entries = av_malloc(sti->index_entries_allocated_size); |
| 4807 | + if (!out_sti->index_entries) |
| 4808 | + return AVERROR(ENOMEM); |
| 4809 | + |
| 4810 | + out_sti->index_entries_allocated_size = sti->index_entries_allocated_size; |
| 4811 | + out_sti->nb_index_entries = sti->nb_index_entries; |
| 4812 | + out_sti->skip_samples = sti->skip_samples; |
| 4813 | + memcpy(out_sti->index_entries, sti->index_entries, sti->index_entries_allocated_size); |
| 4814 | + } |
| 4815 | + } |
| 4816 | + |
| 4817 | + return 0; |
| 4818 | +} |
| 4819 | + |
| 4593 | 4820 | static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
| 4594 | 4821 | { |
| 4595 | 4822 | AVStream *st; |
| @@ -4670,6 +4897,12 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 74 unmodified lines |
| 4670 | 4897 | |
| 4671 | 4898 | mov_build_index(c, st); |
| 4672 | 4899 | |
| 4900 | + if (sc->iamf) { |
| 4901 | + ret = mov_update_iamf_streams(c, st); |
| 4902 | + if (ret < 0) |
| 4903 | + return ret; |
| 4904 | + } |
| 4905 | + |
| 4673 | 4906 | if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { |
| 4674 | 4907 | MOVDref *dref = &sc->drefs[sc->dref_id - 1]; |
| 4675 | 4908 | if (c->enable_drefs) { |
| @@ -4902,6 +5135,7 @@ static int heif_add_stream(MOVContext *c, HEIFItem *item) · 226 unmodified lines |
| 4902 | 5135 | st->priv_data = sc; |
| 4903 | 5136 | st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; |
| 4904 | 5137 | st->codecpar->codec_id = mov_codec_id(st, item->type); |
| 5138 | + sc->id = st->id; |
| 4905 | 5139 | sc->ffindex = st->index; |
| 4906 | 5140 | c->trak_index = st->index; |
| 4907 | 5141 | st->avg_frame_rate.num = st->avg_frame_rate.den = 1; |
| @@ -5000,6 +5234,7 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 92 unmodified lines |
| 5000 | 5234 | avio_rb32(pb); /* modification time */ |
| 5001 | 5235 | } |
| 5002 | 5236 | st->id = (int)avio_rb32(pb); /* track id (NOT 0 !)*/ |
| 5237 | + sc->id = st->id; |
| 5003 | 5238 | avio_rb32(pb); /* reserved */ |
| 5004 | 5239 | |
| 5005 | 5240 | /* highlevel (considering edits) duration in movie timebase */ |
| @@ -5174,7 +5409,8 @@ static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 168 unmodified lines |
| 5174 | 5409 | int64_t base_media_decode_time; |
| 5175 | 5410 | |
| 5176 | 5411 | for (i = 0; i < c->fc->nb_streams; i++) { |
| 5177 | | − if (c->fc->streams[i]->id == frag->track_id) { |
| 5412 | + sc = c->fc->streams[i]->priv_data; |
| 5413 | + if (sc->id == frag->track_id) { |
| 5178 | 5414 | st = c->fc->streams[i]; |
| 5179 | 5415 | break; |
| 5180 | 5416 | } |
| @@ -5227,7 +5463,8 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 46 unmodified lines |
| 5227 | 5463 | } |
| 5228 | 5464 | |
| 5229 | 5465 | for (i = 0; i < c->fc->nb_streams; i++) { |
| 5230 | | − if (c->fc->streams[i]->id == frag->track_id) { |
| 5466 | + sc = c->fc->streams[i]->priv_data; |
| 5467 | + if (sc->id == frag->track_id) { |
| 5231 | 5468 | st = c->fc->streams[i]; |
| 5232 | 5469 | sti = ffstream(st); |
| 5233 | 5470 | break; |
| @@ -5530,7 +5767,8 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 296 unmodified lines |
| 5530 | 5767 | |
| 5531 | 5768 | track_id = avio_rb32(pb); // Reference ID |
| 5532 | 5769 | for (i = 0; i < c->fc->nb_streams; i++) { |
| 5533 | | − if (c->fc->streams[i]->id == track_id) { |
| 5770 | + sc = c->fc->streams[i]->priv_data; |
| 5771 | + if (sc->id == track_id) { |
| 5534 | 5772 | st = c->fc->streams[i]; |
| 5535 | 5773 | break; |
| 5536 | 5774 | } |
| @@ -6447,7 +6685,8 @@ static int get_current_encryption_info(MOVContext *c, MOVEncryptionIndex **encry · 910 unmodified lines |
| 6447 | 6685 | frag_stream_info = get_current_frag_stream_info(&c->frag_index); |
| 6448 | 6686 | if (frag_stream_info) { |
| 6449 | 6687 | for (i = 0; i < c->fc->nb_streams; i++) { |
| 6450 | | − if (c->fc->streams[i]->id == frag_stream_info->id) { |
| 6688 | + *sc = c->fc->streams[i]->priv_data; |
| 6689 | + if ((*sc)->id == frag_stream_info->id) { |
| 6451 | 6690 | st = c->fc->streams[i]; |
| 6452 | 6691 | break; |
| 6453 | 6692 | } |
| @@ -7391,7 +7630,7 @@ static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPa · 937 unmodified lines |
| 7391 | 7630 | AVEncryptionInfo *encrypted_sample; |
| 7392 | 7631 | int encrypted_index, ret; |
| 7393 | 7632 | |
| 7394 | | − frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, st->id); |
| 7633 | + frag_stream_info = get_frag_stream_info_from_pkt(&mov->frag_index, pkt, sc->id); |
| 7395 | 7634 | encrypted_index = current_index; |
| 7396 | 7635 | encryption_index = NULL; |
| 7397 | 7636 | if (frag_stream_info) { |
| @@ -8194,6 +8433,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { · 796 unmodified lines |
| 8194 | 8433 | { MKTAG('i','p','r','p'), mov_read_iprp }, |
| 8195 | 8434 | { MKTAG('i','i','n','f'), mov_read_iinf }, |
| 8196 | 8435 | { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */ |
| 8436 | +{ MKTAG('i','a','c','b'), mov_read_iacb }, |
| 8197 | 8437 | { 0, NULL } |
| 8198 | 8438 | }; |
| 8199 | 8439 | |
| @@ -8425,11 +8665,13 @@ static void mov_read_chapters(AVFormatContext *s) · 225 unmodified lines |
| 8425 | 8665 | AVStream *st = NULL; |
| 8426 | 8666 | FFStream *sti = NULL; |
| 8427 | 8667 | chapter_track = mov->chapter_tracks[j]; |
| 8428 | | − for (i = 0; i < s->nb_streams; i++) |
| 8429 | | − if (s->streams[i]->id == chapter_track) { |
| 8668 | + for (i = 0; i < s->nb_streams; i++) { |
| 8669 | + sc = mov->fc->streams[i]->priv_data; |
| 8670 | + if (sc->id == chapter_track) { |
| 8430 | 8671 | st = s->streams[i]; |
| 8431 | 8672 | break; |
| 8432 | 8673 | } |
| 8674 | + } |
| 8433 | 8675 | if (!st) { |
| 8434 | 8676 | av_log(s, AV_LOG_ERROR, "Referenced QT chapter track not found\n"); |
| 8435 | 8677 | continue; |
| @@ -8662,6 +8904,10 @@ static void mov_free_stream_context(AVFormatContext *s, AVStream *st) · 226 unmodified lines |
| 8662 | 8904 | av_freep(&sc->mastering); |
| 8663 | 8905 | av_freep(&sc->coll); |
| 8664 | 8906 | av_freep(&sc->ambient); |
| 8907 | + |
| 8908 | + if (sc->iamf) |
| 8909 | + ff_iamf_read_deinit(sc->iamf); |
| 8910 | + av_freep(&sc->iamf); |
| 8665 | 8911 | } |
| 8666 | 8912 | |
| 8667 | 8913 | static int mov_read_close(AVFormatContext *s) |
| @@ -8916,9 +9162,11 @@ static int mov_read_header(AVFormatContext *s) · 248 unmodified lines |
| 8916 | 9162 | AVDictionaryEntry *tcr; |
| 8917 | 9163 | int tmcd_st_id = -1; |
| 8918 | 9164 | |
| 8919 | | − for (j = 0; j < s->nb_streams; j++) |
| 8920 | | − if (s->streams[j]->id == sc->timecode_track) |
| 9165 | + for (j = 0; j < s->nb_streams; j++) { |
| 9166 | + MOVStreamContext *sc2 = s->streams[j]->priv_data; |
| 9167 | + if (sc2->id == sc->timecode_track) |
| 8921 | 9168 | tmcd_st_id = j; |
| 9169 | + } |
| 8922 | 9170 | |
| 8923 | 9171 | if (tmcd_st_id < 0 || tmcd_st_id == i) |
| 8924 | 9172 | continue; |
| @@ -9298,7 +9546,29 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) · 373 unmodified lines |
| 9298 | 9546 | |
| 9299 | 9547 | if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8) |
| 9300 | 9548 | ret = get_eia608_packet(sc->pb, pkt, sample->size); |
| 9301 | | − else |
| 9549 | + else if (sc->iamf) { |
| 9550 | + int64_t pts, dts, pos, duration; |
| 9551 | + int flags, size = sample->size; |
| 9552 | + ret = mov_finalize_packet(s, st, sample, current_index, pkt); |
| 9553 | + pts = pkt->pts; dts = pkt->dts; |
| 9554 | + pos = pkt->pos; flags = pkt->flags; |
| 9555 | + duration = pkt->duration; |
| 9556 | + while (!ret && size > 0) { |
| 9557 | + ret = ff_iamf_read_packet(s, sc->iamf, sc->pb, size, pkt); |
| 9558 | + if (ret < 0) { |
| 9559 | + if (should_retry(sc->pb, ret)) |
| 9560 | + mov_current_sample_dec(sc); |
| 9561 | + return ret; |
| 9562 | + } |
| 9563 | + size -= ret; |
| 9564 | + pkt->pts = pts; pkt->dts = dts; |
| 9565 | + pkt->pos = pos; pkt->flags |= flags; |
| 9566 | + pkt->duration = duration; |
| 9567 | + ret = ff_buffer_packet(s, pkt); |
| 9568 | + } |
| 9569 | + if (!ret) |
| 9570 | + return FFERROR_REDO; |
| 9571 | + } else |
| 9302 | 9572 | ret = av_get_packet(sc->pb, pkt, sample->size); |
| 9303 | 9573 | if (ret < 0) { |
| 9304 | 9574 | if (should_retry(sc->pb, ret)) { |