diff --git a/core/screenshot.c b/core/screenshot.c index 8e16771289..0f397f2dd7 100644 --- a/core/screenshot.c +++ b/core/screenshot.c @@ -48,7 +48,6 @@ typedef struct screenshot_ctx { int mode; int each_frame; - int using_vf_screenshot; int frameno; } screenshot_ctx; @@ -234,16 +233,9 @@ static char *gen_fname(screenshot_ctx *ctx, const char *file_ext) } } -static struct mp_image *add_subs(struct MPContext *mpctx, - struct mp_image *image) +static void add_subs(struct MPContext *mpctx, struct mp_image *image) { - if (!(image->flags & MP_IMGFLAG_ALLOCATED)) { - struct mp_image *new_image = alloc_mpi(image->w, image->h, - image->imgfmt); - copy_mpi(new_image, image); - vf_clone_mpi_attributes(new_image, image); - image = new_image; - } + mp_image_make_writeable(image); int d_w = image->display_w ? image->display_w : image->w; int d_h = image->display_h ? image->display_h : image->h; @@ -259,8 +251,6 @@ static struct mp_image *add_subs(struct MPContext *mpctx, osd_draw_on_image(mpctx->osd, res, mpctx->osd->vo_pts, OSD_DRAW_SUB_ONLY, image); - - return image; } static void screenshot_save(struct MPContext *mpctx, struct mp_image *image, @@ -270,31 +260,18 @@ static void screenshot_save(struct MPContext *mpctx, struct mp_image *image, struct image_writer_opts *opts = mpctx->opts.screenshot_image_opts; - struct mp_image *new_image = image; if (with_subs) - new_image = add_subs(mpctx, new_image); + add_subs(mpctx, image); char *filename = gen_fname(ctx, image_writer_file_ext(opts)); if (filename) { mp_msg(MSGT_CPLAYER, MSGL_INFO, "*** screenshot '%s' ***\n", filename); - if (!write_image(new_image, opts, filename)) + if (!write_image(image, opts, filename)) mp_msg(MSGT_CPLAYER, MSGL_ERR, "\nError writing screenshot!\n"); talloc_free(filename); } - if (new_image != image) - free_mp_image(new_image); -} - -static void vf_screenshot_callback(void *pctx, struct mp_image *image) -{ - struct MPContext *mpctx = (struct MPContext *)pctx; - screenshot_ctx *ctx = mpctx->screenshot_ctx; - screenshot_save(mpctx, image, ctx->mode == MODE_SUBTITLES); - if (ctx->each_frame) { - ctx->each_frame = false; - screenshot_request(mpctx, ctx->mode, true); - } + talloc_free(image); } static bool force_vf(struct MPContext *mpctx) @@ -315,7 +292,6 @@ void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame) if (mpctx->video_out && mpctx->video_out->config_ok) { screenshot_ctx *ctx = mpctx->screenshot_ctx; - ctx->using_vf_screenshot = 0; if (mode == MODE_SUBTITLES && mpctx->osd->render_subs_in_filter) mode = 0; @@ -332,26 +308,24 @@ void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame) struct voctrl_screenshot_args args = { .full_window = (mode == MODE_FULL_WINDOW) }; - if (!force_vf(mpctx) - && vo_control(mpctx->video_out, VOCTRL_SCREENSHOT, &args) == true) - { + + if (!force_vf(mpctx)) + vo_control(mpctx->video_out, VOCTRL_SCREENSHOT, &args); + + if (!args.out_image) { + mp_msg(MSGT_CPLAYER, MSGL_INFO, "No VO support for taking" + " screenshots, trying VFCTRL_SCREENSHOT!\n"); + struct vf_instance *vfilter = mpctx->sh_video->vfilter; + vfilter->control(vfilter, VFCTRL_SCREENSHOT, &args); + } + + if (args.out_image) { if (args.has_osd) mode = 0; screenshot_save(mpctx, args.out_image, mode == MODE_SUBTITLES); - free_mp_image(args.out_image); } else { - mp_msg(MSGT_CPLAYER, MSGL_INFO, "No VO support for taking" - " screenshots, trying VFCTRL_SCREENSHOT!\n"); - ctx->using_vf_screenshot = 1; - struct vf_ctrl_screenshot cmd = { - .image_callback = vf_screenshot_callback, - .image_callback_ctx = mpctx, - }; - struct vf_instance *vfilter = mpctx->sh_video->vfilter; - if (vfilter->control(vfilter, VFCTRL_SCREENSHOT, &cmd) != - CONTROL_OK) - mp_msg(MSGT_CPLAYER, MSGL_INFO, - "...failed (need --vf=screenshot?)\n"); + mp_msg(MSGT_CPLAYER, MSGL_INFO, + "...failed (need --vf=screenshot?)\n"); } } } @@ -363,13 +337,6 @@ void screenshot_flip(struct MPContext *mpctx) if (!ctx->each_frame) return; - // screenshot_flip is called when the VO presents a new frame. vf_screenshot - // can behave completely different (consider filters inserted between - // vf_screenshot and vf_vo, that add or remove frames), so handle this case - // somewhere else. - if (ctx->using_vf_screenshot) - return; - ctx->each_frame = false; screenshot_request(mpctx, ctx->mode, true); } diff --git a/video/filter/vf.h b/video/filter/vf.h index ac9394024f..187af302ad 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -86,19 +86,13 @@ typedef struct vf_seteq { int value; } vf_equalizer_t; -struct vf_ctrl_screenshot { - // When the screenshot is complete, pass it to this callback. - void (*image_callback)(void *, mp_image_t *); - void *image_callback_ctx; -}; - #define VFCTRL_QUERY_MAX_PP_LEVEL 4 // query max postprocessing level (if any) #define VFCTRL_SET_PP_LEVEL 5 // set postprocessing level #define VFCTRL_SET_EQUALIZER 6 // set color options (brightness,contrast etc) #define VFCTRL_GET_EQUALIZER 8 // get color options (brightness,contrast etc) #define VFCTRL_HWDEC_DECODER_RENDER 9 // vdpau hw decoding #define VFCTRL_HWDEC_ALLOC_SURFACE 10 // vdpau hw decoding -#define VFCTRL_SCREENSHOT 14 // Take screenshot, arg is vf_ctrl_screenshot +#define VFCTRL_SCREENSHOT 14 // Take screenshot, arg is voctrl_screenshot_args #define VFCTRL_INIT_OSD 15 // Filter OSD renderer present? #define VFCTRL_SET_DEINTERLACE 18 // Set deinterlacing status #define VFCTRL_GET_DEINTERLACE 19 // Get deinterlacing status diff --git a/video/filter/vf_screenshot.c b/video/filter/vf_screenshot.c index d02581a461..8deb48924a 100644 --- a/video/filter/vf_screenshot.c +++ b/video/filter/vf_screenshot.c @@ -23,29 +23,25 @@ #include #include -#include "core/mp_msg.h" +#include "talloc.h" + #include "video/img_format.h" #include "video/mp_image.h" -#include "vf.h" #include "video/sws_utils.h" -#include "video/fmt-conversion.h" -#include "video/memcpy_pic.h" +#include "video/out/vo.h" -#include +#include "vf.h" struct vf_priv_s { int display_w, display_h; - void (*image_callback)(void *, mp_image_t *); - void *image_callback_ctx; - int shot; + struct mp_image *current; }; -//===========================================================================// - static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt) { + mp_image_unrefp(&vf->priv->current); vf->priv->display_w = d_width; vf->priv->display_h = d_height; return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); @@ -53,57 +49,37 @@ static int config(struct vf_instance *vf, static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { - if(vf->priv->shot) { - vf->priv->shot=0; - mp_image_t image = *mpi; - image.flags &= ~MP_IMGFLAG_ALLOCATED; - mp_image_copy_attributes(&image, mpi); - mp_image_set_display_size(&image, vf->priv->display_w, - vf->priv->display_h); - vf->priv->image_callback(vf->priv->image_callback_ctx, &image); - } - + mp_image_unrefp(&vf->priv->current); + vf->priv->current = talloc_steal(vf, mp_image_new_ref(mpi)); + mp_image_set_display_size(vf->priv->current, vf->priv->display_w, + vf->priv->display_h); return mpi; } static int control (vf_instance_t *vf, int request, void *data) { - if(request==VFCTRL_SCREENSHOT) { - struct vf_ctrl_screenshot *cmd = (struct vf_ctrl_screenshot *)data; - vf->priv->image_callback = cmd->image_callback; - vf->priv->image_callback_ctx = cmd->image_callback_ctx; - vf->priv->shot=1; + if (request == VFCTRL_SCREENSHOT && vf->priv->current) { + struct voctrl_screenshot_args *args = data; + args->out_image = mp_image_new_ref(vf->priv->current); return CONTROL_TRUE; } return vf_next_control (vf, request, data); } - -//===========================================================================// - static int query_format(struct vf_instance *vf, unsigned int fmt) { - enum PixelFormat av_format = imgfmt2pixfmt(fmt); - - if (av_format != PIX_FMT_NONE && sws_isSupportedInput(av_format)) + if (mp_sws_supported_format(fmt)) return vf_next_query_format(vf, fmt); return 0; } -static void uninit(vf_instance_t *vf) -{ - free(vf->priv); -} - static int vf_open(vf_instance_t *vf, char *args) { - vf->config=config; - vf->control=control; - vf->filter=filter; - vf->query_format=query_format; - vf->uninit=uninit; - vf->priv=malloc(sizeof(struct vf_priv_s)); - vf->priv->shot=0; + vf->config = config; + vf->control = control; + vf->filter = filter; + vf->query_format = query_format; + vf->priv = talloc_zero(vf, struct vf_priv_s); return 1; } @@ -126,5 +102,3 @@ const vf_info_t vf_info_screenshot_force = { vf_open, NULL }; - -//===========================================================================//