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

2016-12-01 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.

Test sample: https://www.dropbox.com/s/qz0ort4znqq9jdy/attachment_video.mov?dl=0

Run `ffmpeg -i attachment_video.mov -f image2 frames%03d.png`. The git-master 
version cannot decode frame 327 to 330 because a wrong stsd is used. After 
applying this patch they are decoded correctly.

Signed-off-by: Jiejun Zhang 
---
 libavformat/isom.h |  13 +-
 libavformat/mov.c  | 125 +
 2 files changed, 109 insertions(+), 29 deletions(-)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 02bfedd..141237a 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -115,6 +115,14 @@ typedef struct MOVFragmentIndex {
 MOVFragmentIndexItem *items;
 } MOVFragmentIndex;
 
+/**
+ * An entry for: stsd changes to `stsd_id` at sample `sample_index` (inclusive)
+ */
+typedef struct MOVStsdChangeEntry {
+int64_t sample_index;
+int stsd_id;
+} MOVStsdChangeEntry;
+
 typedef struct MOVStreamContext {
 AVIOContext *pb;
 int pb_is_copied;
@@ -128,12 +136,13 @@ typedef struct MOVStreamContext {
 MOVStts *ctts_data;
 unsigned int stsc_count;
 MOVStsc *stsc_data;
-int stsc_index;
-int stsc_sample;
 unsigned int stps_count;
 unsigned *stps_data;  ///< partial sync sample for mpeg-2 open gop
 MOVElst *elst_data;
 unsigned int elst_count;
+MOVStsdChangeEntry *stsd_change_data;
+int stsd_change_count;
+int stsd_change_index;
 int ctts_index;
 int ctts_sample;
 unsigned int sample_size; ///< may contain value calculated from stsd or 
value from stsz atom
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 88a79da..e5f7f72 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2901,6 +2901,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.
@@ -2984,6 +3013,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;
 
 if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) {
 return;
@@ -3012,6 +3043,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",
@@ -3073,6 +3109,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;
 
@@ -3176,12 +3226,36 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
 }
 }
 
-if (add_index_entr

[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 v2] libavformat/mov: fix multiple stsd handling of files with edit list, fix #6584

2017-08-16 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 c02caf6719..628cf31cec 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2926,6 +2926,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.
@@ -3058,6 +3087,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;
 
@@ -3094,6 +3125,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",
@@ -3156,6 +3192,20 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
 }
 current = e_old + index;
 
+// adjust stsd index
+int time_sample = 0;
+for (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;
 
@@ -3268,12 +3318,35 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
 }
 }
 
-if (add_index_entry(st, current->pos, edit_list_dts

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

2017-08-16 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  | 120 +
 2 files changed, 104 insertions(+), 30 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 c02caf6719..e775056c90 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2926,6 +2926,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.
@@ -3058,6 +3087,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;
 
@@ -3094,6 +3125,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",
@@ -3156,6 +3192,20 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
 }
 current = e_old + index;
 
+// adjust stsd index
+int time_sample = 0;
+for (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;
 
@@ -3268,12 +3318,35 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
 }
 }
 
-if (add_index_entry(st, current->pos, edit_list_dt

[FFmpeg-devel] [PATCH] lavc/audiotoolboxenc: fix noise in encoded audio

2018-01-01 Thread zhangjiejun1992
From: Jiejun Zhang 

This fixes #6940
---
 libavcodec/audiotoolboxenc.c | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
index 71885d1530..b70375a692 100644
--- a/libavcodec/audiotoolboxenc.c
+++ b/libavcodec/audiotoolboxenc.c
@@ -48,6 +48,9 @@ typedef struct ATDecodeContext {
 AudioFrameQueue afq;
 int eof;
 int frame_size;
+
+uint8_t* audio_data_buf;
+uint32_t audio_data_buf_size;
 } ATDecodeContext;
 
 static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
@@ -442,6 +445,9 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
 
 ff_af_queue_init(avctx, &at->afq);
 
+at->audio_data_buf_size = 0;
+at->audio_data_buf = NULL;
+
 return 0;
 }
 
@@ -471,7 +477,15 @@ static OSStatus ffat_encode_callback(AudioConverterRef 
converter, UInt32 *nb_pac
 data->mBuffers[0].mDataByteSize   = frame->nb_samples *
 
av_get_bytes_per_sample(avctx->sample_fmt) *
 avctx->channels;
-data->mBuffers[0].mData   = frame->data[0];
+if (at->audio_data_buf_size < data->mBuffers[0].mDataByteSize) {
+av_log(avctx, AV_LOG_INFO, "Increasing audio data buffer size to %u",
+   data->mBuffers[0].mDataByteSize);
+av_free(at->audio_data_buf);
+at->audio_data_buf_size = data->mBuffers[0].mDataByteSize;
+at->audio_data_buf = av_malloc(at->audio_data_buf_size);
+}
+memcpy(at->audio_data_buf, frame->data[0], 
data->mBuffers[0].mDataByteSize);
+data->mBuffers[0].mData   = at->audio_data_buf;
 if (*nb_packets > frame->nb_samples)
 *nb_packets = frame->nb_samples;
 
@@ -565,6 +579,10 @@ static av_cold int ffat_close_encoder(AVCodecContext 
*avctx)
 ff_bufqueue_discard_all(&at->frame_queue);
 ff_bufqueue_discard_all(&at->used_frame_queue);
 ff_af_queue_close(&at->afq);
+if (at->audio_data_buf_size > 0) {
+at->audio_data_buf_size = 0;
+av_free(at->audio_data_buf);
+}
 return 0;
 }
 
-- 
2.14.3 (Apple Git-98)

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


[FFmpeg-devel] [PATCH] lavc/audiotoolboxenc: fix noise in encoded audio

2018-01-02 Thread zhangjiejun1992
From: Jiejun Zhang 

This fixes #6940
---
 libavcodec/audiotoolboxenc.c | 34 +-
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
index 71885d1530..0c1e5feadc 100644
--- a/libavcodec/audiotoolboxenc.c
+++ b/libavcodec/audiotoolboxenc.c
@@ -48,6 +48,9 @@ typedef struct ATDecodeContext {
 AudioFrameQueue afq;
 int eof;
 int frame_size;
+
+uint8_t* audio_data_buf;
+uint32_t audio_data_buf_size;
 } ATDecodeContext;
 
 static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
@@ -442,6 +445,9 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
 
 ff_af_queue_init(avctx, &at->afq);
 
+at->audio_data_buf_size = 0;
+at->audio_data_buf = NULL;
+
 return 0;
 }
 
@@ -465,13 +471,27 @@ static OSStatus ffat_encode_callback(AudioConverterRef 
converter, UInt32 *nb_pac
 }
 
 frame = ff_bufqueue_get(&at->frame_queue);
-
+int audio_data_size = frame->nb_samples *
+  av_get_bytes_per_sample(avctx->sample_fmt) *
+  avctx->channels;
+if (at->audio_data_buf_size < audio_data_size) {
+av_log(avctx, AV_LOG_INFO, "Increasing audio data buffer size to %d\n",
+   audio_data_size);
+av_free(at->audio_data_buf);
+at->audio_data_buf_size = audio_data_size;
+at->audio_data_buf = av_malloc(at->audio_data_buf_size);
+if (!at->audio_data_buf) {
+at->audio_data_buf_size = 0;
+data->mNumberBuffers = 0;
+*nb_packets = 0;
+return AVERROR(ENOMEM);
+}
+}
 data->mNumberBuffers  = 1;
 data->mBuffers[0].mNumberChannels = avctx->channels;
-data->mBuffers[0].mDataByteSize   = frame->nb_samples *
-
av_get_bytes_per_sample(avctx->sample_fmt) *
-avctx->channels;
-data->mBuffers[0].mData   = frame->data[0];
+data->mBuffers[0].mDataByteSize   = audio_data_size;
+data->mBuffers[0].mData   = at->audio_data_buf;
+memcpy(at->audio_data_buf, frame->data[0], 
data->mBuffers[0].mDataByteSize);
 if (*nb_packets > frame->nb_samples)
 *nb_packets = frame->nb_samples;
 
@@ -565,6 +585,10 @@ static av_cold int ffat_close_encoder(AVCodecContext 
*avctx)
 ff_bufqueue_discard_all(&at->frame_queue);
 ff_bufqueue_discard_all(&at->used_frame_queue);
 ff_af_queue_close(&at->afq);
+if (at->audio_data_buf_size > 0) {
+at->audio_data_buf_size = 0;
+av_free(at->audio_data_buf);
+}
 return 0;
 }
 
-- 
2.14.3 (Apple Git-98)

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


[FFmpeg-devel] [PATCH v2] lavc/audiotoolboxenc: fix noise in encoded audio

2018-01-02 Thread zhangjiejun1992
From: Jiejun Zhang 

This fixes #6940

Although undocumented, AudioToolbox seems to require the data supplied
by the callback (i.e. ffat_encode_callback) being unchanged until the
next time the callback is called. In the old implementation, the
AVBuffer backing the frame is recycled after the frame is freed, and
somebody else (maybe the decoder) will write into the AVBuffer and
change the data. AudioToolbox then encodes some wrong data and noise
is produced. Copying the data to a separate buffer solves this
problem.
---
 libavcodec/audiotoolboxenc.c | 32 +++-
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
index 71885d1530..dcac88cdde 100644
--- a/libavcodec/audiotoolboxenc.c
+++ b/libavcodec/audiotoolboxenc.c
@@ -48,6 +48,9 @@ typedef struct ATDecodeContext {
 AudioFrameQueue afq;
 int eof;
 int frame_size;
+
+uint8_t* audio_data_buf;
+uint32_t audio_data_buf_size;
 } ATDecodeContext;
 
 static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
@@ -442,6 +445,9 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
 
 ff_af_queue_init(avctx, &at->afq);
 
+at->audio_data_buf_size = 0;
+at->audio_data_buf = NULL;
+
 return 0;
 }
 
@@ -465,13 +471,27 @@ static OSStatus ffat_encode_callback(AudioConverterRef 
converter, UInt32 *nb_pac
 }
 
 frame = ff_bufqueue_get(&at->frame_queue);
-
+int audio_data_size = frame->nb_samples *
+  av_get_bytes_per_sample(avctx->sample_fmt) *
+  avctx->channels;
+if (at->audio_data_buf_size < audio_data_size) {
+av_log(avctx, AV_LOG_INFO, "Increasing audio data buffer size to %d\n",
+   audio_data_size);
+av_free(at->audio_data_buf);
+at->audio_data_buf_size = audio_data_size;
+at->audio_data_buf = av_malloc(at->audio_data_buf_size);
+if (!at->audio_data_buf) {
+at->audio_data_buf_size = 0;
+data->mNumberBuffers = 0;
+*nb_packets = 0;
+return AVERROR(ENOMEM);
+}
+}
 data->mNumberBuffers  = 1;
 data->mBuffers[0].mNumberChannels = avctx->channels;
-data->mBuffers[0].mDataByteSize   = frame->nb_samples *
-
av_get_bytes_per_sample(avctx->sample_fmt) *
-avctx->channels;
-data->mBuffers[0].mData   = frame->data[0];
+data->mBuffers[0].mDataByteSize   = audio_data_size;
+data->mBuffers[0].mData   = at->audio_data_buf;
+memcpy(at->audio_data_buf, frame->data[0], 
data->mBuffers[0].mDataByteSize);
 if (*nb_packets > frame->nb_samples)
 *nb_packets = frame->nb_samples;
 
@@ -565,6 +585,8 @@ static av_cold int ffat_close_encoder(AVCodecContext *avctx)
 ff_bufqueue_discard_all(&at->frame_queue);
 ff_bufqueue_discard_all(&at->used_frame_queue);
 ff_af_queue_close(&at->afq);
+at->audio_data_buf_size = 0;
+av_freep(&at->audio_data_buf);
 return 0;
 }
 
-- 
2.14.3 (Apple Git-98)

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


[FFmpeg-devel] [PATCH v3] lavc/audiotoolboxenc: fix noise in encoded audio

2018-01-02 Thread zhangjiejun1992
From: Jiejun Zhang 

This fixes #6940

Although undocumented, AudioToolbox seems to require the data supplied
by the callback (i.e. ffat_encode_callback) being unchanged until the
next time the callback is called. In the old implementation, the
AVBuffer backing the frame is recycled after the frame is freed, and
somebody else (maybe the decoder) will write into the AVBuffer and
change the data. AudioToolbox then encodes some wrong data and noise
is produced. Retaining a frame reference solves this problem.
---
 libavcodec/audiotoolboxenc.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
index 71885d1530..5d3a746348 100644
--- a/libavcodec/audiotoolboxenc.c
+++ b/libavcodec/audiotoolboxenc.c
@@ -48,6 +48,8 @@ typedef struct ATDecodeContext {
 AudioFrameQueue afq;
 int eof;
 int frame_size;
+
+AVFrame* encoding_frame;
 } ATDecodeContext;
 
 static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
@@ -442,6 +444,10 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
 
 ff_af_queue_init(avctx, &at->afq);
 
+at->encoding_frame = av_frame_alloc();
+if (!at->encoding_frame)
+return AVERROR(ENOMEM);
+
 return 0;
 }
 
@@ -453,6 +459,7 @@ static OSStatus ffat_encode_callback(AudioConverterRef 
converter, UInt32 *nb_pac
 AVCodecContext *avctx = inctx;
 ATDecodeContext *at = avctx->priv_data;
 AVFrame *frame;
+int ret;
 
 if (!at->frame_queue.available) {
 if (at->eof) {
@@ -475,6 +482,10 @@ static OSStatus ffat_encode_callback(AudioConverterRef 
converter, UInt32 *nb_pac
 if (*nb_packets > frame->nb_samples)
 *nb_packets = frame->nb_samples;
 
+av_frame_unref(at->encoding_frame);
+if ((ret = av_frame_ref(at->encoding_frame, frame)) < 0)
+return ret;
+
 ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
 
 return 0;
@@ -565,6 +576,7 @@ static av_cold int ffat_close_encoder(AVCodecContext *avctx)
 ff_bufqueue_discard_all(&at->frame_queue);
 ff_bufqueue_discard_all(&at->used_frame_queue);
 ff_af_queue_close(&at->afq);
+av_frame_free(&at->encoding_frame);
 return 0;
 }
 
-- 
2.14.3 (Apple Git-98)

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


[FFmpeg-devel] [PATCH v4] lavc/audiotoolboxenc: fix noise in encoded audio

2018-01-02 Thread zhangjiejun1992
From: Jiejun Zhang 

This fixes #6940

Although undocumented, AudioToolbox seems to require the data supplied
by the callback (i.e. ffat_encode_callback) being unchanged until the
next time the callback is called. In the old implementation, the
AVBuffer backing the frame is recycled after the frame is freed, and
somebody else (maybe the decoder) will write into the AVBuffer and
change the data. AudioToolbox then encodes some wrong data and noise
is produced. Retaining a frame reference solves this problem.
---
 libavcodec/audiotoolboxenc.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
index 71885d1530..4d8130af96 100644
--- a/libavcodec/audiotoolboxenc.c
+++ b/libavcodec/audiotoolboxenc.c
@@ -48,6 +48,8 @@ typedef struct ATDecodeContext {
 AudioFrameQueue afq;
 int eof;
 int frame_size;
+
+AVFrame* encoding_frame;
 } ATDecodeContext;
 
 static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
@@ -442,6 +444,10 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
 
 ff_af_queue_init(avctx, &at->afq);
 
+at->encoding_frame = av_frame_alloc();
+if (!at->encoding_frame)
+return AVERROR(ENOMEM);
+
 return 0;
 }
 
@@ -453,6 +459,7 @@ static OSStatus ffat_encode_callback(AudioConverterRef 
converter, UInt32 *nb_pac
 AVCodecContext *avctx = inctx;
 ATDecodeContext *at = avctx->priv_data;
 AVFrame *frame;
+int ret;
 
 if (!at->frame_queue.available) {
 if (at->eof) {
@@ -475,6 +482,12 @@ static OSStatus ffat_encode_callback(AudioConverterRef 
converter, UInt32 *nb_pac
 if (*nb_packets > frame->nb_samples)
 *nb_packets = frame->nb_samples;
 
+av_frame_unref(at->encoding_frame);
+if ((ret = av_frame_ref(at->encoding_frame, frame)) < 0) {
+*nb_packets = 0;
+return ret;
+}
+
 ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
 
 return 0;
@@ -565,6 +578,7 @@ static av_cold int ffat_close_encoder(AVCodecContext *avctx)
 ff_bufqueue_discard_all(&at->frame_queue);
 ff_bufqueue_discard_all(&at->used_frame_queue);
 ff_af_queue_close(&at->afq);
+av_frame_free(&at->encoding_frame);
 return 0;
 }
 
-- 
2.14.3 (Apple Git-98)

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