mirror of https://git.ffmpeg.org/ffmpeg.git
lavc/audiotoolboxenc: fix noise in encoded audio
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. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
29b5f3115d
commit
677701c6b3
|
@ -48,6 +48,8 @@ typedef struct ATDecodeContext {
|
||||||
AudioFrameQueue afq;
|
AudioFrameQueue afq;
|
||||||
int eof;
|
int eof;
|
||||||
int frame_size;
|
int frame_size;
|
||||||
|
|
||||||
|
AVFrame* encoding_frame;
|
||||||
} ATDecodeContext;
|
} ATDecodeContext;
|
||||||
|
|
||||||
static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
|
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);
|
ff_af_queue_init(avctx, &at->afq);
|
||||||
|
|
||||||
|
at->encoding_frame = av_frame_alloc();
|
||||||
|
if (!at->encoding_frame)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,6 +459,7 @@ static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_pac
|
||||||
AVCodecContext *avctx = inctx;
|
AVCodecContext *avctx = inctx;
|
||||||
ATDecodeContext *at = avctx->priv_data;
|
ATDecodeContext *at = avctx->priv_data;
|
||||||
AVFrame *frame;
|
AVFrame *frame;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!at->frame_queue.available) {
|
if (!at->frame_queue.available) {
|
||||||
if (at->eof) {
|
if (at->eof) {
|
||||||
|
@ -475,6 +482,13 @@ static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_pac
|
||||||
if (*nb_packets > frame->nb_samples)
|
if (*nb_packets > frame->nb_samples)
|
||||||
*nb_packets = frame->nb_samples;
|
*nb_packets = frame->nb_samples;
|
||||||
|
|
||||||
|
av_frame_unref(at->encoding_frame);
|
||||||
|
ret = av_frame_ref(at->encoding_frame, frame);
|
||||||
|
if (ret < 0) {
|
||||||
|
*nb_packets = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
|
ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -565,6 +579,7 @@ static av_cold int ffat_close_encoder(AVCodecContext *avctx)
|
||||||
ff_bufqueue_discard_all(&at->frame_queue);
|
ff_bufqueue_discard_all(&at->frame_queue);
|
||||||
ff_bufqueue_discard_all(&at->used_frame_queue);
|
ff_bufqueue_discard_all(&at->used_frame_queue);
|
||||||
ff_af_queue_close(&at->afq);
|
ff_af_queue_close(&at->afq);
|
||||||
|
av_frame_free(&at->encoding_frame);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue