diff options
45 files changed, 219 insertions, 67 deletions
diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 0b24689313..02b7f9ec20 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -223,12 +223,18 @@ static void scale_sb_rgba(struct sub_bitmap *sb, struct mp_image *dst_format, sbisrc.planes[0] = sb->bitmap; sbisrc.stride[0] = sb->stride; struct mp_image *sbisrc2 = mp_image_alloc(IMGFMT_BGR32, sb->dw, sb->dh); - mp_image_swscale(sbisrc2, &sbisrc, SWS_BILINEAR); - struct mp_image *sba = mp_image_alloc(IMGFMT_Y8, sb->dw, sb->dh); + struct mp_image *sbi = mp_image_alloc(dst_format->imgfmt, sb->dw, sb->dh); + if (!sbisrc2 || !sba || !sbi) { + talloc_free(sbisrc2); + talloc_free(sba); + talloc_free(sbi); + return; + } + + mp_image_swscale(sbisrc2, &sbisrc, SWS_BILINEAR); unpremultiply_and_split_BGR32(sbisrc2, sba); - struct mp_image *sbi = mp_image_alloc(dst_format->imgfmt, sb->dw, sb->dh); sbi->params.colorspace = dst_format->params.colorspace; sbi->params.colorlevels = dst_format->params.colorlevels; mp_image_swscale(sbi, sbisrc2, SWS_BILINEAR); @@ -262,6 +268,9 @@ static void draw_rgba(struct mp_draw_sub_cache *cache, struct mp_rect bb, if (!(sbi && sba)) scale_sb_rgba(sb, temp, &sbi, &sba); + // on OOM, skip drawing + if (!(sbi && sba)) + continue; int bytes = (bits + 7) / 8; uint8_t *alpha_p = sba->planes[0] + src_y * sba->stride[0] + src_x; @@ -452,6 +461,8 @@ static struct mp_image *chroma_up(struct mp_draw_sub_cache *cache, int imgfmt, talloc_free(cache->upsample_img); cache->upsample_img = mp_image_alloc(imgfmt, src->w, src->h); talloc_steal(cache, cache->upsample_img); + if (!cache->upsample_img) + return NULL; } cache->upsample_temp = *cache->upsample_img; @@ -547,6 +558,8 @@ void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst, struct mp_image dst_region = *dst; mp_image_crop_rc(&dst_region, bb); struct mp_image *temp = chroma_up(cache_, format, &dst_region); + if (!temp) + continue; // on OOM, skip region if (sbs->format == SUBBITMAP_RGBA) { draw_rgba(cache_, bb, temp, bits, sbs); diff --git a/sub/img_convert.c b/sub/img_convert.c index 8c42c5ed4b..a29db4a6f2 100644 --- a/sub/img_convert.c +++ b/sub/img_convert.c @@ -77,6 +77,12 @@ bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs) *d = *s; struct mp_image *image = mp_image_alloc(IMGFMT_BGRA, s->w, s->h); talloc_steal(c->parts, image); + if (!image) { + // on OOM, skip the region by making it 0 sized + d->w = d->h = d->dw = d->dh = 0; + continue; + } + d->stride = image->stride[0]; d->bitmap = image->planes[0]; @@ -108,6 +114,8 @@ bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs, int pad = 5; struct mp_image *temp = mp_image_alloc(IMGFMT_BGRA, s->w + pad * 2, s->h + pad * 2); + if (!temp) + continue; // on OOM, skip region memset_pic(temp->planes[0], 0, temp->w * 4, temp->h, temp->stride[0]); uint8_t *p0 = temp->planes[0] + pad * 4 + pad * temp->stride[0]; memcpy_pic(p0, s->bitmap, s->w * 4, s->h, temp->stride[0], s->stride); @@ -121,10 +129,15 @@ bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs, d->h = d->dh = s->dh + pad * 2 * sy; struct mp_image *image = mp_image_alloc(IMGFMT_BGRA, d->w, d->h); talloc_steal(c->parts, image); - d->stride = image->stride[0]; - d->bitmap = image->planes[0]; - - mp_image_sw_blur_scale(image, temp, gblur); + if (image) { + d->stride = image->stride[0]; + d->bitmap = image->planes[0]; + + mp_image_sw_blur_scale(image, temp, gblur); + } else { + // on OOM, skip region + *d = *s; + } talloc_free(temp); } @@ -168,10 +181,15 @@ bool osd_scale_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs) d->h = d->dh = s->dh; struct mp_image *image = mp_image_alloc(IMGFMT_BGRA, d->w, d->h); talloc_steal(c->parts, image); - d->stride = image->stride[0]; - d->bitmap = image->planes[0]; - - mp_image_swscale(image, &src_image, mp_sws_fast_flags); + if (image) { + d->stride = image->stride[0]; + d->bitmap = image->planes[0]; + + mp_image_swscale(image, &src_image, mp_sws_fast_flags); + } else { + // on OOM, skip the region; just don't scale it + *d = *s; + } } return true; } @@ -353,11 +353,8 @@ static void draw_on_image(void *ctx, struct sub_bitmaps *imgs) { struct draw_on_image_closure *closure = ctx; struct osd_state *osd = closure->osd; - if (closure->pool) { - mp_image_pool_make_writeable(closure->pool, closure->dest); - } else { - mp_image_make_writeable(closure->dest); - } + if (!mp_image_pool_make_writeable(closure->pool, closure->dest)) + return; // on OOM, skip mp_draw_sub_bitmaps(&osd->draw_cache, closure->dest, imgs); talloc_steal(osd, osd->draw_cache); closure->changed = true; 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, ¶ms); 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_se |