mp_image: factor buffer referencing

Reduce the trivial but still annoying code duplication in
mp_image_new_ref(), which has to create new buffer references and deal
with possible failure of creating them. The tricky part is that if
creating a reference fails, we must set the target to NULL, so that
unreferencing the failed new mp_image reference does not release the
buffer references of the original mp_image. For the same reason, the
code can't jump to error handling when it can't create a new reference,
and has to set a flag instead.
This commit is contained in:
wm4 2018-01-29 13:47:05 +01:00 committed by Kevin Mitchell
parent 0366ba2531
commit 3d367e009c
1 changed files with 15 additions and 17 deletions

View File

@ -296,6 +296,16 @@ void mp_image_unref_data(struct mp_image *img)
}
}
static bool ref_buffer(AVBufferRef **dst)
{
if (*dst) {
*dst = av_buffer_ref(*dst);
if (!*dst)
return false;
}
return true;
}
// Return a new reference to img. The returned reference is owned by the caller,
// while img is left untouched.
struct mp_image *mp_image_new_ref(struct mp_image *img)
@ -311,24 +321,12 @@ struct mp_image *mp_image_new_ref(struct mp_image *img)
*new = *img;
bool fail = false;
for (int p = 0; p < MP_MAX_PLANES; p++) {
if (new->bufs[p]) {
new->bufs[p] = av_buffer_ref(new->bufs[p]);
if (!new->bufs[p])
fail = true;
}
}
if (new->hwctx) {
new->hwctx = av_buffer_ref(new->hwctx);
if (!new->hwctx)
fail = true;
}
for (int p = 0; p < MP_MAX_PLANES; p++)
fail |= !ref_buffer(&new->bufs[p]);
fail |= !ref_buffer(&new->hwctx);
fail |= !ref_buffer(&new->icc_profile);
if (new->icc_profile) {
new->icc_profile = av_buffer_ref(new->icc_profile);
if (!new->icc_profile)
fail = true;
}
if (!fail)
return new;