You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avformat/mov: move edit list heuristics into mov_build_index()
mov_read_elst() is now only responsible from storing the table in a data structure; this is consistent with other table readers functions.
This commit is contained in:
		| @@ -53,6 +53,12 @@ typedef struct MOVStsc { | ||||
|     int id; | ||||
| } MOVStsc; | ||||
|  | ||||
| typedef struct MOVElst { | ||||
|     int64_t duration; | ||||
|     int64_t time; | ||||
|     float rate; | ||||
| } MOVElst; | ||||
|  | ||||
| typedef struct MOVDref { | ||||
|     uint32_t type; | ||||
|     char *path; | ||||
| @@ -121,6 +127,8 @@ typedef struct MOVStreamContext { | ||||
|     MOVStsc *stsc_data; | ||||
|     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 | ||||
| @@ -131,8 +139,6 @@ typedef struct MOVStreamContext { | ||||
|     unsigned int keyframe_count; | ||||
|     int *keyframes; | ||||
|     int time_scale; | ||||
|     int64_t empty_duration; ///< empty duration of the first edit list entry | ||||
|     int64_t start_time;   ///< start time of the media | ||||
|     int64_t time_offset;  ///< time offset of the edit list entries | ||||
|     int current_sample; | ||||
|     unsigned int bytes_per_frame; | ||||
|   | ||||
| @@ -2268,11 +2268,32 @@ static void mov_build_index(MOVContext *mov, AVStream *st) | ||||
|     unsigned int i, j; | ||||
|     uint64_t stream_size = 0; | ||||
|  | ||||
|     if (sc->elst_count) { | ||||
|         int i, edit_start_index = 0, unsupported = 0; | ||||
|         int64_t empty_duration = 0; // empty duration of the first edit list entry | ||||
|         int64_t start_time = 0; // start time of the media | ||||
|  | ||||
|         for (i = 0; i < sc->elst_count; i++) { | ||||
|             const MOVElst *e = &sc->elst_data[i]; | ||||
|             if (i == 0 && e->time == -1) { | ||||
|                 /* if empty, the first entry is the start time of the stream | ||||
|                  * relative to the presentation itself */ | ||||
|                 empty_duration = e->duration; | ||||
|                 edit_start_index = 1; | ||||
|             } else if (i == edit_start_index && e->time >= 0) { | ||||
|                 start_time = e->time; | ||||
|             } else | ||||
|                 unsupported = 1; | ||||
|         } | ||||
|         if (unsupported) | ||||
|             av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, " | ||||
|                    "a/v desync might occur, patch welcome\n"); | ||||
|  | ||||
|     /* adjust first dts according to edit list */ | ||||
|     if ((sc->empty_duration || sc->start_time) && mov->time_scale > 0) { | ||||
|         if (sc->empty_duration) | ||||
|             sc->empty_duration = av_rescale(sc->empty_duration, sc->time_scale, mov->time_scale); | ||||
|         sc->time_offset = sc->start_time - sc->empty_duration; | ||||
|     if ((empty_duration || start_time) && mov->time_scale > 0) { | ||||
|         if (empty_duration) | ||||
|             empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale); | ||||
|         sc->time_offset = start_time - empty_duration; | ||||
|         current_dts = -sc->time_offset; | ||||
|         if (sc->ctts_count>0 && sc->stts_count>0 && | ||||
|             sc->ctts_data[0].duration / FFMAX(sc->stts_data[0].duration, 1) > 16) { | ||||
| @@ -2282,6 +2303,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) | ||||
|             st->codec->has_b_frames = 1; | ||||
|         } | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     /* only use old uncompressed audio chunk demuxing when stts specifies it */ | ||||
|     if (!(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && | ||||
| @@ -2626,6 +2648,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) | ||||
|     av_freep(&sc->keyframes); | ||||
|     av_freep(&sc->stts_data); | ||||
|     av_freep(&sc->stps_data); | ||||
|     av_freep(&sc->elst_data); | ||||
|     av_freep(&sc->rap_group); | ||||
|  | ||||
|     return 0; | ||||
| @@ -3190,8 +3213,7 @@ free_and_return: | ||||
| static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) | ||||
| { | ||||
|     MOVStreamContext *sc; | ||||
|     int i, edit_count, version, edit_start_index = 0; | ||||
|     int unsupported = 0; | ||||
|     int i, edit_count, version; | ||||
|  | ||||
|     if (c->fc->nb_streams < 1 || c->ignore_editlist) | ||||
|         return 0; | ||||
| @@ -3201,37 +3223,32 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) | ||||
|     avio_rb24(pb); /* flags */ | ||||
|     edit_count = avio_rb32(pb); /* entries */ | ||||
|  | ||||
|     if ((uint64_t)edit_count*12+8 > atom.size) | ||||
|         return AVERROR_INVALIDDATA; | ||||
|     if (!edit_count) | ||||
|         return 0; | ||||
|     if (sc->elst_data) | ||||
|         av_log(c->fc, AV_LOG_WARNING, "Duplicated ELST atom\n"); | ||||
|     av_free(sc->elst_data); | ||||
|     sc->elst_count = 0; | ||||
|     sc->elst_data = av_malloc_array(edit_count, sizeof(*sc->elst_data)); | ||||
|     if (!sc->elst_data) | ||||
|         return AVERROR(ENOMEM); | ||||
|  | ||||
|     av_dlog(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, edit_count); | ||||
|     for (i=0; i<edit_count; i++){ | ||||
|         int64_t time; | ||||
|         int64_t duration; | ||||
|         int rate; | ||||
|     for (i = 0; i < edit_count && !pb->eof_reached; i++) { | ||||
|         MOVElst *e = &sc->elst_data[i]; | ||||
|  | ||||
|         if (version == 1) { | ||||
|             duration = avio_rb64(pb); | ||||
|             time     = avio_rb64(pb); | ||||
|             e->duration = avio_rb64(pb); | ||||
|             e->time     = avio_rb64(pb); | ||||
|         } else { | ||||
|             duration = avio_rb32(pb); /* segment duration */ | ||||
|             time     = (int32_t)avio_rb32(pb); /* media time */ | ||||
|             e->duration = avio_rb32(pb); /* segment duration */ | ||||
|             e->time     = (int32_t)avio_rb32(pb); /* media time */ | ||||
|         } | ||||
|         rate = avio_rb32(pb); | ||||
|         if (i == 0 && time == -1) { | ||||
|             sc->empty_duration = duration; | ||||
|             edit_start_index = 1; | ||||
|         } else if (i == edit_start_index && time >= 0) | ||||
|             sc->start_time = time; | ||||
|         else | ||||
|             unsupported = 1; | ||||
|  | ||||
|         e->rate = avio_rb32(pb) / 65536.0; | ||||
|         av_dlog(c->fc, "duration=%"PRId64" time=%"PRId64" rate=%f\n", | ||||
|                 duration, time, rate / 65536.0); | ||||
|                 e->duration, e->time, e->rate); | ||||
|     } | ||||
|  | ||||
|     if (unsupported) | ||||
|         av_log(c->fc, AV_LOG_WARNING, "multiple edit list entries, " | ||||
|                "a/v desync might occur, patch welcome\n"); | ||||
|     sc->elst_count = i; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @@ -3746,6 +3763,7 @@ static int mov_read_close(AVFormatContext *s) | ||||
|         av_freep(&sc->keyframes); | ||||
|         av_freep(&sc->stts_data); | ||||
|         av_freep(&sc->stps_data); | ||||
|         av_freep(&sc->elst_data); | ||||
|         av_freep(&sc->rap_group); | ||||
|         av_freep(&sc->display_matrix); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user