Re: [FFmpeg-devel] [PATCH] libavformat/mov: fix multiple stsd handling of files with edit list, fix #6584
2017-08-12 16:42 GMT+08:00 : > From: Jiejun Zhang > > When an edit list exists in a MOV file, counting by stscs no longer > works because stscs' order is different from the actual timeline. This > commit adds stsd-change markers to the actual timeline and changes stsd > according to these markers. > --- > libavformat/isom.h | 14 -- > libavformat/mov.c | 122 > + > 2 files changed, 105 insertions(+), 31 deletions(-) > > diff --git a/libavformat/isom.h b/libavformat/isom.h > index ff009b0896..51cd333a8c 100644 > --- a/libavformat/isom.h > +++ b/libavformat/isom.h > @@ -127,6 +127,11 @@ typedef struct MOVIndexRange { > int64_t end; > } MOVIndexRange; > > +typedef struct MOVStsdChangeEntry { > +int64_t sample_index; ///< stsd changes at this sample index > +int stsd_id; ///< stsd changes to stsd_id > +} MOVStsdChangeEntry; > + > typedef struct MOVStreamContext { > AVIOContext *pb; > int pb_is_copied; > @@ -140,16 +145,17 @@ typedef struct MOVStreamContext { > MOVStts *ctts_data; > unsigned int stsc_count; > MOVStsc *stsc_data; > -int stsc_index; > -int stsc_sample; > +MOVStsdChangeEntry *stsd_change_data; > +int stsd_change_count; > +int stsd_change_index; > unsigned int stps_count; > unsigned *stps_data; ///< partial sync sample for mpeg-2 open gop > MOVElst *elst_data; > unsigned int elst_count; > int ctts_index; > int ctts_sample; > -unsigned int sample_size; ///< may contain value calculated from stsd or > value from stsz atom > -unsigned int stsz_sample_size; ///< always contains sample size from > stsz atom > +unsigned int sample_size; ///< may contain value calculated from stsd or > value from stsz atom unsigned > +int stsz_sample_size; ///< always contains sample size from stsz atom > unsigned int sample_count; > int *sample_sizes; > int keyframe_absent; > diff --git a/libavformat/mov.c b/libavformat/mov.c > index 63f84be782..f3239047c8 100644 > --- a/libavformat/mov.c > +++ b/libavformat/mov.c > @@ -2923,6 +2923,35 @@ static int64_t add_index_entry(AVStream *st, int64_t > pos, int64_t timestamp, > return index; > } > > +static int add_stsd_change_entry(MOVStreamContext *msc, int64_t > sample_index, int stsd_id, > +unsigned int* allocated_size) > +{ > +MOVStsdChangeEntry *entries; > +const size_t min_size_needed = (msc->stsd_change_count + 1) * > sizeof(MOVStsdChangeEntry); > + > +const size_t requested_size = > +min_size_needed > *allocated_size ? > +FFMAX(min_size_needed, 2 * (*allocated_size)) : > +min_size_needed; > + > +if ((unsigned)msc->stsd_change_count + 1 >= UINT_MAX / > sizeof(MOVStsdChangeEntry)) > +return -1; > + > +entries = av_fast_realloc(msc->stsd_change_data, > + allocated_size, > + requested_size); > + > +if (!entries) > +return -1; > + > +msc->stsd_change_data = entries; > +entries[msc->stsd_change_count].sample_index = sample_index; > +entries[msc->stsd_change_count].stsd_id = stsd_id; > +msc->stsd_change_count++; > + > +return 0; > +} > + > /** > * Rewrite timestamps of index entries in the range [end_index - > frame_duration_buffer_size, end_index) > * by subtracting end_ts successively by the amounts given in > frame_duration_buffer. > @@ -3055,6 +3084,8 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) > int num_discarded_begin = 0; > int first_non_zero_audio_edit = -1; > int packet_skip_samples = 0; > +int stsc_index = 0; > +int stsc_sample = 0; > MOVIndexRange *current_index_range; > int i; > > @@ -3091,6 +3122,11 @@ static void mov_fix_index(MOVContext *mov, AVStream > *st) > > start_dts = edit_list_dts_entry_end; > > +msc->last_stsd_index = -1; > +unsigned int stsd_change_data_allocated_size = 0; > +msc->stsd_change_data = NULL; > +msc->stsd_change_count = 0; > + > while (get_edit_list_entry(mov, msc, edit_list_index, > &edit_list_media_time, > &edit_list_duration, mov->time_scale)) { > av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list > %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n", > @@ -3153,6 +3189,20 @@ static void mov_fix_index(MOVContext *mov, AVStream > *st) > } > current = e_old + index; > > +// adjust stsd index > +int time_sample = 0; > +for (int i = 0; i < msc->stsc_count; i++) { the i redefined, first define at the top of the function mov_list_index > +int next = time_sample + mov_get_stsc_samples(msc, i); > +if (next > index) { > +stsc_index = i; > +stsc_sample = index - time_sample; > +break; > +} > +time_sample = next; > +} > + > +
[FFmpeg-devel] [PATCH] libavformat/mov: fix multiple stsd handling of files with edit list, fix #6584
From: Jiejun Zhang When an edit list exists in a MOV file, counting by stscs no longer works because stscs' order is different from the actual timeline. This commit adds stsd-change markers to the actual timeline and changes stsd according to these markers. --- libavformat/isom.h | 14 -- libavformat/mov.c | 122 + 2 files changed, 105 insertions(+), 31 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index ff009b0896..51cd333a8c 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -127,6 +127,11 @@ typedef struct MOVIndexRange { int64_t end; } MOVIndexRange; +typedef struct MOVStsdChangeEntry { +int64_t sample_index; ///< stsd changes at this sample index +int stsd_id; ///< stsd changes to stsd_id +} MOVStsdChangeEntry; + typedef struct MOVStreamContext { AVIOContext *pb; int pb_is_copied; @@ -140,16 +145,17 @@ typedef struct MOVStreamContext { MOVStts *ctts_data; unsigned int stsc_count; MOVStsc *stsc_data; -int stsc_index; -int stsc_sample; +MOVStsdChangeEntry *stsd_change_data; +int stsd_change_count; +int stsd_change_index; unsigned int stps_count; unsigned *stps_data; ///< partial sync sample for mpeg-2 open gop MOVElst *elst_data; unsigned int elst_count; int ctts_index; int ctts_sample; -unsigned int sample_size; ///< may contain value calculated from stsd or value from stsz atom -unsigned int stsz_sample_size; ///< always contains sample size from stsz atom +unsigned int sample_size; ///< may contain value calculated from stsd or value from stsz atom unsigned +int stsz_sample_size; ///< always contains sample size from stsz atom unsigned int sample_count; int *sample_sizes; int keyframe_absent; diff --git a/libavformat/mov.c b/libavformat/mov.c index 63f84be782..f3239047c8 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2923,6 +2923,35 @@ static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, return index; } +static int add_stsd_change_entry(MOVStreamContext *msc, int64_t sample_index, int stsd_id, +unsigned int* allocated_size) +{ +MOVStsdChangeEntry *entries; +const size_t min_size_needed = (msc->stsd_change_count + 1) * sizeof(MOVStsdChangeEntry); + +const size_t requested_size = +min_size_needed > *allocated_size ? +FFMAX(min_size_needed, 2 * (*allocated_size)) : +min_size_needed; + +if ((unsigned)msc->stsd_change_count + 1 >= UINT_MAX / sizeof(MOVStsdChangeEntry)) +return -1; + +entries = av_fast_realloc(msc->stsd_change_data, + allocated_size, + requested_size); + +if (!entries) +return -1; + +msc->stsd_change_data = entries; +entries[msc->stsd_change_count].sample_index = sample_index; +entries[msc->stsd_change_count].stsd_id = stsd_id; +msc->stsd_change_count++; + +return 0; +} + /** * Rewrite timestamps of index entries in the range [end_index - frame_duration_buffer_size, end_index) * by subtracting end_ts successively by the amounts given in frame_duration_buffer. @@ -3055,6 +3084,8 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) int num_discarded_begin = 0; int first_non_zero_audio_edit = -1; int packet_skip_samples = 0; +int stsc_index = 0; +int stsc_sample = 0; MOVIndexRange *current_index_range; int i; @@ -3091,6 +3122,11 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) start_dts = edit_list_dts_entry_end; +msc->last_stsd_index = -1; +unsigned int stsd_change_data_allocated_size = 0; +msc->stsd_change_data = NULL; +msc->stsd_change_count = 0; + while (get_edit_list_entry(mov, msc, edit_list_index, &edit_list_media_time, &edit_list_duration, mov->time_scale)) { av_log(mov->fc, AV_LOG_DEBUG, "Processing st: %d, edit list %"PRId64" - media time: %"PRId64", duration: %"PRId64"\n", @@ -3153,6 +3189,20 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) } current = e_old + index; +// adjust stsd index +int time_sample = 0; +for (int i = 0; i < msc->stsc_count; i++) { +int next = time_sample + mov_get_stsc_samples(msc, i); +if (next > index) { +stsc_index = i; +stsc_sample = index - time_sample; +break; +} +time_sample = next; +} + +av_log(mov->fc, AV_LOG_INFO, "stream %d, adjusted stsc_index: %d, stsc_sample: %d\n", st->index, stsc_index, stsc_sample); + ctts_index_old = 0; ctts_sample_old = 0; @@ -3265,12 +3315,35 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) } } -if (add_index_entry(st, current->pos, edit_list