[FFmpeg-devel] [PATCH] libavformat/mov: fix multiple stsd handling of files with edit list, fix #6584

2017-08-12 Thread zhangjiejun1992
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

[FFmpeg-devel] [PATCH] libavcodec: fix field_order labelling

2017-08-12 Thread Dave Rice
Hello all,
This issue originated in this thread 
https://github.com/amiaopensource/vrecord/issues/170. On Field Order, in the 
QuickTime specification at 
https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
 (and similarly in the Matroska specification which adopted similar language) 
it states the following meanings for field order values:

> 9 – B is displayed earliest, T is stored first in the file. 14 – T is 
> displayed earliest, B is stored first in the file.

 This definition is contradicted by other Apple documentation such as 
https://developer.apple.com/library/content/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG10-THE__FIEL__IMAGEDESCRIPTION_EXTENSION__FIELD_FRAME_INFORMATION.
 

An Apple engineer confirmed that the QuickTime specification’s definitions for 
those Field Order values is wrong and does not match Apple’s (of FFmpeg’s) 
practice, see 
https://github.com/amiaopensource/vrecord/issues/170#issuecomment-321937668.

However I think that some of the commenting in ffmpeg is based upon the 
inaccurate definitions from Apple. For instance, in that thread David Singer 
confirms:

> Ah, not quite. 1 and 6 are indeed 'planar' (all of one field before all of 
> the other). They don't concern us. Both 9 and 14 are stored in spatial order 
> (i.e. you could do terrible de-interlacing by simply displaying the buffer as 
> a frame), and the 9 or 14 value tells you which field is to be displayed 
> first.
> 
> 9 – T is earlier than B. 14 – B is earlier than T

mov.c associates AV_FIELD_TB with 9 and AV_FIELD_BT with 14 (similar 
associations in matroska.h), but avcodec.h states:

> AV_FIELD_TB,  //< Top coded first, bottom displayed first
> AV_FIELD_BT,  //< Bottom coded first, bottom displayed first

IMHO in both cases of AV_FIELD_TB and AV_FIELD_BT the coding should be referred 
as interleaved rather than ‘bottom coded first’ or ‘top coded first’. In the 
case of AV_FIELD_TT and AV_FIELD_BB the fields are stored as planar images 
where storage order is notable, but with TB and BT the fields are interleaved.

Also utils.c associates these field order values with the following labels:

> AV_FIELD_TB  -> "top coded first (swapped)";
> AV_FIELD_BT -> "bottom coded first (swapped)";

From my reading, I infer that "top coded first (swapped)” means "top coded 
first, bottom displayed first”; however in practice from files generated by 
QuickTime and FFmpeg files with a value of TB have the top field displayed 
first, so I think the labels are swapped. In the patch below I suggest using 
“top first (interleaved)” for TB and “bottom first (interleaved)” for BT.

Comments?


From de871b3fa891fa0ae6856461c1f8305cc889cde7 Mon Sep 17 00:00:00 2001
From: Dave Rice 
Date: Sat, 12 Aug 2017 12:30:43 -0400
Subject: [PATCH] libavcodec: fix field_order labelling

---
 libavcodec/avcodec.h | 4 ++--
 libavcodec/utils.c   | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index c594993766..37c39072b3 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1726,8 +1726,8 @@ enum AVFieldOrder {
 AV_FIELD_PROGRESSIVE,
 AV_FIELD_TT,  //< Top coded_first, top displayed first
 AV_FIELD_BB,  //< Bottom coded first, bottom displayed first
-AV_FIELD_TB,  //< Top coded first, bottom displayed first
-AV_FIELD_BT,  //< Bottom coded first, top displayed first
+AV_FIELD_TB,  //< Interleaved coding, top displayed first
+AV_FIELD_BT,  //< Interleaved coding, bottom displayed first
 };
 
 /**
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 1336e921c9..926c964846 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1406,9 +1406,9 @@ void avcodec_string(char *buf, int buf_size, 
AVCodecContext *enc, int encode)
 else if (enc->field_order == AV_FIELD_BB)
 field_order = "bottom first";
 else if (enc->field_order == AV_FIELD_TB)
-field_order = "top coded first (swapped)";
+field_order = "top first (interleaved)";
 else if (enc->field_order == AV_FIELD_BT)
-field_order = "bottom coded first (swapped)";
+field_order = "bottom first (interleaved)";
 
 av_strlcatf(detail, sizeof(detail), "%s, ", field_order);
 }
-- 
2.13.1


Thanks much,
Dave Rice


___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/3] avcodec/ffv1dec_template: Fix undefined shift

2017-08-12 Thread Michael Niedermayer
On Fri, Aug 11, 2017 at 11:21:21PM +0200, Michael Niedermayer wrote:
> Fixes: runtime error: left shift of negative value -127
> Fixes: 2834/clusterfuzz-testcase-minimized-5988039123795968
> 
> Found-by: continuous fuzzing process 
> https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
> Signed-off-by: Michael Niedermayer 
> ---
>  libavcodec/ffv1dec_template.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

patchset applied

[...]
-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

When you are offended at any man's fault, turn to yourself and study your
own failings. Then you will forget your anger. -- Epictetus


signature.asc
Description: Digital signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel