Should reduce memory usage as well as remove code duplication.
Showing the changes to libavformat (2 of 2 files). Show all
Unified · Split
| @@ -54,6 +54,12 @@ struct AVAESCTR; · 53 unmodified lines | |||
| 54 | * Here we just use what is needed to read the chunks | 54 | * Here we just use what is needed to read the chunks |
| 55 | */ | 55 | */ |
| 56 | 56 | ||
| 57 | typedef struct MOVTimeToSample { | ||
| 58 | unsigned int count; | ||
| 59 | unsigned int duration; | ||
| 60 | int offset; | ||
| 61 | } MOVTimeToSample; | ||
| 62 | |||
| 57 | typedef struct MOVStts { | 63 | typedef struct MOVStts { |
| 58 | unsigned int count; | 64 | unsigned int count; |
| 59 | unsigned int duration; | 65 | unsigned int duration; |
| @@ -173,6 +179,9 @@ typedef struct MOVStreamContext { · 113 unmodified lines | |||
| 173 | int next_chunk; | 179 | int next_chunk; |
| 174 | unsigned int chunk_count; | 180 | unsigned int chunk_count; |
| 175 | int64_t *chunk_offsets; | 181 | int64_t *chunk_offsets; |
| 182 | unsigned int tts_count; | ||
| 183 | unsigned int tts_allocated_size; | ||
| 184 | MOVTimeToSample *tts_data; | ||
| 176 | unsigned int stts_count; | 185 | unsigned int stts_count; |
| 177 | unsigned int stts_allocated_size; | 186 | unsigned int stts_allocated_size; |
| 178 | MOVStts *stts_data; | 187 | MOVStts *stts_data; |
| @@ -189,10 +198,8 @@ typedef struct MOVStreamContext { · 10 unmodified lines | |||
| 189 | unsigned *stps_data; ///< partial sync sample for mpeg-2 open gop | 198 | unsigned *stps_data; ///< partial sync sample for mpeg-2 open gop |
| 190 | MOVElst *elst_data; | 199 | MOVElst *elst_data; |
| 191 | unsigned int elst_count; | 200 | unsigned int elst_count; |
| 192 | int stts_index; | 201 | int tts_index; |
| 193 | int stts_sample; | 202 | int tts_sample; |
| 194 | int ctts_index; | ||
| 195 | int ctts_sample; | ||
| 196 | unsigned int sample_size; ///< may contain value calculated from stsd or value from stsz atom | 203 | unsigned int sample_size; ///< may contain value calculated from stsd or value from stsz atom |
| 197 | unsigned int stsz_sample_size; ///< always contains sample size from stsz atom | 204 | unsigned int stsz_sample_size; ///< always contains sample size from stsz atom |
| 198 | unsigned int sample_count; | 205 | unsigned int sample_count; |
| @@ -87,8 +87,6 @@ typedef struct MOVParseTableEntry { · 86 unmodified lines | |||
| 87 | static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom); | 87 | static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom); |
| 88 | static int mov_read_mfra(MOVContext *c, AVIOContext *f); | 88 | static int mov_read_mfra(MOVContext *c, AVIOContext *f); |
| 89 | static void mov_free_stream_context(AVFormatContext *s, AVStream *st); | 89 | static void mov_free_stream_context(AVFormatContext *s, AVStream *st); |
| 90 | static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, | ||
| 91 | int count, int duration); | ||
| 92 | 90 | ||
| 93 | static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb, | 91 | static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb, |
| 94 | unsigned len, const char *key) | 92 | unsigned len, const char *key) |
| @@ -3666,6 +3664,12 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 3571 unmodified lines | |||
| 3666 | return AVERROR(ENOMEM); | 3664 | return AVERROR(ENOMEM); |
| 3667 | 3665 | ||
| 3668 | for (i = 0; i < entries && !pb->eof_reached; i++) { | 3666 | for (i = 0; i < entries && !pb->eof_reached; i++) { |
| 3667 | MOVCtts *ctts_data; | ||
| 3668 | const size_t min_size_needed = (ctts_count + 1) * sizeof(MOVCtts); | ||
| 3669 | const size_t requested_size = | ||
| 3670 | min_size_needed > sc->ctts_allocated_size ? | ||
| 3671 | FFMAX(min_size_needed, 2 * sc->ctts_allocated_size) : | ||
| 3672 | min_size_needed; | ||
| 3669 | int count = avio_rb32(pb); | 3673 | int count = avio_rb32(pb); |
| 3670 | int duration = avio_rb32(pb); | 3674 | int duration = avio_rb32(pb); |
| 3671 | 3675 | ||
| @@ -3676,8 +3680,19 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 4 unmodified lines | |||
| 3676 | continue; | 3680 | continue; |
| 3677 | } | 3681 | } |
| 3678 | 3682 | ||
| 3679 | add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size, | 3683 | if (ctts_count >= UINT_MAX / sizeof(MOVCtts) - 1) |
| 3680 | count, duration); | 3684 | return AVERROR(ENOMEM); |
| 3685 | |||
| 3686 | ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size); | ||
| 3687 | |||
| 3688 | if (!ctts_data) | ||
| 3689 | return AVERROR(ENOMEM); | ||
| 3690 | |||
| 3691 | sc->ctts_data = ctts_data; | ||
| 3692 | |||
| 3693 | ctts_data[ctts_count].count = count; | ||
| 3694 | ctts_data[ctts_count].offset = duration; | ||
| 3695 | ctts_count++; | ||
| 3681 | 3696 | ||
| 3682 | av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n", | 3697 | av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n", |
| 3683 | count, duration); | 3698 | count, duration); |
| @@ -3871,24 +3886,19 @@ static int get_edit_list_entry(MOVContext *mov, · 187 unmodified lines | |||
| 3871 | static int find_prev_closest_index(AVStream *st, | 3886 | static int find_prev_closest_index(AVStream *st, |
| 3872 | AVIndexEntry *e_old, | 3887 | AVIndexEntry *e_old, |
| 3873 | int nb_old, | 3888 | int nb_old, |
| 3874 | MOVStts* stts_data, | 3889 | MOVTimeToSample *tts_data, |
| 3875 | int64_t stts_count, | 3890 | int64_t tts_count, |
| 3876 | MOVCtts* ctts_data, | ||
| 3877 | int64_t ctts_count, | ||
| 3878 | int64_t timestamp_pts, | 3891 | int64_t timestamp_pts, |
| 3879 | int flag, | 3892 | int flag, |
| 3880 | int64_t* index, | 3893 | int64_t* index, |
| 3881 | int64_t* stts_index, | 3894 | int64_t* tts_index, |
| 3882 | int64_t* stts_sample, | 3895 | int64_t* tts_sample) |
| 3883 | int64_t* ctts_index, | ||
| 3884 | int64_t* ctts_sample) | ||
| 3885 | { | 3896 | { |
| 3886 | MOVStreamContext *msc = st->priv_data; | 3897 | MOVStreamContext *msc = st->priv_data; |
| 3887 | FFStream *const sti = ffstream(st); | 3898 | FFStream *const sti = ffstream(st); |
| 3888 | AVIndexEntry *e_keep = sti->index_entries; | 3899 | AVIndexEntry *e_keep = sti->index_entries; |
| 3889 | int nb_keep = sti->nb_index_entries; | 3900 | int nb_keep = sti->nb_index_entries; |
| 3890 | int64_t i = 0; | 3901 | int64_t i = 0; |
| 3891 | int64_t index_ctts_count; | ||
| 3892 | 3902 | ||
| 3893 | av_assert0(index); | 3903 | av_assert0(index); |
| 3894 | 3904 | ||
| @@ -3916,64 +3926,38 @@ static int find_prev_closest_index(AVStream *st, · 21 unmodified lines | |||
| 3916 | 3926 | ||
| 3917 | // If we have CTTS then refine the search, by searching backwards over PTS | 3927 | // If we have CTTS then refine the search, by searching backwards over PTS |
| 3918 | // computed by adding corresponding CTTS durations to index timestamps. | 3928 | // computed by adding corresponding CTTS durations to index timestamps. |
| 3919 | if (ctts_data && *index >= 0) { | 3929 | if (msc->ctts_count && *index >= 0) { |
| 3920 | av_assert0(ctts_index); | 3930 | av_assert0(tts_index); |
| 3921 | av_assert0(ctts_sample); | 3931 | av_assert0(tts_sample); |
| 3922 | // Find out the ctts_index for the found frame. | 3932 | // Find out the ctts_index for the found frame. |
| 3923 | *ctts_index = 0; | 3933 | *tts_index = 0; |
| 3924 | *ctts_sample = 0; | 3934 | *tts_sample = 0; |
| 3925 | 3935 | for (int64_t index_tts_count = 0; index_tts_count < *index; index_tts_count++) { | |
| 3926 | if (stts_data) { | 3936 | if (*tts_index < tts_count) { |
| 3927 | av_assert0(stts_index); | 3937 | (*tts_sample)++; |
| 3928 | av_assert0(stts_sample); | 3938 | if (tts_data[*tts_index].count == *tts_sample) { |
| 3929 | 3939 | (*tts_index)++; | |
| 3930 | *stts_index = 0; | 3940 | *tts_sample = 0; |
| 3931 | *stts_sample = 0; | ||
| 3932 | } | ||
| 3933 | |||
| 3934 | for (index_ctts_count = 0; index_ctts_count < *index; index_ctts_count++) { | ||
| 3935 | if (*ctts_index < ctts_count) { | ||
| 3936 | (*ctts_sample)++; | ||
| 3937 | if (ctts_data[*ctts_index].count == *ctts_sample) { | ||
| 3938 | (*ctts_index)++; | ||
| 3939 | *ctts_sample = 0; | ||
| 3940 | } | ||
| 3941 | } | ||
| 3942 | if (stts_data && *stts_index < stts_count) { | ||
| 3943 | (*stts_sample)++; | ||
| 3944 | if (stts_data[*stts_index].count == *stts_sample) { | ||
| 3945 | (*stts_index)++; | ||
| 3946 | *stts_sample = 0; | ||
| 3947 | } | 3941 | } |
| 3948 | } | 3942 | } |
| 3949 | } | 3943 | } |
| 3950 | 3944 | ||
| 3951 | while (*index >= 0 && (*ctts_index) >= 0 && (*ctts_index) < ctts_count) { | 3945 | while (*index >= 0 && (*tts_index) >= 0 && (*tts_index) < tts_count) { |
| 3952 | // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly). | 3946 | // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly). |
| 3953 | // No need to add dts_shift to the timestamp here becase timestamp_pts has already been | 3947 | // No need to add dts_shift to the timestamp here becase timestamp_pts has already been |
| 3954 | // compensated by dts_shift above. | 3948 | // compensated by dts_shift above. |
| 3955 | if ((e_old[*index].timestamp + ctts_data[*ctts_index].offset) <= timestamp_pts && | 3949 | if ((e_old[*index].timestamp + tts_data[*tts_index].offset) <= timestamp_pts && |
| 3956 | (e_old[*index].flags & AVINDEX_KEYFRAME)) { | 3950 | (e_old[*index].flags & AVINDEX_KEYFRAME)) { |
| 3957 | break; | 3951 | break; |
| 3958 | } | 3952 | } |
| 3959 | 3953 | ||
| 3960 | (*index)--; | 3954 | (*index)--; |
| 3961 | if (*ctts_sample == 0) { | 3955 | if (*tts_sample == 0) { |
| 3962 | (*ctts_index)--; | 3956 | (*tts_index)--; |
| 3963 | if (*ctts_index >= 0) | 3957 | if (*tts_index >= 0) |
| 3964 | *ctts_sample = ctts_data[*ctts_index].count - 1; | 3958 | *tts_sample = tts_data[*tts_index].count - 1; |
| 3965 | } else { | 3959 | } else { |
| 3966 | (*ctts_sample)--; | 3960 | (*tts_sample)--; |
| 3967 | } | ||
| 3968 | if (stts_data) { | ||
| 3969 | if (*stts_sample == 0) { | ||
| 3970 | (*stts_index)--; | ||
| 3971 | if (*stts_index >= 0) { | ||
| 3972 | *stts_sample = stts_data[*stts_index].count - 1; | ||
| 3973 | } | ||
| 3974 | } else { | ||
| 3975 | (*stts_sample)--; | ||
| 3976 | } | ||
| 3977 | } | 3961 | } |
| 3978 | } | 3962 | } |
| 3979 | } | 3963 | } |
| @@ -4048,62 +4032,32 @@ static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ · 68 unmodified lines | |||
| 4048 | } | 4032 | } |
| 4049 | } | 4033 | } |
| 4050 | 4034 | ||
| 4051 | static int64_t add_stts_entry(MOVStts** stts_data, unsigned int* stts_count, unsigned int* allocated_size, | 4035 | static int add_tts_entry(MOVTimeToSample **tts_data, unsigned int *tts_count, unsigned int *allocated_size, |
| 4052 | int count, int duration) | 4036 | int count, int offset, unsigned int duration) |
| 4053 | { | ||
| 4054 | MOVStts *stts_buf_new; | ||
| 4055 | const size_t min_size_needed = (*stts_count + 1) * sizeof(MOVStts); | ||
| 4056 | const size_t requested_size = | ||
| 4057 | min_size_needed > *allocated_size ? | ||
| 4058 | FFMAX(min_size_needed, 2 * (*allocated_size)) : | ||
| 4059 | min_size_needed; | ||
| 4060 | |||
| 4061 | if ((unsigned)(*stts_count) >= UINT_MAX / sizeof(MOVStts) - 1) | ||
| 4062 | return -1; | ||
| 4063 | |||
| 4064 | stts_buf_new = av_fast_realloc(*stts_data, allocated_size, requested_size); | ||
| 4065 | |||
| 4066 | if (!stts_buf_new) | ||
| 4067 | return -1; | ||
| 4068 | |||
| 4069 | *stts_data = stts_buf_new; | ||
| 4070 | |||
| 4071 | stts_buf_new[*stts_count].count = count; | ||
| 4072 | stts_buf_new[*stts_count].duration = duration; | ||
| 4073 | |||
| 4074 | *stts_count = (*stts_count) + 1; | ||
| 4075 | return *stts_count; | ||
| 4076 | } | ||
| 4077 | |||
| 4078 | /** | ||
| 4079 | * Append a new ctts entry to ctts_data. | ||
| 4080 | * Returns the new ctts_count if successful, else returns -1. | ||
| 4081 | */ | ||
| 4082 | static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, | ||
| 4083 | int count, int offset) | ||
| 4084 | { | 4037 | { |
| 4085 | MOVCtts *ctts_buf_new; | 4038 | MOVTimeToSample *tts_buf_new; |
| 4086 | const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVCtts); | 4039 | const size_t min_size_needed = (*tts_count + 1) * sizeof(MOVTimeToSample); |
| 4087 | const size_t requested_size = | 4040 | const size_t requested_size = |
| 4088 | min_size_needed > *allocated_size ? | 4041 | min_size_needed > *allocated_size ? |
| 4089 | FFMAX(min_size_needed, 2 * (*allocated_size)) : | 4042 | FFMAX(min_size_needed, 2 * (*allocated_size)) : |
| 4090 | min_size_needed; | 4043 | min_size_needed; |
| 4091 | 4044 | ||
| 4092 | if ((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVCtts) - 1) | 4045 | if ((unsigned)(*tts_count) >= UINT_MAX / sizeof(MOVTimeToSample) - 1) |
| 4093 | return -1; | 4046 | return -1; |
| 4094 | 4047 | ||
| 4095 | ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size); | 4048 | tts_buf_new = av_fast_realloc(*tts_data, allocated_size, requested_size); |
| 4096 | 4049 | ||
| 4097 | if (!ctts_buf_new) | 4050 | if (!tts_buf_new) |
| 4098 | return -1; | 4051 | return -1; |
| 4099 | 4052 | ||
| 4100 | *ctts_data = ctts_buf_new; | 4053 | *tts_data = tts_buf_new; |
| 4101 | 4054 | ||
| 4102 | ctts_buf_new[*ctts_count].count = count; | 4055 | tts_buf_new[*tts_count].count = count; |
| 4103 | ctts_buf_new[*ctts_count].offset = offset; | 4056 | tts_buf_new[*tts_count].offset = offset; |
| 4057 | tts_buf_new[*tts_count].duration = duration; | ||
| 4104 | 4058 | ||
| 4105 | *ctts_count = (*ctts_count) + 1; | 4059 | *tts_count = (*tts_count) + 1; |
| 4106 | return *ctts_count; | 4060 | return 0; |
| 4107 | } | 4061 | } |
| 4108 | 4062 | ||
| 4109 | #define MAX_REORDER_DELAY 16 | 4063 | #define MAX_REORDER_DELAY 16 |
| @@ -4120,17 +4074,17 @@ static void mov_estimate_video_delay(MOVContext *c, AVStream* st) · 10 unmodified lines | |||
| 4120 | for (j = 0; j < MAX_REORDER_DELAY + 1; j++) | 4074 | for (j = 0; j < MAX_REORDER_DELAY + 1; j++) |
| 4121 | pts_buf[j] = INT64_MIN; | 4075 | pts_buf[j] = INT64_MIN; |
| 4122 | 4076 | ||
| 4123 | if (st->codecpar->video_delay <= 0 && msc->ctts_data && | 4077 | if (st->codecpar->video_delay <= 0 && msc->ctts_count && |
| 4124 | st->codecpar->codec_id == AV_CODEC_ID_H264) { | 4078 | st->codecpar->codec_id == AV_CODEC_ID_H264) { |
| 4125 | st->codecpar->video_delay = 0; | 4079 | st->codecpar->video_delay = 0; |
| 4126 | for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) { | 4080 | for (int ind = 0; ind < sti->nb_index_entries && ctts_ind < msc->tts_count; ++ind) { |
| 4127 | // Point j to the last elem of the buffer and insert the current pts there. | 4081 | // Point j to the last elem of the buffer and insert the current pts there. |
| 4128 | j = buf_start; | 4082 | j = buf_start; |
| 4129 | buf_start = (buf_start + 1); | 4083 | buf_start = (buf_start + 1); |
| 4130 | if (buf_start == MAX_REORDER_DELAY + 1) | 4084 | if (buf_start == MAX_REORDER_DELAY + 1) |
| 4131 | buf_start = 0; | 4085 | buf_start = 0; |
| 4132 | 4086 | ||
| 4133 | pts_buf[j] = sti->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].offset; | 4087 | pts_buf[j] = sti->index_entries[ind].timestamp + msc->tts_data[ctts_ind].offset; |
| 4134 | 4088 | ||
| 4135 | // The timestamps that are already in the sorted buffer, and are greater than the | 4089 | // The timestamps that are already in the sorted buffer, and are greater than the |
| 4136 | // current pts, are exactly the timestamps that need to be buffered to output PTS | 4090 | // current pts, are exactly the timestamps that need to be buffered to output PTS |
| @@ -4153,7 +4107,7 @@ static void mov_estimate_video_delay(MOVContext *c, AVStream* st) · 16 unmodified lines | |||
| 4153 | st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps); | 4107 | st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps); |
| 4154 | 4108 | ||
| 4155 | ctts_sample++; | 4109 | ctts_sample++; |
| 4156 | if (ctts_sample == msc->ctts_data[ctts_ind].count) { | 4110 | if (ctts_sample == msc->tts_data[ctts_ind].count) { |
| 4157 | ctts_ind++; | 4111 | ctts_ind++; |
| 4158 | ctts_sample = 0; | 4112 | ctts_sample = 0; |
| 4159 | } | 4113 | } |
| @@ -4223,21 +4177,16 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) · 63 unmodified lines | |||
| 4223 | int nb_old = sti->nb_index_entries; | 4177 | int nb_old = sti->nb_index_entries; |
| 4224 | const AVIndexEntry *e_old_end = e_old + nb_old; | 4178 | const AVIndexEntry *e_old_end = e_old + nb_old; |
| 4225 | const AVIndexEntry *current = NULL; | 4179 | const AVIndexEntry *current = NULL; |
| 4226 | MOVStts *stts_data_old = msc->stts_data; | 4180 | MOVTimeToSample *tts_data_old = msc->tts_data; |
| 4227 | int64_t stts_index_old = 0; | 4181 | int64_t tts_index_old = 0; |
| 4228 | int64_t stts_sample_old = 0; | 4182 | int64_t tts_sample_old = 0; |
| 4229 | int64_t stts_count_old = msc->stts_count; | 4183 | int64_t tts_count_old = msc->tts_count; |
| 4230 | MOVCtts *ctts_data_old = msc->ctts_data; | ||
| 4231 | int64_t ctts_index_old = 0; | ||
| 4232 | int64_t ctts_sample_old = 0; | ||
| 4233 | int64_t ctts_count_old = msc->ctts_count; | ||
| 4234 | int64_t edit_list_media_time = 0; | 4184 | int64_t edit_list_media_time = 0; |
| 4235 | int64_t edit_list_duration = 0; | 4185 | int64_t edit_list_duration = 0; |
| 4236 | int64_t frame_duration = 0; | 4186 | int64_t frame_duration = 0; |
| 4237 | int64_t edit_list_dts_counter = 0; | 4187 | int64_t edit_list_dts_counter = 0; |
| 4238 | int64_t edit_list_dts_entry_end = 0; | 4188 | int64_t edit_list_dts_entry_end = 0; |
| 4239 | int64_t edit_list_start_stts_sample = 0; | 4189 | int64_t edit_list_start_tts_sample = 0; |
| 4240 | int64_t edit_list_start_ctts_sample = 0; | ||
| 4241 | int64_t curr_cts; | 4190 | int64_t curr_cts; |
| 4242 | int64_t curr_ctts = 0; | 4191 | int64_t curr_ctts = 0; |
| 4243 | int64_t empty_edits_sum_duration = 0; | 4192 | int64_t empty_edits_sum_duration = 0; |
| @@ -4274,16 +4223,11 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) · 30 unmodified lines | |||
| 4274 | sti->nb_index_entries = 0; | 4223 | sti->nb_index_entries = 0; |
| 4275 | 4224 | ||
| 4276 | // Clean time to sample fields of MOVStreamContext | 4225 | // Clean time to sample fields of MOVStreamContext |
| 4277 | msc->stts_data = NULL; | 4226 | msc->tts_data = NULL; |
| 4278 | msc->stts_count = 0; | 4227 | msc->tts_count = 0; |
| 4279 | msc->stts_index = 0; | 4228 | msc->tts_index = 0; |
| 4280 | msc->stts_sample = 0; | 4229 | msc->tts_sample = 0; |
| 4281 | msc->stts_allocated_size = 0; | 4230 | msc->tts_allocated_size = 0; |
| 4282 | msc->ctts_data = NULL; | ||
| 4283 | msc->ctts_count = 0; | ||
| 4284 | msc->ctts_index = 0; | ||
| 4285 | msc->ctts_sample = 0; | ||
| 4286 | msc->ctts_allocated_size = 0; | ||
| 4287 | 4231 | ||
| 4288 | // Reinitialize min_corrected_pts so that it can be computed again. | 4232 | // Reinitialize min_corrected_pts so that it can be computed again. |
| 4289 | msc->min_corrected_pts = -1; | 4233 | msc->min_corrected_pts = -1; |
| @@ -4336,26 +4280,23 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) · 46 unmodified lines | |||
| 4336 | search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp); | 4280 | search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp); |
| 4337 | } | 4281 | } |
| 4338 | 4282 | ||
| 4339 | if (find_prev_closest_index(st, e_old, nb_old, stts_data_old, stts_count_old, ctts_data_old, ctts_count_old, search_timestamp, 0, | 4283 | if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, 0, |
| 4340 | &index, &stts_index_old, &stts_sample_old, &ctts_index_old, &ctts_sample_old) < 0) { | 4284 | &index, &tts_index_old, &tts_sample_old) < 0) { |
| 4341 | av_log(mov->fc, AV_LOG_WARNING, | 4285 | av_log(mov->fc, AV_LOG_WARNING, |
| 4342 | "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n", | 4286 | "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n", |
| 4343 | st->index, edit_list_index, search_timestamp); | 4287 | st->index, edit_list_index, search_timestamp); |
| 4344 | if (find_prev_closest_index(st, e_old, nb_old, stts_data_old, stts_count_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY, | 4288 | if (find_prev_closest_index(st, e_old, nb_old, tts_data_old, tts_count_old, search_timestamp, AVSEEK_FLAG_ANY, |
| 4345 | &index, &stts_index_old, &stts_sample_old, &ctts_index_old, &ctts_sample_old) < 0) { | 4289 | &index, &tts_index_old, &tts_sample_old) < 0) { |
| 4346 | av_log(mov->fc, AV_LOG_WARNING, | 4290 | av_log(mov->fc, AV_LOG_WARNING, |
| 4347 | "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n", | 4291 | "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n", |
| 4348 | st->index, edit_list_index, search_timestamp); | 4292 | st->index, edit_list_index, search_timestamp); |
| 4349 | index = 0; | 4293 | index = 0; |
| 4350 | stts_index_old = 0; | 4294 | tts_index_old = 0; |
| 4351 | stts_sample_old = 0; | 4295 | tts_sample_old = 0; |
| 4352 | ctts_index_old = 0; | ||
| 4353 | ctts_sample_old = 0; | ||
| 4354 | } | 4296 | } |
| 4355 | } | 4297 | } |
| 4356 | current = e_old + index; | 4298 | current = e_old + index; |
| 4357 | edit_list_start_ctts_sample = ctts_sample_old; | 4299 | edit_list_start_tts_sample = tts_sample_old; |
| 4358 | edit_list_start_stts_sample = stts_sample_old; | ||
| 4359 | 4300 | ||
| 4360 | // Iterate over index and arrange it according to edit list | 4301 | // Iterate over index and arrange it according to edit list |
| 4361 | edit_list_start_encountered = 0; | 4302 | edit_list_start_encountered = 0; |
| @@ -4371,44 +4312,26 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) · 9 unmodified lines | |||
| 4371 | curr_cts = current->timestamp + msc->dts_shift; | 4312 | curr_cts = current->timestamp + msc->dts_shift; |
| 4372 | curr_ctts = 0; | 4313 | curr_ctts = 0; |
| 4373 | 4314 | ||
| 4374 | if (stts_data_old && stts_index_old < stts_count_old) { | 4315 | if (tts_data_old && tts_index_old < tts_count_old) { |
| 4375 | stts_sample_old++; | 4316 | curr_ctts = tts_data_old[tts_index_old].offset; |
| 4376 | if (stts_sample_old == stts_data_old[stts_index_old].count) { | 4317 | av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", tts_index: %"PRId64", tts_count: %"PRId64"\n", |
| 4377 | if (add_stts_entry(&msc->stts_data, &msc->stts_count, | 4318 | curr_cts, curr_ctts, tts_index_old, tts_count_old); |
| 4378 | &msc->stts_allocated_size, | ||
| 4379 | stts_data_old[stts_index_old].count - edit_list_start_stts_sample, | ||
| 4380 | stts_data_old[stts_index_old].duration) == -1) { | ||
| 4381 | av_log(mov->fc, AV_LOG_ERROR, "Cannot add STTS entry %"PRId64" - {%"PRId64", %d}\n", | ||
| 4382 | stts_index_old, | ||
| 4383 | stts_data_old[stts_index_old].count - edit_list_start_stts_sample, | ||
| 4384 | stts_data_old[stts_index_old].duration); | ||
| 4385 | break; | ||
| 4386 | } | ||
| 4387 | stts_index_old++; | ||
| 4388 | stts_sample_old = 0; | ||
| 4389 | edit_list_start_stts_sample = 0; | ||
| 4390 | } | ||
| 4391 | } | ||
| 4392 | if (ctts_data_old && ctts_index_old < ctts_count_old) { | ||
| 4393 | curr_ctts = ctts_data_old[ctts_index_old].offset; | ||
| 4394 | av_log(mov->fc, AV_LOG_TRACE, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n", | ||
| 4395 | curr_cts, curr_ctts, ctts_index_old, ctts_count_old); | ||
| 4396 | curr_cts += curr_ctts; | 4319 | curr_cts += curr_ctts; |
| 4397 | ctts_sample_old++; | 4320 | tts_sample_old++; |
| 4398 | if (ctts_sample_old == ctts_data_old[ctts_index_old].count) { | 4321 | if (tts_sample_old == tts_data_old[tts_index_old].count) { |
| 4399 | if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count, | 4322 | if (add_tts_entry(&msc->tts_data, &msc->tts_count, |
| 4400 | &msc->ctts_allocated_size, | 4323 | &msc->tts_allocated_size, |
| 4401 | ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample, | 4324 | tts_data_old[tts_index_old].count - edit_list_start_tts_sample, |
| 4402 | ctts_data_old[ctts_index_old].offset) == -1) { | 4325 | tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) { |
| 4403 | av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n", | 4326 | av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n", |
| 4404 | ctts_index_old, | 4327 | tts_index_old, |
| 4405 | ctts_data_old[ctts_index_old].count - edit_list_start_ctts_sample, | 4328 | tts_data_old[tts_index_old].count - edit_list_start_tts_sample, |
| 4406 | ctts_data_old[ctts_index_old].offset); | 4329 | tts_data_old[tts_index_old].offset); |
| 4407 | break; | 4330 | break; |
| 4408 | } | 4331 | } |
| 4409 | ctts_index_old++; | 4332 | tts_index_old++; |
| 4410 | ctts_sample_old = 0; | 4333 | tts_sample_old = 0; |
| 4411 | edit_list_start_ctts_sample = 0; | 4334 | edit_list_start_tts_sample = 0; |
| 4412 | } | 4335 | } |
| 4413 | } | 4336 | } |
| 4414 | 4337 | ||
| @@ -4494,7 +4417,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) · 79 unmodified lines | |||
| 4494 | // Break when found first key frame after edit entry completion | 4417 | // Break when found first key frame after edit entry completion |
| 4495 | if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) && | 4418 | if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) && |
| 4496 | ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) { | 4419 | ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) { |
| 4497 | if (ctts_data_old) { | 4420 | if (msc->ctts_count) { |
| 4498 | // If we have CTTS and this is the first keyframe after edit elist, | 4421 | // If we have CTTS and this is the first keyframe after edit elist, |
| 4499 | // wait for one more, because there might be trailing B-frames after this I-frame | 4422 | // wait for one more, because there might be trailing B-frames after this I-frame |
| 4500 | // that do belong to the edit. | 4423 | // that do belong to the edit. |
| @@ -4502,24 +4425,14 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) · 1 unmodified line | |||
| 4502 | found_keyframe_after_edit = 1; | 4425 | found_keyframe_after_edit = 1; |
| 4503 | continue; | 4426 | continue; |
| 4504 | } | 4427 | } |
| 4505 | if (ctts_sample_old != 0) { | 4428 | if (tts_sample_old != 0) { |
| 4506 | if (stts_data_old && | 4429 | if (add_tts_entry(&msc->tts_data, &msc->tts_count, |
| 4507 | add_stts_entry(&msc->stts_data, &msc->stts_count, | 4430 | &msc->tts_allocated_size, |
| 4508 | &msc->stts_allocated_size, | 4431 | tts_sample_old - edit_list_start_tts_sample, |
| 4509 | stts_sample_old - edit_list_start_stts_sample, | 4432 | tts_data_old[tts_index_old].offset, tts_data_old[tts_index_old].duration) == -1) { |
| 4510 | stts_data_old[stts_index_old].duration) == -1) { | 4433 | av_log(mov->fc, AV_LOG_ERROR, "Cannot add Time To Sample entry %"PRId64" - {%"PRId64", %d}\n", |
| 4511 | av_log(mov->fc, AV_LOG_ERROR, "Cannot add STTS entry %"PRId64" - {%"PRId64", %d}\n", | 4434 | tts_index_old, tts_sample_old - edit_list_start_tts_sample, |
| 4512 | stts_index_old, stts_sample_old - edit_list_start_stts_sample, | 4435 | tts_data_old[tts_index_old].offset); |
| 4513 | stts_data_old[stts_index_old].duration); | ||
| 4514 | break; | ||
| 4515 | } | ||
| 4516 | if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count, | ||
| 4517 | &msc->ctts_allocated_size, | ||
| 4518 | ctts_sample_old - edit_list_start_ctts_sample, | ||
| 4519 | ctts_data_old[ctts_index_old].offset) == -1) { | ||
| 4520 | av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n", | ||
| 4521 | ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample, | ||
| 4522 | ctts_data_old[ctts_index_old].offset); | ||
| 4523 | break; | 4436 | break; |
| 4524 | } | 4437 | } |
| 4525 | } | 4438 | } |
| @@ -4550,8 +4463,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) · 24 unmodified lines | |||
| 4550 | 4463 | ||
| 4551 | // Free the old index and the old CTTS structures | 4464 | // Free the old index and the old CTTS structures |
| 4552 | av_free(e_old); | 4465 | av_free(e_old); |
| 4553 | av_free(stts_data_old); | 4466 | av_free(tts_data_old); |
| 4554 | av_free(ctts_data_old); | ||
| 4555 | av_freep(&frame_duration_buffer); | 4467 | av_freep(&frame_duration_buffer); |
| 4556 | 4468 | ||
| 4557 | // Null terminate the index ranges array | 4469 | // Null terminate the index ranges array |
| @@ -4633,6 +4545,76 @@ static int build_open_gop_key_points(AVStream *st) · 75 unmodified lines | |||
| 4633 | return 0; | 4545 | return 0; |
| 4634 | } | 4546 | } |
| 4635 | 4547 | ||
| 4548 | #define MOV_MERGE_CTTS 1 | ||
| 4549 | #define MOV_MERGE_STTS 2 | ||
| 4550 | /* | ||
| 4551 | * Merge stts and ctts arrays into a new combined array. | ||
| 4552 | * stts_count and ctts_count may be left untouched as they will be | ||
| 4553 | * used to check for the presence of either of them. | ||
| 4554 | */ | ||
| 4555 | static int mov_merge_tts_data(MOVContext *mov, AVStream *st, int flags) | ||
| 4556 | { | ||
| 4557 | MOVStreamContext *sc = st->priv_data; | ||
| 4558 | int ctts = sc->ctts_data && (flags & MOV_MERGE_CTTS); | ||
| 4559 | int stts = sc->stts_data && (flags & MOV_MERGE_STTS); | ||
| 4560 | int idx = 0; | ||
| 4561 | |||
| 4562 | if (!sc->ctts_data && !sc->stts_data) | ||
| 4563 | return 0; | ||
| 4564 | // Expand time to sample entries such that we have a 1-1 mapping with samples | ||
| 4565 | if (!sc->sample_count || sc->sample_count >= UINT_MAX / sizeof(*sc->tts_data)) | ||
| 4566 | return -1; | ||
| 4567 | |||
| 4568 | if (ctts) { | ||
| 4569 | sc->tts_data = av_fast_realloc(NULL, &sc->tts_allocated_size, | ||
| 4570 | sc->sample_count * sizeof(*sc->tts_data)); | ||
| 4571 | if (!sc->tts_data) | ||
| 4572 | return -1; | ||
| 4573 | |||
| 4574 | memset(sc->tts_data, 0, sc->tts_allocated_size); | ||
| 4575 | |||
| 4576 | for (int i = 0; i < sc->ctts_count && | ||
| 4577 | idx < sc->sample_count; i++) | ||
| 4578 | for (int j = 0; j < sc->ctts_data[i].count && | ||
| 4579 | idx < sc->sample_count; j++) { | ||
| 4580 | sc->tts_data[idx].offset = sc->ctts_data[i].offset; | ||
| 4581 | sc->tts_data[idx++].count = 1; | ||
| 4582 | } | ||
| 4583 | |||
| 4584 | sc->tts_count = idx; | ||
| 4585 | } else | ||
| 4586 | sc->ctts_count = 0; | ||
| 4587 | av_freep(&sc->ctts_data); | ||
| 4588 | sc->ctts_allocated_size = 0; | ||
| 4589 | |||
| 4590 | idx = 0; | ||
| 4591 | if (stts) { | ||
| 4592 | MOVTimeToSample *tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size, | ||
| 4593 | sc->sample_count * sizeof(*sc->tts_data)); | ||
| 4594 | if (!tts_data) | ||
| 4595 | return -1; | ||
| 4596 | |||
| 4597 | if (!sc->tts_data) | ||
| 4598 | memset(tts_data, 0, sc->tts_allocated_size); | ||
| 4599 | sc->tts_data = tts_data; | ||
| 4600 | |||
| 4601 | for (int i = 0; i < sc->stts_count && | ||
| 4602 | idx < sc->sample_count; i++) | ||
| 4603 | for (int j = 0; j < sc->stts_data[i].count && | ||
| 4604 | idx < sc->sample_count; j++) { | ||
| 4605 | sc->tts_data[idx].duration = sc->stts_data[i].duration; | ||
| 4606 | sc->tts_data[idx++].count = 1; | ||
| 4607 | } | ||
| 4608 | |||
| 4609 | sc->tts_count = FFMAX(sc->tts_count, idx); | ||
| 4610 | } else | ||
| 4611 | sc->stts_count = 0; | ||
| 4612 | av_freep(&sc->stts_data); | ||
| 4613 | sc->stts_allocated_size = 0; | ||
| 4614 | |||
| 4615 | return 0; | ||
| 4616 | } | ||
| 4617 | |||
| 4636 | static void mov_build_index(MOVContext *mov, AVStream *st) | 4618 | static void mov_build_index(MOVContext *mov, AVStream *st) |
| 4637 | { | 4619 | { |
| 4638 | MOVStreamContext *sc = st->priv_data; | 4620 | MOVStreamContext *sc = st->priv_data; |
| @@ -4645,10 +4627,6 @@ static void mov_build_index(MOVContext *mov, AVStream *st) · 6 unmodified lines | |||
| 4645 | unsigned int stps_index = 0; | 4627 | unsigned int stps_index = 0; |
| 4646 | unsigned int i, j; | 4628 | unsigned int i, j; |
| 4647 | uint64_t stream_size = 0; | 4629 | uint64_t stream_size = 0; |
| 4648 | MOVStts *stts_data_old = sc->stts_data; | ||
| 4649 | MOVCtts *ctts_data_old = sc->ctts_data; | ||
| 4650 | unsigned int stts_count_old = sc->stts_count; | ||
| 4651 | unsigned int ctts_count_old = sc->ctts_count; | ||
| 4652 | 4630 | ||
| 4653 | int ret = build_open_gop_key_points(st); | 4631 | int ret = build_open_gop_key_points(st); |
| 4654 | if (ret < 0) | 4632 | if (ret < 0) |
| @@ -4728,54 +4706,9 @@ static void mov_build_index(MOVContext *mov, AVStream *st) · 73 unmodified lines | |||
| 4728 | } | 4706 | } |
| 4729 | sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries); | 4707 | sti->index_entries_allocated_size = (sti->nb_index_entries + sc->sample_count) * sizeof(*sti->index_entries); |
| 4730 | 4708 | ||
| 4731 | if (ctts_data_old) { | 4709 | ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS | MOV_MERGE_STTS); |
| 4732 | // Expand ctts entries such that we have a 1-1 mapping with samples | 4710 | if (ret < 0) |
| 4733 | if (sc->sample_count >= UINT_MAX / sizeof(*sc->ctts_data)) | 4711 | return; |
| 4734 | return; | ||
| 4735 | sc->ctts_count = 0; | ||
| 4736 | sc->ctts_allocated_size = 0; | ||
| 4737 | sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, | ||
| 4738 | sc->sample_count * sizeof(*sc->ctts_data)); | ||
| 4739 | if (!sc->ctts_data) { | ||
| 4740 | av_free(ctts_data_old); | ||
| 4741 | return; | ||
| 4742 | } | ||
| 4743 | |||
| 4744 | memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size); | ||
| 4745 | |||
| 4746 | for (i = 0; i < ctts_count_old && | ||
| 4747 | sc->ctts_count < sc->sample_count; i++) | ||
| 4748 | for (j = 0; j < ctts_data_old[i].count && | ||
| 4749 | sc->ctts_count < sc->sample_count; j++) | ||
| 4750 | add_ctts_entry(&sc->ctts_data, &sc->ctts_count, | ||
| 4751 | &sc->ctts_allocated_size, 1, | ||
| 4752 | ctts_data_old[i].offset); | ||
| 4753 | av_free(ctts_data_old); | ||
| 4754 | } | ||
| 4755 | if (stts_data_old) { | ||
| 4756 | // Expand stts entries such that we have a 1-1 mapping with samples | ||
| 4757 | if (sc->sample_count >= UINT_MAX / sizeof(*sc->stts_data)) | ||
| 4758 | return; | ||
| 4759 | sc->stts_count = 0; | ||
| 4760 | sc->stts_allocated_size = 0; | ||
| 4761 | sc->stts_data = av_fast_realloc(NULL, &sc->stts_allocated_size, | ||
| 4762 | sc->sample_count * sizeof(*sc->stts_data)); | ||
| 4763 | if (!sc->stts_data) { | ||
| 4764 | av_free(stts_data_old); | ||
| 4765 | return; | ||
| 4766 | } | ||
| 4767 | |||
| 4768 | memset((uint8_t*)(sc->stts_data), 0, sc->stts_allocated_size); | ||
| 4769 | |||
| 4770 | for (i = 0; i < stts_count_old && | ||
| 4771 | sc->stts_count < sc->sample_count; i++) | ||
| 4772 | for (j = 0; j < stts_data_old[i].count && | ||
| 4773 | sc->stts_count < sc->sample_count; j++) | ||
| 4774 | add_stts_entry(&sc->stts_data, &sc->stts_count, | ||
| 4775 | &sc->stts_allocated_size, 1, | ||
| 4776 | stts_data_old[i].duration); | ||
| 4777 | av_free(stts_data_old); | ||
| 4778 | } | ||
| 4779 | 4712 | ||
| 4780 | for (i = 0; i < sc->chunk_count; i++) { | 4713 | for (i = 0; i < sc->chunk_count; i++) { |
| 4781 | int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX; | 4714 | int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX; |
| @@ -4856,12 +4789,12 @@ static void mov_build_index(MOVContext *mov, AVStream *st) · 74 unmodified lines | |||
| 4856 | current_offset += sample_size; | 4789 | current_offset += sample_size; |
| 4857 | stream_size += sample_size; | 4790 | stream_size += sample_size; |
| 4858 | 4791 | ||
| 4859 | current_dts += sc->stts_data[stts_index].duration; | 4792 | current_dts += sc->tts_data[stts_index].duration; |
| 4860 | 4793 | ||
| 4861 | distance++; | 4794 | distance++; |
| 4862 | stts_sample++; | 4795 | stts_sample++; |
| 4863 | current_sample++; | 4796 | current_sample++; |
| 4864 | if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) { | 4797 | if (stts_index + 1 < sc->tts_count && stts_sample == sc->tts_data[stts_index].count) { |
| 4865 | stts_sample = 0; | 4798 | stts_sample = 0; |
| 4866 | stts_index++; | 4799 | stts_index++; |
| 4867 | } | 4800 | } |
| @@ -4872,6 +4805,10 @@ static void mov_build_index(MOVContext *mov, AVStream *st) · 4 unmodified lines | |||
| 4872 | } else { | 4805 | } else { |
| 4873 | unsigned chunk_samples, total = 0; | 4806 | unsigned chunk_samples, total = 0; |
| 4874 | 4807 | ||
| 4808 | ret = mov_merge_tts_data(mov, st, MOV_MERGE_CTTS); | ||
| 4809 | if (ret < 0) | ||
| 4810 | return; | ||
| 4811 | |||
| 4875 | if (!sc->chunk_count) | 4812 | if (!sc->chunk_count) |
| 4876 | return; | 4813 | return; |
| 4877 | 4814 | ||
| @@ -4979,8 +4916,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st) · 101 unmodified lines | |||
| 4979 | // Update start time of the stream. | 4916 | // Update start time of the stream. |
| 4980 | if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) { | 4917 | if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sti->nb_index_entries > 0) { |
| 4981 | st->start_time = sti->index_entries[0].timestamp + sc->dts_shift; | 4918 | st->start_time = sti->index_entries[0].timestamp + sc->dts_shift; |
| 4982 | if (sc->ctts_data) { | 4919 | if (sc->tts_data) { |
| 4983 | st->start_time += sc->ctts_data[0].offset; | 4920 | st->start_time += sc->tts_data[0].offset; |
| 4984 | } | 4921 | } |
| 4985 | } | 4922 | } |
| 4986 | 4923 | ||
| @@ -5254,14 +5191,14 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 267 unmodified lines | |||
| 5254 | } | 5191 | } |
| 5255 | 5192 | ||
| 5256 | #if FF_API_R_FRAME_RATE | 5193 | #if FF_API_R_FRAME_RATE |
| 5257 | for (int i = 1; sc->stts_count && i < sc->stts_count - 1; i++) { | 5194 | for (int i = 1; sc->stts_count && i < sc->tts_count - 1; i++) { |
| 5258 | if (sc->stts_data[i].duration == sc->stts_data[0].duration) | 5195 | if (sc->tts_data[i].duration == sc->tts_data[0].duration) |
| 5259 | continue; | 5196 | continue; |
| 5260 | stts_constant = 0; | 5197 | stts_constant = 0; |
| 5261 | } | 5198 | } |
| 5262 | if (stts_constant) | 5199 | if (stts_constant) |
| 5263 | av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, | 5200 | av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, |
| 5264 | sc->time_scale, sc->stts_data[0].duration, INT_MAX); | 5201 | sc->time_scale, sc->tts_data[0].duration, INT_MAX); |
| 5265 | #endif | 5202 | #endif |
| 5266 | } | 5203 | } |
| 5267 | 5204 | ||
| @@ -5292,8 +5229,8 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 24 unmodified lines | |||
| 5292 | if (st->codecpar->codec_id == AV_CODEC_ID_MP3 | 5229 | if (st->codecpar->codec_id == AV_CODEC_ID_MP3 |
| 5293 | && sc->time_scale == st->codecpar->sample_rate) { | 5230 | && sc->time_scale == st->codecpar->sample_rate) { |
| 5294 | int stts_constant = 1; | 5231 | int stts_constant = 1; |
| 5295 | for (int i = 1; i < sc->stts_count; i++) { | 5232 | for (int i = 1; sc->stts_count && i < sc->tts_count; i++) { |
| 5296 | if (sc->stts_data[i].duration == sc->stts_data[0].duration) | 5233 | if (sc->tts_data[i].duration == sc->tts_data[0].duration) |
| 5297 | continue; | 5234 | continue; |
| 5298 | stts_constant = 0; | 5235 | stts_constant = 0; |
| 5299 | } | 5236 | } |
| @@ -5776,8 +5713,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 476 unmodified lines | |||
| 5776 | AVStream *st = NULL; | 5713 | AVStream *st = NULL; |
| 5777 | FFStream *sti = NULL; | 5714 | FFStream *sti = NULL; |
| 5778 | MOVStreamContext *sc; | 5715 | MOVStreamContext *sc; |
| 5779 | MOVStts *stts_data; | 5716 | MOVTimeToSample *tts_data; |
| 5780 | MOVCtts *ctts_data; | ||
| 5781 | uint64_t offset; | 5717 | uint64_t offset; |
| 5782 | int64_t dts, pts = AV_NOPTS_VALUE; | 5718 | int64_t dts, pts = AV_NOPTS_VALUE; |
| 5783 | int data_offset = 0; | 5719 | int data_offset = 0; |
| @@ -5833,7 +5769,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 49 unmodified lines | |||
| 5833 | entries = avio_rb32(pb); | 5769 | entries = avio_rb32(pb); |
| 5834 | av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries); | 5770 | av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries); |
| 5835 | 5771 | ||
| 5836 | if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data)) | 5772 | if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data)) |
| 5837 | return AVERROR_INVALIDDATA; | 5773 | return AVERROR_INVALIDDATA; |
| 5838 | if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb); | 5774 | if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb); |
| 5839 | if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb); | 5775 | if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb); |
| @@ -5906,52 +5842,39 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 66 unmodified lines | |||
| 5906 | return AVERROR(ENOMEM); | 5842 | return AVERROR(ENOMEM); |
| 5907 | sti->index_entries= new_entries; | 5843 | sti->index_entries= new_entries; |
| 5908 | 5844 | ||
| 5909 | requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->ctts_data); | 5845 | requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->tts_data); |
| 5910 | old_allocated_size = sc->ctts_allocated_size; | 5846 | old_allocated_size = sc->tts_allocated_size; |
| 5911 | ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, | 5847 | tts_data = av_fast_realloc(sc->tts_data, &sc->tts_allocated_size, |
| 5912 | requested_size); | 5848 | requested_size); |
| 5913 | if (!ctts_data) | 5849 | if (!tts_data) |
| 5914 | return AVERROR(ENOMEM); | 5850 | return AVERROR(ENOMEM); |
| 5915 | sc->ctts_data = ctts_data; | 5851 | sc->tts_data = tts_data; |
| 5916 | 5852 | ||
| 5917 | // In case there were samples without ctts entries, ensure they get | 5853 | // In case there were samples without time to sample entries, ensure they get |
| 5918 | // zero valued entries. This ensures clips which mix boxes with and | 5854 | // zero valued entries. This ensures clips which mix boxes with and |
| 5919 | // without ctts entries don't pickup uninitialized data. | 5855 | // without time to sample entries don't pickup uninitialized data. |
| 5920 | memset((uint8_t*)(sc->ctts_data) + old_allocated_size, 0, | 5856 | memset((uint8_t*)(sc->tts_data) + old_allocated_size, 0, |
| 5921 | sc->ctts_allocated_size - old_allocated_size); | 5857 | sc->tts_allocated_size - old_allocated_size); |
| 5922 | |||
| 5923 | requested_size = (sti->nb_index_entries + entries) * sizeof(*sc->stts_data); | ||
| 5924 | old_allocated_size = sc->stts_allocated_size; | ||
| 5925 | stts_data = av_fast_realloc(sc->stts_data, &sc->stts_allocated_size, | ||
| 5926 | requested_size); | ||
| 5927 | if (!stts_data) | ||
| 5928 | return AVERROR(ENOMEM); | ||
| 5929 | sc->stts_data = stts_data; | ||
| 5930 | |||
| 5931 | // See the comment for ctts above. | ||
| 5932 | memset((uint8_t*)(sc->stts_data) + old_allocated_size, 0, | ||
| 5933 | sc->stts_allocated_size - old_allocated_size); | ||
| 5934 | 5858 | ||
| 5935 | if (index_entry_pos < sti->nb_index_entries) { | 5859 | if (index_entry_pos < sti->nb_index_entries) { |
| 5936 | // Make hole in index_entries and ctts_data for new samples | 5860 | // Make hole in index_entries and tts_data for new samples |
| 5937 | memmove(sti->index_entries + index_entry_pos + entries, | 5861 | memmove(sti->index_entries + index_entry_pos + entries, |
| 5938 | sti->index_entries + index_entry_pos, | 5862 | sti->index_entries + index_entry_pos, |
| 5939 | sizeof(*sti->index_entries) * | 5863 | sizeof(*sti->index_entries) * |
| 5940 | (sti->nb_index_entries - index_entry_pos)); | 5864 | (sti->nb_index_entries - index_entry_pos)); |
| 5941 | memmove(sc->ctts_data + index_entry_pos + entries, | 5865 | memmove(sc->tts_data + index_entry_pos + entries, |
| 5942 | sc->ctts_data + index_entry_pos, | 5866 | sc->tts_data + index_entry_pos, |
| 5943 | sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos)); | 5867 | sizeof(*sc->tts_data) * (sc->tts_count - index_entry_pos)); |
| 5944 | memmove(sc->stts_data + index_entry_pos + entries, | ||
| 5945 | sc->stts_data + index_entry_pos, | ||
| 5946 | sizeof(*sc->stts_data) * (sc->stts_count - index_entry_pos)); | ||
| 5947 | if (index_entry_pos < sc->current_sample) { | 5868 | if (index_entry_pos < sc->current_sample) { |
| 5948 | sc->current_sample += entries; | 5869 | sc->current_sample += entries; |
| 5949 | } | 5870 | } |
| 5950 | } | 5871 | } |
| 5951 | 5872 | ||
| 5952 | sti->nb_index_entries += entries; | 5873 | sti->nb_index_entries += entries; |
| 5953 | sc->ctts_count = sti->nb_index_entries; | 5874 | sc->tts_count = sti->nb_index_entries; |
| 5954 | sc->stts_count = sti->nb_index_entries; | 5875 | sc->stts_count = sti->nb_index_entries; |
| 5876 | if (flags & MOV_TRUN_SAMPLE_CTS) | ||
| 5877 | sc->ctts_count = sti->nb_index_entries; | ||
| 5955 | 5878 | ||
| 5956 | // Record the index_entry position in frag_index of this fragment | 5879 | // Record the index_entry position in frag_index of this fragment |
| 5957 | if (frag_stream_info) { | 5880 | if (frag_stream_info) { |
| @@ -6013,10 +5936,9 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 55 unmodified lines | |||
| 6013 | sti->index_entries[index_entry_pos].min_distance = distance; | 5936 | sti->index_entries[index_entry_pos].min_distance = distance; |
| 6014 | sti->index_entries[index_entry_pos].flags = index_entry_flags; | 5937 | sti->index_entries[index_entry_pos].flags = index_entry_flags; |
| 6015 | 5938 | ||
| 6016 | sc->ctts_data[index_entry_pos].count = 1; | 5939 | sc->tts_data[index_entry_pos].count = 1; |
| 6017 | sc->ctts_data[index_entry_pos].offset = ctts_duration; | 5940 | sc->tts_data[index_entry_pos].offset = ctts_duration; |
| 6018 | sc->stts_data[index_entry_pos].count = 1; | 5941 | sc->tts_data[index_entry_pos].duration = sample_duration; |
| 6019 | sc->stts_data[index_entry_pos].duration = sample_duration; | ||
| 6020 | index_entry_pos++; | 5942 | index_entry_pos++; |
| 6021 | 5943 | ||
| 6022 | av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " | 5944 | av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " |
| @@ -6042,24 +5964,19 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 19 unmodified lines | |||
| 6042 | frag_stream_info->next_trun_dts = dts + sc->time_offset; | 5964 | frag_stream_info->next_trun_dts = dts + sc->time_offset; |
| 6043 | if (i < entries) { | 5965 | if (i < entries) { |
| 6044 | // EOF found before reading all entries. Fix the hole this would | 5966 | // EOF found before reading all entries. Fix the hole this would |
| 6045 | // leave in index_entries and ctts_data | 5967 | // leave in index_entries and tts_data |
| 6046 | int gap = entries - i; | 5968 | int gap = entries - i; |
| 6047 | memmove(sti->index_entries + index_entry_pos, | 5969 | memmove(sti->index_entries + index_entry_pos, |
| 6048 | sti->index_entries + index_entry_pos + gap, | 5970 | sti->index_entries + index_entry_pos + gap, |
| 6049 | sizeof(*sti->index_entries) * | 5971 | sizeof(*sti->index_entries) * |
| 6050 | (sti->nb_index_entries - (index_entry_pos + gap))); | 5972 | (sti->nb_index_entries - (index_entry_pos + gap))); |
| 6051 | memmove(sc->ctts_data + index_entry_pos, | 5973 | memmove(sc->tts_data + index_entry_pos, |
| 6052 | sc->ctts_data + index_entry_pos + gap, | 5974 | sc->tts_data + index_entry_pos + gap, |
| 6053 | sizeof(*sc->ctts_data) * | 5975 | sizeof(*sc->tts_data) * |
| 6054 | (sc->ctts_count - (index_entry_pos + gap))); | 5976 | (sc->tts_count - (index_entry_pos + gap))); |
| 6055 | memmove(sc->stts_data + index_entry_pos, | ||
| 6056 | sc->stts_data + index_entry_pos + gap, | ||
| 6057 | sizeof(*sc->stts_data) * | ||
| 6058 | (sc->stts_count - (index_entry_pos + gap))); | ||
| 6059 | 5977 | ||
| 6060 | sti->nb_index_entries -= gap; | 5978 | sti->nb_index_entries -= gap; |
| 6061 | sc->ctts_count -= gap; | 5979 | sc->tts_count -= gap; |
| 6062 | sc->stts_count -= gap; | ||
| 6063 | if (index_entry_pos < sc->current_sample) { | 5980 | if (index_entry_pos < sc->current_sample) { |
| 6064 | sc->current_sample -= gap; | 5981 | sc->current_sample -= gap; |
| 6065 | } | 5982 | } |
| @@ -9821,7 +9738,7 @@ static void mov_free_stream_context(AVFormatContext *s, AVStream *st) · 3755 unmodified lines | |||
| 9821 | return; | 9738 | return; |
| 9822 | } | 9739 | } |
| 9823 | 9740 | ||
| 9824 | av_freep(&sc->ctts_data); | 9741 | av_freep(&sc->tts_data); |
| 9825 | for (int i = 0; i < sc->drefs_count; i++) { | 9742 | for (int i = 0; i < sc->drefs_count; i++) { |
| 9826 | av_freep(&sc->drefs[i].path); | 9743 | av_freep(&sc->drefs[i].path); |
| 9827 | av_freep(&sc->drefs[i].dir); | 9744 | av_freep(&sc->drefs[i].dir); |
| @@ -9838,6 +9755,7 @@ static void mov_free_stream_context(AVFormatContext *s, AVStream *st) · 10 unmodified lines | |||
| 9838 | av_freep(&sc->stsc_data); | 9755 | av_freep(&sc->stsc_data); |
| 9839 | av_freep(&sc->sample_sizes); | 9756 | av_freep(&sc->sample_sizes); |
| 9840 | av_freep(&sc->keyframes); | 9757 | av_freep(&sc->keyframes); |
| 9758 | av_freep(&sc->ctts_data); | ||
| 9841 | av_freep(&sc->stts_data); | 9759 | av_freep(&sc->stts_data); |
| 9842 | av_freep(&sc->sdtp_data); | 9760 | av_freep(&sc->sdtp_data); |
| 9843 | av_freep(&sc->stps_data); | 9761 | av_freep(&sc->stps_data); |
| @@ -10859,27 +10777,10 @@ static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *s · 1015 unmodified lines | |||
| 10859 | if (sample->flags & AVINDEX_DISCARD_FRAME) { | 10777 | if (sample->flags & AVINDEX_DISCARD_FRAME) { |
| 10860 | pkt->flags |= AV_PKT_FLAG_DISCARD; | 10778 | pkt->flags |= AV_PKT_FLAG_DISCARD; |
| 10861 | } | 10779 | } |
| 10862 | if (sc->stts_data && sc->stts_index < sc->stts_count) { | 10780 | if (sc->stts_count && sc->tts_index < sc->tts_count) |
| 10863 | pkt->duration = sc->stts_data[sc->stts_index].duration; | 10781 | pkt->duration = sc->tts_data[sc->tts_index].duration; |
| 10864 | 10782 | if (sc->ctts_count && sc->tts_index < sc->tts_count) { | |
| 10865 | /* update stts context */ | 10783 | pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->tts_data[sc->tts_index].offset)); |
| 10866 | sc->stts_sample++; | ||
| 10867 | if (sc->stts_index < sc->stts_count && | ||
| 10868 | sc->stts_data[sc->stts_index].count == sc->stts_sample) { | ||
| 10869 | sc->stts_index++; | ||
| 10870 | sc->stts_sample = 0; | ||
| 10871 | } | ||
| 10872 | } | ||
| 10873 | if (sc->ctts_data && sc->ctts_index < sc->ctts_count) { | ||
| 10874 | pkt->pts = av_sat_add64(pkt->dts, av_sat_add64(sc->dts_shift, sc->ctts_data[sc->ctts_index].offset)); | ||
| 10875 | |||
| 10876 | /* update ctts context */ | ||
| 10877 | sc->ctts_sample++; | ||
| 10878 | if (sc->ctts_index < sc->ctts_count && | ||
| 10879 | sc->ctts_data[sc->ctts_index].count == sc->ctts_sample) { | ||
| 10880 | sc->ctts_index++; | ||
| 10881 | sc->ctts_sample = 0; | ||
| 10882 | } | ||
| 10883 | } else { | 10784 | } else { |
| 10884 | if (pkt->duration == 0) { | 10785 | if (pkt->duration == 0) { |
| 10885 | int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ? | 10786 | int64_t next_dts = (sc->current_sample < ffstream(st)->nb_index_entries) ? |
| @@ -10890,6 +10791,16 @@ static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *s · 4 unmodified lines | |||
| 10890 | pkt->pts = pkt->dts; | 10791 | pkt->pts = pkt->dts; |
| 10891 | } | 10792 | } |
| 10892 | 10793 | ||
| 10794 | if (sc->tts_data && sc->tts_index < sc->tts_count) { | ||
| 10795 | /* update tts context */ | ||
| 10796 | sc->tts_sample++; | ||
| 10797 | if (sc->tts_index < sc->tts_count && | ||
| 10798 | sc->tts_data[sc->tts_index].count == sc->tts_sample) { | ||
| 10799 | sc->tts_index++; | ||
| 10800 | sc->tts_sample = 0; | ||
| 10801 | } | ||
| 10802 | } | ||
| 10803 | |||
| 10893 | if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) { | 10804 | if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) { |
| 10894 | uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1]; | 10805 | uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1]; |
| 10895 | uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3; | 10806 | uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3; |
| @@ -10952,7 +10863,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) · 56 unmodified lines | |||
| 10952 | 10863 | ||
| 10953 | // Clear current sample | 10864 | // Clear current sample |
| 10954 | mov_current_sample_set(msc, 0); | 10865 | mov_current_sample_set(msc, 0); |
| 10955 | msc->ctts_index = 0; | 10866 | msc->tts_index = 0; |
| 10956 | 10867 | ||
| 10957 | // Discard current index entries | 10868 | // Discard current index entries |
| 10958 | avsti = ffstream(avst); | 10869 | avsti = ffstream(avst); |
| @@ -11185,27 +11096,14 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, · 226 unmodified lines | |||
| 11185 | 11096 | ||
| 11186 | mov_current_sample_set(sc, sample); | 11097 | mov_current_sample_set(sc, sample); |
| 11187 | av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample); | 11098 | av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample); |
| 11188 | /* adjust stts index */ | 11099 | /* adjust time to sample index */ |
| 11189 | if (sc->stts_data) { | 11100 | if (sc->tts_data) { |
| 11190 | time_sample = 0; | ||
| 11191 | for (i = 0; i < sc->stts_count; i++) { | ||
| 11192 | int next = time_sample + sc->stts_data[i].count; | ||
| 11193 | if (next > sc->current_sample) { | ||
| 11194 | sc->stts_index = i; | ||
| 11195 | sc->stts_sample = sc->current_sample - time_sample; | ||
| 11196 | break; | ||
| 11197 | } | ||
| 11198 | time_sample = next; | ||
| 11199 | } | ||
| 11200 | } | ||
| 11201 | /* adjust ctts index */ | ||
| 11202 | if (sc->ctts_data) { | ||
| 11203 | time_sample = 0; | 11101 | time_sample = 0; |
| 11204 | for (i = 0; i < sc->ctts_count; i++) { | 11102 | for (i = 0; i < sc->tts_count; i++) { |
| 11205 | int next = time_sample + sc->ctts_data[i].count; | 11103 | int next = time_sample + sc->tts_data[i].count; |
| 11206 | if (next > sc->current_sample) { | 11104 | if (next > sc->current_sample) { |
| 11207 | sc->ctts_index = i; | 11105 | sc->tts_index = i; |
| 11208 | sc->ctts_sample = sc->current_sample - time_sample; | 11106 | sc->tts_sample = sc->current_sample - time_sample; |
| 11209 | break; | 11107 | break; |
| 11210 | } | 11108 | } |
| 11211 | time_sample = next; | 11109 | time_sample = next; |