summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/decode/vd_lavc.c2
-rw-r--r--video/filter/vf.c8
-rw-r--r--video/filter/vf.h2
-rw-r--r--video/filter/vf_divtc.c5
-rw-r--r--video/filter/vf_dlopen.c8
-rw-r--r--video/filter/vf_eq.c6
-rw-r--r--video/filter/vf_expand.c2
-rw-r--r--video/filter/vf_ilpack.c2
-rw-r--r--video/filter/vf_lavfi.c4
-rw-r--r--video/filter/vf_mirror.c2
-rw-r--r--video/filter/vf_noise.c2
-rw-r--r--video/filter/vf_phase.c2
-rw-r--r--video/filter/vf_pp.c2
-rw-r--r--video/filter/vf_pullup.c2
-rw-r--r--video/filter/vf_scale.c2
-rw-r--r--video/filter/vf_softpulldown.c15
-rw-r--r--video/filter/vf_stereo3d.c2
-rw-r--r--video/filter/vf_sub.c2
-rw-r--r--video/filter/vf_vapoursynth.c3
-rw-r--r--video/filter/vf_vdpaupp.c4
-rw-r--r--video/image_writer.c4
-rw-r--r--video/mp_image.c38
-rw-r--r--video/mp_image.h2
-rw-r--r--video/mp_image_pool.c22
-rw-r--r--video/mp_image_pool.h4
-rw-r--r--video/out/gl_common.c2
-rw-r--r--video/out/gl_video.c17
-rw-r--r--video/out/vo.c2
-rw-r--r--video/out/vo.h2
-rw-r--r--video/out/vo_corevideo.c3
-rw-r--r--video/out/vo_direct3d.c5
-rw-r--r--video/out/vo_image.c4
-rw-r--r--video/out/vo_lavc.c2
-rw-r--r--video/out/vo_opengl_old.c2
-rw-r--r--video/out/vo_sdl.c2
-rw-r--r--video/out/vo_vaapi.c10
-rw-r--r--video/out/vo_vdpau.c3
-rw-r--r--video/out/vo_x11.c3
-rw-r--r--video/out/vo_xv.c3
-rw-r--r--video/vaapi.c3
-rw-r--r--video/vdpau.c10
-rw-r--r--video/vdpau_mixer.c6
42 files changed, 175 insertions, 51 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 5af70aebe5..721461fdb7 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -628,7 +628,7 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
struct mp_image *mpi = mp_image_from_av_frame(ctx->pic);
av_frame_unref(ctx->pic);
if (!mpi)
- return 0;
+ return 0; // mpi==NULL, or OOM
assert(mpi->planes[0] || mpi->planes[3]);
mp_image_set_params(mpi, &params);
diff --git a/video/filter/vf.c b/video/filter/vf.c
index 5326483444..045b68f774 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -200,17 +200,19 @@ struct mp_image *vf_alloc_out_image(struct vf_instance *vf)
struct mp_image_params *p = &vf->fmt_out;
assert(p->imgfmt);
struct mp_image *img = mp_image_pool_get(vf->out_pool, p->imgfmt, p->w, p->h);
- vf_fix_img_params(img, p);
+ if (img)
+ vf_fix_img_params(img, p);
return img;
}
-void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img)
+// Returns false on failure; then the image can't be written to.
+bool vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img)
{
struct mp_image_params *p = &vf->fmt_out;
assert(p->imgfmt);
assert(p->imgfmt == img->imgfmt);
assert(p->w == img->w && p->h == img->h);
- mp_image_pool_make_writeable(vf->out_pool, img);
+ return mp_image_pool_make_writeable(vf->out_pool, img);
}
//============================================================================
diff --git a/video/filter/vf.h b/video/filter/vf.h
index bfe573e618..71dcb699c2 100644
--- a/video/filter/vf.h
+++ b/video/filter/vf.h
@@ -155,7 +155,7 @@ void vf_print_filter_chain(struct vf_chain *c, int msglevel,
// Filter internal API
struct mp_image *vf_alloc_out_image(struct vf_instance *vf);
-void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img);
+bool vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img);
void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img);
// default wrappers:
diff --git a/video/filter/vf_divtc.c b/video/filter/vf_divtc.c
index e93950ff6f..093aa2883b 100644
--- a/video/filter/vf_divtc.c
+++ b/video/filter/vf_divtc.c
@@ -221,6 +221,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
mp_image_unrefp(&p->buffer);
p->buffer = mp_image_alloc(mpi->imgfmt, mpi->w, mpi->h);
talloc_steal(vf, p->buffer);
+ if (!p->buffer)
+ return NULL; // skip on OOM
}
struct mp_image *dmpi = p->buffer;
@@ -317,7 +319,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
if(p->deghost>0)
{
imgop(copyop, dmpi, mpi, 0);
- vf_make_out_image_writeable(vf, mpi);
+ if (!vf_make_out_image_writeable(vf, mpi))
+ return NULL; // oom: eof
imgop(deghost_plane, mpi, dmpi, p->deghost);
mpi->pts = vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0);
diff --git a/video/filter/vf_dlopen.c b/video/filter/vf_dlopen.c
index 9f9cd20318..78bde8eb64 100644
--- a/video/filter/vf_dlopen.c
+++ b/video/filter/vf_dlopen.c
@@ -160,8 +160,10 @@ static int config(struct vf_instance *vf,
vf->priv->outpic[i] =
mp_image_alloc(vf->priv->out_width, vf->priv->out_height,
vf->priv->outfmt);
- set_imgprop(&vf->priv->filter.outpic[i], vf->priv->outpic[i]);
+ if (!vf->priv->outpic[i])
+ return 0; // OOM
talloc_steal(vf, vf->priv->outpic[i]);
+ set_imgprop(&vf->priv->filter.outpic[i], vf->priv->outpic[i]);
}
return vf_next_config(vf, vf->priv->out_width,
@@ -235,6 +237,10 @@ static int filter(struct vf_instance *vf, struct mp_image *mpi)
for (int n = 0; n < vf->priv->out_cnt; n++) {
out[n] = vf_alloc_out_image(vf);
+ if (!out[n]) {
+ talloc_free(mpi);
+ return -1;
+ }
mp_image_copy_attributes(out[n], mpi);
set_imgprop(&vf->priv->filter.outpic[n], out[n]);
}
diff --git a/video/filter/vf_eq.c b/video/filter/vf_eq.c
index 80eefab9b9..3381f248f7 100644
--- a/video/filter/vf_eq.c
+++ b/video/filter/vf_eq.c
@@ -216,8 +216,10 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *src)
}
struct mp_image *new = vf_alloc_out_image(vf);
- mp_image_copy(new, &dst);
- mp_image_copy_attributes(new, &dst);
+ if (new) {
+ mp_image_copy(new, &dst);
+ mp_image_copy_attributes(new, &dst);
+ }
talloc_free(src);
return new;
diff --git a/video/filter/vf_expand.c b/video/filter/vf_expand.c
index ba636ee279..4b8e89c88c 100644
--- a/video/filter/vf_expand.c
+++ b/video/filter/vf_expand.c
@@ -115,6 +115,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
return mpi;
struct mp_image *dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
struct mp_image cropped = *dmpi;
diff --git a/video/filter/vf_ilpack.c b/video/filter/vf_ilpack.c
index e27b846735..157f02eb7c 100644
--- a/video/filter/vf_ilpack.c
+++ b/video/filter/vf_ilpack.c
@@ -116,6 +116,8 @@ static void ilpack(unsigned char *dst, unsigned char *src[3],
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
mp_image_t *dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
diff --git a/video/filter/vf_lavfi.c b/video/filter/vf_lavfi.c
index 066afa28dd..c6f0783460 100644
--- a/video/filter/vf_lavfi.c
+++ b/video/filter/vf_lavfi.c
@@ -273,6 +273,8 @@ static AVFrame *mp_to_av(struct vf_instance *vf, struct mp_image *img)
uint64_t pts = img->pts == MP_NOPTS_VALUE ?
AV_NOPTS_VALUE : img->pts * av_q2d(av_inv_q(p->timebase_in));
AVFrame *frame = mp_image_to_av_frame_and_unref(img);
+ if (!frame)
+ return NULL; // OOM is (coincidentally) handled as EOF
frame->pts = pts;
frame->sample_aspect_ratio = p->par_in;
return frame;
@@ -282,6 +284,8 @@ static struct mp_image *av_to_mp(struct vf_instance *vf, AVFrame *av_frame)
{
struct vf_priv_s *p = vf->priv;
struct mp_image *img = mp_image_from_av_frame(av_frame);
+ if (!img)
+ return NULL; // OOM
img->pts = av_frame->pts == AV_NOPTS_VALUE ?
MP_NOPTS_VALUE : av_frame->pts * av_q2d(p->timebase_out);
av_frame_free(&av_frame);
diff --git a/video/filter/vf_mirror.c b/video/filter/vf_mirror.c
index 2cf9e4a78d..90316b2be9 100644
--- a/video/filter/vf_mirror.c
+++ b/video/filter/vf_mirror.c
@@ -58,6 +58,8 @@ static inline void mirror(uint8_t *dst, uint8_t *src, int bp, int w)
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
mp_image_t *dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
for (int p = 0; p < mpi->num_planes; p++) {
diff --git a/video/filter/vf_noise.c b/video/filter/vf_noise.c
index f612469b8d..025de86bfc 100644
--- a/video/filter/vf_noise.c
+++ b/video/filter/vf_noise.c
@@ -216,6 +216,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
struct mp_image *dmpi = mpi;
if (!mp_image_is_writeable(mpi)) {
dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
}
diff --git a/video/filter/vf_phase.c b/video/filter/vf_phase.c
index d0b6e33312..5d2179d92a 100644
--- a/video/filter/vf_phase.c
+++ b/video/filter/vf_phase.c
@@ -203,6 +203,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
enum mode mode;
struct mp_image *dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
int pw[MP_MAX_PLANES] = {0};
diff --git a/video/filter/vf_pp.c b/video/filter/vf_pp.c
index f60b8d8257..4acce1c272 100644
--- a/video/filter/vf_pp.c
+++ b/video/filter/vf_pp.c
@@ -89,6 +89,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
struct mp_image *dmpi = mpi;
if (!mp_image_is_writeable(mpi) || non_local) {
dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
}
diff --git a/video/filter/vf_pullup.c b/video/filter/vf_pullup.c
index 7e04722f1c..2d131842e7 100644
--- a/video/filter/vf_pullup.c
+++ b/video/filter/vf_pullup.c
@@ -204,6 +204,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
// safe thing and always copy. Code outside the filter might
// hold a buffer reference even if the filter chain is destroyed.
dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
struct mp_image data = *dmpi;
diff --git a/video/filter/vf_scale.c b/video/filter/vf_scale.c
index 0090eb775f..11c4044483 100644
--- a/video/filter/vf_scale.c
+++ b/video/filter/vf_scale.c
@@ -334,6 +334,8 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
struct mp_image *dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
mp_sws_scale(vf->priv->sws, dmpi, mpi);
diff --git a/video/filter/vf_softpulldown.c b/video/filter/vf_softpulldown.c
index afa6bf31f0..cc2742ee72 100644
--- a/video/filter/vf_softpulldown.c
+++ b/video/filter/vf_softpulldown.c
@@ -63,6 +63,8 @@ static int filter(struct vf_instance *vf, struct mp_image *mpi)
mp_image_unrefp(&p->buffer);
p->buffer = mp_image_alloc(mpi->imgfmt, mpi->w, mpi->h);
talloc_steal(vf, p->buffer);
+ if (!p->buffer)
+ goto failed; // OOM
}
mp_image_copy_attributes(p->buffer, mpi);
@@ -83,6 +85,8 @@ static int filter(struct vf_instance *vf, struct mp_image *mpi)
if (state == 0) {
struct mp_image *new = mp_image_new_ref(mpi);
+ if (!new)
+ goto failed;
new->pts = vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, mpi->pts, 0, 0, vf->priv->last_frame_duration);
vf_add_output_frame(vf, new);
vf->priv->out++;
@@ -93,13 +97,17 @@ static int filter(struct vf_instance *vf, struct mp_image *mpi)
} else {
copy_pic_field(dmpi, mpi, 1);
struct mp_image *new = mp_image_new_ref(mpi);
+ if (!new)
+ goto failed;
new->pts = vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, mpi->pts, 0, 0, vf->priv->last_frame_duration);
vf_add_output_frame(vf, new);
vf->priv->out++;
if (flags & MP_IMGFIELD_REPEAT_FIRST) {
struct mp_image *new2 = mp_image_new_ref(mpi);
- new2->pts = vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, mpi->pts, 0, 0, 3);
- vf_add_output_frame(vf, new2);
+ if (new2) {
+ new2->pts = vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, mpi->pts, 0, 0, 3);
+ vf_add_output_frame(vf, new2);
+ }
vf->priv->out++;
vf->priv->state=0;
} else {
@@ -116,6 +124,9 @@ static int filter(struct vf_instance *vf, struct mp_image *mpi)
talloc_free(mpi);
return 0;
+failed:
+ talloc_free(mpi);
+ return -1;
}
static int control(vf_instance_t *vf, int request, void *data)
diff --git a/video/filter/vf_stereo3d.c b/video/filter/vf_stereo3d.c
index 4126cd2f4e..15d2095f5d 100644
--- a/video/filter/vf_stereo3d.c
+++ b/video/filter/vf_stereo3d.c
@@ -294,6 +294,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
vf->priv->in.off_right;
struct mp_image *dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
out_off_left = vf->priv->out.row_left * dmpi->stride[0] +
diff --git a/video/filter/vf_sub.c b/video/filter/vf_sub.c
index 1f31d7b67f..e2d633dce7 100644
--- a/video/filter/vf_sub.c
+++ b/video/filter/vf_sub.c
@@ -96,6 +96,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
if (vf->priv->opt_top_margin || vf->priv->opt_bottom_margin) {
struct mp_image *dmpi = vf_alloc_out_image(vf);
+ if (!dmpi)
+ return NULL;
mp_image_copy_attributes(dmpi, mpi);
prepare_image(vf, dmpi, mpi);
talloc_free(mpi);
diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c
index 9d871c2173..8af3d02bb0 100644
--- a/video/filter/vf_vapoursynth.c
+++ b/video/filter/vf_vapoursynth.c
@@ -205,7 +205,8 @@ static void VS_CC vs_frame_done(void *userData, const VSFrameRef *f, int n,
MP_ERR(vf, "No PTS after filter at frame %d!\n", n);
res = mp_image_new_copy(&img);
p->vsapi->freeFrame(f);
- } else {
+ }
+ if (!res) {
p->failed = true;
MP_ERR(vf, "Filter error at frame %d: %s\n", n, errorMsg);
}
diff --git a/video/filter/vf_vdpaupp.c b/video/filter/vf_vdpaupp.c
index e0349c0c21..05cabf7998 100644
--- a/video/filter/vf_vdpaupp.c
+++ b/video/filter/vf_vdpaupp.c
@@ -70,6 +70,8 @@ static VdpVideoSurface ref_field(struct vf_priv_s *p,
if (!FIELD_VALID(p, pos))
return VDP_INVALID_HANDLE;
struct mp_image *mpi = mp_image_new_ref(p->buffered[pos / 2]);
+ if (!mpi)
+ return VDP_INVALID_HANDLE;
talloc_steal(frame, mpi);
return (uintptr_t)mpi->planes[3];
}
@@ -84,6 +86,8 @@ static bool output_field(struct vf_instance *vf, int pos)
return false;
struct mp_image *mpi = mp_vdpau_mixed_frame_create(p->buffered[pos / 2]);
+ if (!mpi)
+ return false; // skip output on OOM
struct mp_vdpau_mixer_frame *frame = mp_vdpau_mixed_frame_get(mpi);
frame->field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
diff --git a/video/image_writer.c b/video/image_writer.c
index f769fd9f27..c6da4ff7e5 100644
--- a/video/image_writer.c
+++ b/video/image_writer.c
@@ -289,6 +289,10 @@ int write_image(struct mp_image *image, const struct image_writer_opts *opts,
// it's unclear what colorspace/levels the target wants
if (image->imgfmt != destfmt || is_anamorphic) {
struct mp_image *dst = mp_image_alloc(destfmt, d_w, d_h);
+ if (!dst) {
+ mp_err(log, "Out of memory.\n");
+ return 0;
+ }
mp_image_copy_attributes(dst, image);
mp_image_swscale(dst, image, mp_sws_hq_flags);
diff --git a/video/mp_image.c b/video/mp_image.c
index 13b59b2c4e..dc123b7bf2 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -117,7 +117,7 @@ static bool m_refcount_is_unique(struct m_refcount *ref)
return true;
}
-static void mp_image_alloc_planes(struct mp_image *mpi)
+static bool mp_image_alloc_planes(struct mp_image *mpi)
{
assert(!mpi->planes[0]);
@@ -141,12 +141,13 @@ static void mp_image_alloc_planes(struct mp_image *mpi)
uint8_t *data = av_malloc(FFMAX(sum, 1));
if (!data)
- abort(); //out of memory
+ return false;
for (int n = 0; n < MP_MAX_PLANES; n++) {
mpi->planes[n] = plane_size[n] ? data : NULL;
data += plane_size[n];
}
+ return true;
}
void mp_image_setfmt(struct mp_image *mpi, int out_fmt)
@@ -203,11 +204,14 @@ struct mp_image *mp_image_alloc(int imgfmt, int w, int h)
{
struct mp_image *mpi = talloc_zero(NULL, struct mp_image);
talloc_set_destructor(mpi, mp_image_destructor);
+ mpi->refcount = m_refcount_new();
+
mp_image_set_size(mpi, w, h);
mp_image_setfmt(mpi, imgfmt);
- mp_image_alloc_planes(mpi);
-
- mpi->refcount = m_refcount_new();
+ if (!mp_image_alloc_planes(mpi)) {
+ talloc_free(mpi);
+ return NULL;
+ }
mpi->refcount->free = av_free;
mpi->refcount->arg = mpi->planes[0];
return mpi;
@@ -216,6 +220,8 @@ struct mp_image *mp_image_alloc(int imgfmt, int w, int h)
struct mp_image *mp_image_new_copy(struct mp_image *img)
{
struct mp_image *new = mp_image_alloc(img->imgfmt, img->w, img->h);
+ if (!new)
+ return NULL;
mp_image_copy(new, img);
mp_image_copy_attributes(new, img);
@@ -265,6 +271,7 @@ struct mp_image *mp_image_new_ref(struct mp_image *img)
// Return a reference counted reference to img. If the reference count reaches
// 0, call free(free_arg). The data passed by img must not be free'd before
// that. The new reference will be writeable.
+// On allocation failure, unref the frame and return NULL.
struct mp_image *mp_image_new_custom_ref(struct mp_image *img, void *free_arg,
void (*free)(void *arg))
{
@@ -275,6 +282,7 @@ struct mp_image *mp_image_new_custom_ref(struct mp_image *img, void *free_arg,
// connect to an external refcounting API. It is assumed that the new object
// has an initial reference to that external API. If free is given, that is
// called after the last unref. All function pointers are optional.
+// On allocation failure, unref the frame and return NULL.
struct mp_image *mp_image_new_external_ref(struct mp_image *img, void *arg,
void (*ref)(void *arg),
void (*unref)(void *arg),
@@ -304,15 +312,22 @@ bool mp_image_is_writeable(struct mp_image *img)
// Make the image data referenced by img writeable. This allocates new data
// if the data wasn't already writeable, and img->planes[] and img->stride[]
// will be set to the copy.
-void mp_image_make_writeable(struct mp_image *img)
+// Returns success; if false is returned, the image could not be made writeable.
+bool mp_image_make_writeable(struct mp_image *img)
{
if (mp_image_is_writeable(img))
- return;
+ return true;
- mp_image_steal_data(img, mp_image_new_copy(img));
+ struct mp_image *new = mp_image_new_copy(img);
+ if (!new)
+ return false;
+ mp_image_steal_data(img, new);
assert(mp_image_is_writeable(img));
+ return true;
}
+// Helper function: unrefs *p_img, and sets *p_img to a new ref of new_value.
+// Only unrefs *p_img and sets it to NULL if out of memory.
void mp_image_setrefp(struct mp_image **p_img, struct mp_image *new_value)
{
if (*p_img != new_value) {
@@ -586,7 +601,7 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *av_frame)
{
AVFrame *new_ref = av_frame_clone(av_frame);
if (!new_ref)
- abort(); // OOM
+ return NULL;
struct mp_image t = {0};
mp_image_copy_fields_from_av_frame(&t, new_ref);
return mp_image_new_external_ref(&t, new_ref, NULL, NULL, frame_is_unique,
@@ -604,10 +619,13 @@ static void free_img(void *opaque, uint8_t *data)
// mp_image_from_av_frame(). It's done this way to allow marking the
// resulting AVFrame as writeable if img is the only reference (in
// other words, it's an optimization).
+// On failure, img is only unreffed.
struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img)
{
struct mp_image *new_ref = mp_image_new_ref(img); // ensure it's refcounted
talloc_free(img);
+ if (!new_ref)
+ return NULL;
AVFrame *frame = av_frame_alloc();
mp_image_copy_fields_to_av_frame(frame, new_ref);
// Caveat: if img has shared references, and all other references disappear
@@ -619,6 +637,8 @@ struct AVFrame *mp_image_to_av_frame_and_unref(struct mp_image *img)
// Make it so that the actual image data is freed only if _all_ buffers
// are unreferenced.
struct mp_image *dummy_ref = mp_image_new_ref(new_ref);
+ if (!dummy_ref)
+ abort(); // out of memory (for the ref, not real image data)
void *ptr = new_ref->planes[n];
size_t size = new_ref->stride[n] * new_ref->h;
frame->buf[n] = av_buffer_create(ptr, size, free_img, dummy_ref, flags);
diff --git a/video/mp_image.h b/video/mp_image.h
index 9b2ef38c80..70e024bf7f 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -114,7 +114,7 @@ void mp_image_copy_attributes(struct mp_image *dmpi, struct mp_image *mpi);
struct mp_image *mp_image_new_copy(struct mp_image *img);
struct mp_image *mp_image_new_ref(struct mp_image *img);
bool mp_image_is_writeable(struct mp_image *img);
-void mp_image_make_writeable(struct mp_image *img);
+bool mp_image_make_writeable(struct mp_image *img);
void mp_image_setrefp(struct mp_image **p_img, struct mp_image *new_value);
void mp_image_unrefp(struct mp_image **p_img);
diff --git a/video/mp_image_pool.c b/video/mp_image_pool.c
index c2d1fca080..62d55cc372 100644
--- a/video/mp_image_pool.c
+++ b/video/mp_image_pool.c
@@ -147,6 +147,7 @@ struct mp_image *mp_image_pool_get_no_alloc(struct mp_image_pool *pool, int fmt,
// mp_image_alloc() is that there is a transparent mechanism to recycle image
// data allocations through this pool.
// The image can be free'd with talloc_free().
+// Returns NULL on OOM.
struct mp_image *mp_image_pool_get(struct mp_image_pool *pool, int fmt,
int w, int h)
{
@@ -171,24 +172,35 @@ struct mp_image *mp_image_pool_get(struct mp_image_pool *pool, int fmt,
}
// Like mp_image_new_copy(), but allocate the image out of the pool.
+// Returns NULL on OOM.
struct mp_image *mp_image_pool_new_copy(struct mp_image_pool *pool,
struct mp_image *img)
{
struct mp_image *new = mp_image_pool_get(pool, img->imgfmt, img->w, img->h);
- mp_image_copy(new, img);
- mp_image_copy_attributes(new, img);
+ if (new) {
+ mp_image_copy(new, img);
+ mp_image_copy_attributes(new, img);
+ }
return new;
}
// Like mp_image_make_writeable(), but if a copy has to be made, allocate it
// out of the pool.
-void mp_image_pool_make_writeable(struct mp_image_pool *pool,
+// If pool==NULL, mp_image_make_writeable() is called (for convenience).
+// Returns false on failure (see mp_image_make_writeable()).
+bool mp_image_pool_make_writeable(struct mp_image_pool *pool,
struct mp_image *img)
{
if (mp_image_is_writeable(img))
- return;
- mp_image_steal_data(img, mp_image_pool_new_copy(pool, img));
+ return true;
+ if (!pool)
+ return mp_image_make_writeable(img);
+ struct mp_image *new = mp_image_pool_new_copy(pool, img);
+ if (!new)
+ return false;
+ mp_image_steal_data(img, new);
assert(mp_image_is_writeable(img));
+ return true;
}
void mp_image_pool_set_allocator(struct mp_image_pool *pool,
diff --git a/video/mp_image_pool.h b/video/mp_image_pool.h
index d9ab2ee9e1..c2307da887 100644
--- a/video/mp_image_pool.h
+++ b/video/mp_image_pool.h
@@ -1,6 +1,8 @@
#ifndef MPV_MP_IMAGE_POOL_H
#define MPV_MP_IMAGE_POOL_H
+#include <stdbool.h>
+
struct mp_image_pool;