1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-16 12:17:12 +00:00

af_lavcac3enc: fix memory leak on no-op

Simply returning out of this function leaks avpkt, need to always "goto
done".

Rewrite the logic a bit to make it more clear what's going on (IMO).

Fixes #9593
This commit is contained in:
Niklas Haas 2021-12-13 13:26:34 +01:00 committed by Niklas Haas
parent 584ab29c88
commit 0bb15c7a13

View File

@ -163,46 +163,47 @@ static void process(struct mp_filter *f)
break; break;
if (lavc_ret < 0 && lavc_ret != AVERROR(EAGAIN)) { if (lavc_ret < 0 && lavc_ret != AVERROR(EAGAIN)) {
MP_FATAL(f, "Encode failed (receive).\n"); MP_FATAL(f, "Encode failed (receive).\n");
goto done; goto error;
} }
} }
AVFrame *frame = NULL; AVFrame *frame = NULL;
struct mp_frame input = mp_pin_out_read(s->in_pin); struct mp_frame input = mp_pin_out_read(s->in_pin);
// The following code assumes no sample data buffering in the encoder. // The following code assumes no sample data buffering in the encoder.
if (input.type == MP_FRAME_EOF) { switch (input.type) {
case MP_FRAME_NONE:
goto done; // no data yet
case MP_FRAME_EOF:
mp_pin_in_write(f->ppins[1], input); mp_pin_in_write(f->ppins[1], input);
return; goto done;
} else if (input.type == MP_FRAME_AUDIO) { case MP_FRAME_AUDIO:
TA_FREEP(&s->in_frame); TA_FREEP(&s->in_frame);
s->in_frame = input.data; s->in_frame = input.data;
frame = mp_frame_to_av(input, NULL); frame = mp_frame_to_av(input, NULL);
if (!frame) if (!frame)
goto done; goto error;
if (mp_aframe_get_channels(s->in_frame) < s->opts->min_channel_num) { if (mp_aframe_get_channels(s->in_frame) < s->opts->min_channel_num) {
// Just pass it through. // Just pass it through.
s->in_frame = NULL; s->in_frame = NULL;
mp_pin_in_write(f->ppins[1], input); mp_pin_in_write(f->ppins[1], input);
return; goto done;
} }
if (!mp_aframe_config_equals(s->in_frame, s->cur_format)) { if (!mp_aframe_config_equals(s->in_frame, s->cur_format)) {
if (!reinit(f)) if (!reinit(f))
goto done; goto error;
} }
} else if (input.type) { break;
goto done; default: goto error; // unexpected packet type
} else {
return; // no data yet
} }
int lavc_ret = avcodec_send_frame(s->lavc_actx, frame); int lavc_ret = avcodec_send_frame(s->lavc_actx, frame);
av_frame_free(&frame); av_frame_free(&frame);
if (lavc_ret < 0 && lavc_ret != AVERROR(EAGAIN)) { if (lavc_ret < 0 && lavc_ret != AVERROR(EAGAIN)) {
MP_FATAL(f, "Encode failed (send).\n"); MP_FATAL(f, "Encode failed (send).\n");
goto done; goto error;
} }
} }
if (!s->in_frame) if (!s->in_frame)
goto done; goto error;
out = mp_aframe_create(); out = mp_aframe_create();
mp_aframe_set_format(out, AF_FORMAT_S_AC3); mp_aframe_set_format(out, AF_FORMAT_S_AC3);
@ -210,7 +211,7 @@ static void process(struct mp_filter *f)
mp_aframe_set_rate(out, 48000); mp_aframe_set_rate(out, 48000);
if (mp_aframe_pool_allocate(s->out_pool, out, s->out_samples) < 0) if (mp_aframe_pool_allocate(s->out_pool, out, s->out_samples) < 0)
goto done; goto error;
int sstride = mp_aframe_get_sstride(out); int sstride = mp_aframe_get_sstride(out);
@ -239,7 +240,7 @@ static void process(struct mp_filter *f)
uint8_t **planes = mp_aframe_get_data_rw(out); uint8_t **planes = mp_aframe_get_data_rw(out);
if (!planes) if (!planes)
goto done; goto error;
char *buf = planes[0]; char *buf = planes[0];
memcpy(buf, hdr, header_len); memcpy(buf, hdr, header_len);
memcpy(buf + header_len, pkt.data, pkt.size); memcpy(buf + header_len, pkt.data, pkt.size);
@ -250,8 +251,10 @@ static void process(struct mp_filter *f)
mp_pin_in_write(f->ppins[1], MAKE_FRAME(MP_FRAME_AUDIO, out)); mp_pin_in_write(f->ppins[1], MAKE_FRAME(MP_FRAME_AUDIO, out));
out = NULL; out = NULL;
err = 0;
done: done:
err = false;
// fall through
error:
av_packet_unref(&pkt); av_packet_unref(&pkt);
talloc_free(out); talloc_free(out);
if (err) if (err)