Message ID | 20240814075908.92916-2-marc-antoine.arnaud@luminvent.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel,1/2] avformat/mxf: start to add mxf_inspect_mode and skip RIP if needed sponsored by nxtedition | expand |
Context | Check | Description |
---|---|---|
yinshiyou/make_loongarch64 | success | Make finished |
yinshiyou/make_fate_loongarch64 | success | Make fate finished |
ons 2024-08-14 klockan 09:59 +0200 skrev Marc-Antoine Arnaud: > sponsored by nxtedition > --- > libavformat/mxfdec.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 56 insertions(+) > > diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c > index df958819300..83f9e5fc9e0 100644 > --- a/libavformat/mxfdec.c > +++ b/libavformat/mxfdec.c > @@ -2063,6 +2063,52 @@ static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_ta > return 0; > } > > +static int mxf_validate_coherent_index_tables(MXFContext *mxf, int *is_coherent) { > + int i, j, ret, nb_sorted_segments = 0; > + MXFIndexTable *index_tables; > + int nb_index_tables = 0; > + int coherent_index_tables = 1; > + MXFIndexTableSegment **sorted_segments = NULL; > + > + ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments); Should probably bail out here if ret != 0. It seems the intent is to allow the caller to detect that there has been zero index segments so far > + > + index_tables = av_calloc(nb_index_tables, sizeof(MXFIndexTable)); > + if (!index_tables) { > + av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n"); > + av_free(sorted_segments); > + return AVERROR(ENOMEM); > + } > + > + /* distribute sorted segments to index tables */ > + for (i = j = 0; i < nb_sorted_segments; i++) { > + if (i != 0 && sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid) { > + /* next IndexSID */ > + j++; > + } > + > + index_tables[j].nb_segments++; > + } This is copy-pasted from mxf_compute_index_tables. Consider maybe splitting this part out into a common function. > + > + for (i = j = 0; j < nb_index_tables; i += index_tables[j++].nb_segments) { > + if (sorted_segments[i]->index_start_position) { > + av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i starts at EditUnit %"PRId64" - seeking may not work as expected\n", > + sorted_segments[i]->index_sid, sorted_segments[i]->index_start_position); > + coherent_index_tables = 0; > + } > + } This looks like it just checks for index tables that have just one segment. From the name of the function I'd have guessed that it looks for contiguous segments that cover the entire duration of the track. Doing so would be a good idea - then we know to stop even if we're parsing the file backwards Also you could break as soon as you set coherent_index_tables = 0 /Tomas
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index df958819300..83f9e5fc9e0 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -2063,6 +2063,52 @@ static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_ta return 0; } +static int mxf_validate_coherent_index_tables(MXFContext *mxf, int *is_coherent) { + int i, j, ret, nb_sorted_segments = 0; + MXFIndexTable *index_tables; + int nb_index_tables = 0; + int coherent_index_tables = 1; + MXFIndexTableSegment **sorted_segments = NULL; + + ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments); + + index_tables = av_calloc(nb_index_tables, sizeof(MXFIndexTable)); + if (!index_tables) { + av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n"); + av_free(sorted_segments); + return AVERROR(ENOMEM); + } + + /* distribute sorted segments to index tables */ + for (i = j = 0; i < nb_sorted_segments; i++) { + if (i != 0 && sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid) { + /* next IndexSID */ + j++; + } + + index_tables[j].nb_segments++; + } + + for (i = j = 0; j < nb_index_tables; i += index_tables[j++].nb_segments) { + if (sorted_segments[i]->index_start_position) { + av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i starts at EditUnit %"PRId64" - seeking may not work as expected\n", + sorted_segments[i]->index_sid, sorted_segments[i]->index_start_position); + coherent_index_tables = 0; + } + } + + av_free(sorted_segments); + + if (ret == 0 && coherent_index_tables) { + *is_coherent = 1; + } else { + *is_coherent = 0; + } + + return 0; +} + + /** * Sorts and collects index table segments into index tables. * Also computes PTSes if possible. @@ -3752,6 +3798,16 @@ static int mxf_read_header(AVFormatContext *s) if (!essence_offset) essence_offset = klv.offset; + if (mxf->mxf_inspect_mode == 1) { + int ret_local, coherent_index_tables; + ret_local = mxf_validate_coherent_index_tables(mxf, &coherent_index_tables); + + // Break only if index table is coherent + if (ret_local == 0 && coherent_index_tables == 1) { + break; + } + } + /* seek to footer, previous partition or stop */ if (mxf_parse_handle_essence(mxf) <= 0) break;