static void uninit(vf_instance_t *vf) { vf->priv=NULL; if(pause_mpi) { free_mp_image(pause_mpi); pause_mpi = NULL; } }
int write_image(struct mp_image *image, const struct image_writer_opts *opts, const char *filename) { struct mp_image *allocated_image = NULL; struct image_writer_opts defs = image_writer_opts_defaults; int d_w = image->display_w ? image->display_w : image->w; int d_h = image->display_h ? image->display_h : image->h; bool is_anamorphic = image->w != d_w || image->h != d_h; if (!opts) opts = &defs; const struct img_writer *writer = get_writer(opts); struct image_writer_ctx ctx = { opts, writer }; int destfmt = IMGFMT_RGB24; if (writer->pixfmts) { destfmt = writer->pixfmts[0]; // default to first pixel format for (int *fmt = writer->pixfmts; *fmt; fmt++) { if (*fmt == image->imgfmt) { destfmt = *fmt; break; } } } // Caveat: - no colorspace/levels conversion done if pixel formats equal // - RGB->YUV assumes BT.601 // - color levels broken in various ways thanks to libswscale if (image->imgfmt != destfmt || is_anamorphic) { struct mp_image *dst = alloc_mpi(d_w, d_h, destfmt); vf_clone_mpi_attributes(dst, image); int flags = SWS_LANCZOS | SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP | SWS_ACCURATE_RND | SWS_BITEXACT; mp_image_swscale(dst, image, flags); allocated_image = dst; image = dst; } FILE *fp = fopen(filename, "wb"); int success = 0; if (fp == NULL) { mp_msg(MSGT_CPLAYER, MSGL_ERR, "Error opening '%s' for writing!\n", filename); } else { success = writer->write(&ctx, image, fp); success = !fclose(fp) && success; if (!success) mp_msg(MSGT_CPLAYER, MSGL_ERR, "Error writing file '%s'!\n", filename); } free_mp_image(allocated_image); return success; }
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){ mp_image_t *dmpi = NULL; if (vf->priv->passthrough) { dmpi=vf_get_image(vf->next, IMGFMT_MPEGPES, MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h); dmpi->planes[0]=mpi->planes[0]; return vf_next_put_image(vf,dmpi, pts); } if(vf->priv->current->show || (vf->priv->current->parent && vf->priv->current->parent->show)) { // Close all menu who requested it while(vf->priv->current->cl && vf->priv->current != vf->priv->root) { menu_t* m = vf->priv->current; vf->priv->current = m->parent ? m->parent : vf->priv->root; menu_close(m); } // Step 1 : save the picture while(go2pause == 1) { static char delay = 0; // Hack : wait the 2 frame to be sure to show the right picture delay ^= 1; // after a seek if(!delay) break; if(pause_mpi && (mpi->w != pause_mpi->w || mpi->h != pause_mpi->h || mpi->imgfmt != pause_mpi->imgfmt)) { free_mp_image(pause_mpi); pause_mpi = NULL; } if(!pause_mpi) pause_mpi = alloc_mpi(mpi->w,mpi->h,mpi->imgfmt); copy_mpi(pause_mpi,mpi); mp_input_queue_cmd(mp_input_parse_cmd("pause")); go2pause = 2; break; } // Grab // Ungrab the keys if(!mp_input_key_cb && vf->priv->current->show) mp_input_key_cb = key_cb; if(mp_input_key_cb && !vf->priv->current->show) mp_input_key_cb = NULL; if(mpi->flags&MP_IMGFLAG_DIRECT) dmpi = mpi->priv; else { dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w,mpi->h); copy_mpi(dmpi,mpi); } menu_draw(vf->priv->current,dmpi); } else { if(mp_input_key_cb) mp_input_key_cb = NULL; if(mpi->flags&MP_IMGFLAG_DIRECT) dmpi = mpi->priv; else { dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w,mpi->h); dmpi->stride[0] = mpi->stride[0]; dmpi->stride[1] = mpi->stride[1]; dmpi->stride[2] = mpi->stride[2]; dmpi->planes[0] = mpi->planes[0]; dmpi->planes[1] = mpi->planes[1]; dmpi->planes[2] = mpi->planes[2]; dmpi->priv = mpi->priv; } } return vf_next_put_image(vf,dmpi, pts); }
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ mp_image_t *dmpi = NULL; if (vf->priv->passthrough) { dmpi=vf_get_image(vf->next, IMGFMT_MPEGPES, MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h); dmpi->planes[0]=mpi->planes[0]; return vf_next_put_image(vf,dmpi, pts); } // Close all menu who requested it while(vf->priv->current->cl && vf->priv->current != vf->priv->root) { menu_t* m = vf->priv->current; vf->priv->current = m->parent ? m->parent : vf->priv->root; menu_close(m); } // Try to capture the last frame before pause, or fallback to use // last captured frame. if(pause_mpi && (mpi->w != pause_mpi->w || mpi->h != pause_mpi->h || mpi->imgfmt != pause_mpi->imgfmt)) { free_mp_image(pause_mpi); pause_mpi = NULL; } if (!pause_mpi) { pause_mpi = alloc_mpi(mpi->w,mpi->h,mpi->imgfmt); copy_mpi(pause_mpi,mpi); } else if (mpctx_get_osd_function(vf->priv->root->ctx) == OSD_PAUSE) copy_mpi(pause_mpi,mpi); if (vf->priv->current->show) { if (!mp_input_key_cb) mp_input_key_cb = key_cb; if(mpi->flags&MP_IMGFLAG_DIRECT) dmpi = mpi->priv; else { dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w,mpi->h); copy_mpi(dmpi,mpi); } menu_draw(vf->priv->current,dmpi); } else { if(mp_input_key_cb) mp_input_key_cb = NULL; if(mpi->flags&MP_IMGFLAG_DIRECT) dmpi = mpi->priv; else { dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w,mpi->h); dmpi->stride[0] = mpi->stride[0]; dmpi->stride[1] = mpi->stride[1]; dmpi->stride[2] = mpi->stride[2]; dmpi->planes[0] = mpi->planes[0]; dmpi->planes[1] = mpi->planes[1]; dmpi->planes[2] = mpi->planes[2]; dmpi->priv = mpi->priv; } } return vf_next_put_image(vf,dmpi, pts); }
int write_image(struct mp_image *image, const struct mp_csp_details *csp, const struct image_writer_opts *opts, const char *filename) { struct mp_image *allocated_image = NULL; struct image_writer_opts defs = image_writer_opts_defaults; bool is_anamorphic = image->w != image->width || image->h != image->height; if (!opts) opts = &defs; const struct img_writer *writer = get_writer(opts); struct image_writer_ctx ctx = { opts, writer }; int destfmt = IMGFMT_RGB24; if (writer->pixfmts) { destfmt = writer->pixfmts[0]; // default to first pixel format for (int *fmt = writer->pixfmts; *fmt; fmt++) { if (*fmt == image->imgfmt) { destfmt = *fmt; break; } } } if (image->imgfmt != destfmt || is_anamorphic) { struct mp_image *dst = alloc_mpi(image->w, image->h, destfmt); struct SwsContext *sws = sws_getContextFromCmdLine_hq(image->width, image->height, image->imgfmt, dst->width, dst->height, dst->imgfmt); struct mp_csp_details colorspace = MP_CSP_DETAILS_DEFAULTS; if (csp) colorspace = *csp; // This is a property of the output device; images always use // full-range RGB. colorspace.levels_out = MP_CSP_LEVELS_PC; mp_sws_set_colorspace(sws, &colorspace); sws_scale(sws, (const uint8_t **)image->planes, image->stride, 0, image->height, dst->planes, dst->stride); sws_freeContext(sws); allocated_image = dst; image = dst; } FILE *fp = fopen(filename, "wb"); int success = 0; if (fp == NULL) { mp_msg(MSGT_CPLAYER, MSGL_ERR, "Error opening '%s' for writing!\n", filename); } else { success = writer->write(&ctx, image, fp); success = !fclose(fp) && success; if (!success) mp_msg(MSGT_CPLAYER, MSGL_ERR, "Error writing file '%s'!\n", filename); } free_mp_image(allocated_image); return success; }