summaryrefslogtreecommitdiffstats
path: root/mpvcore/player/screenshot.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-17 00:53:22 +0100
committerwm4 <wm4@nowhere>2013-12-17 00:53:22 +0100
commite44911142914783c9ec717f329bd9b6a8bb9b70e (patch)
tree92bb653f7d56553ffd3bb6e5a22ffc0db91142e8 /mpvcore/player/screenshot.c
parent7dc7b900c622235d595337c988a0c75280084b7c (diff)
downloadmpv-e44911142914783c9ec717f329bd9b6a8bb9b70e.tar.bz2
mpv-e44911142914783c9ec717f329bd9b6a8bb9b70e.tar.xz
Move mpvcore/player/ to player/
Diffstat (limited to 'mpvcore/player/screenshot.c')
-rw-r--r--mpvcore/player/screenshot.c404
1 files changed, 0 insertions, 404 deletions
diff --git a/mpvcore/player/screenshot.c b/mpvcore/player/screenshot.c
deleted file mode 100644
index 7aaba5f05a..0000000000
--- a/mpvcore/player/screenshot.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * This file is part of mplayer2.
- *
- * mplayer2 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * mplayer2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with mplayer2; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "config.h"
-
-#include "osdep/io.h"
-
-#include "talloc.h"
-#include "screenshot.h"
-#include "mp_core.h"
-#include "command.h"
-#include "mpvcore/bstr.h"
-#include "mpvcore/mp_msg.h"
-#include "mpvcore/path.h"
-#include "video/mp_image.h"
-#include "video/decode/dec_video.h"
-#include "video/filter/vf.h"
-#include "video/out/vo.h"
-#include "video/image_writer.h"
-#include "sub/osd.h"
-
-#include "video/csputils.h"
-
-#define MODE_FULL_WINDOW 1
-#define MODE_SUBTITLES 2
-
-typedef struct screenshot_ctx {
- struct MPContext *mpctx;
-
- int mode;
- bool each_frame;
- bool osd;
-
- int frameno;
-} screenshot_ctx;
-
-void screenshot_init(struct MPContext *mpctx)
-{
- mpctx->screenshot_ctx = talloc(mpctx, screenshot_ctx);
- *mpctx->screenshot_ctx = (screenshot_ctx) {
- .mpctx = mpctx,
- .frameno = 1,
- };
-}
-
-#define SMSG_OK 0
-#define SMSG_ERR 1
-
-static void screenshot_msg(screenshot_ctx *ctx, int status, const char *msg,
- ...) PRINTF_ATTRIBUTE(3,4);
-
-static void screenshot_msg(screenshot_ctx *ctx, int status, const char *msg,
- ...)
-{
- va_list ap;
- char *s;
-
- va_start(ap, msg);
- s = talloc_vasprintf(NULL, msg, ap);
- va_end(ap);
-
- mp_msg(MSGT_CPLAYER, status == SMSG_ERR ? MSGL_ERR : MSGL_INFO, "%s\n", s);
- if (ctx->osd) {
- set_osd_msg(ctx->mpctx, OSD_MSG_TEXT, 1, ctx->mpctx->opts->osd_duration,
- "%s", s);
- }
-
- talloc_free(s);
-}
-
-static char *stripext(void *talloc_ctx, const char *s)
-{
- const char *end = strrchr(s, '.');
- if (!end)
- end = s + strlen(s);
- return talloc_asprintf(talloc_ctx, "%.*s", (int)(end - s), s);
-}
-
-#ifdef _WIN32
-#define ILLEGAL_FILENAME_CHARS "?\"/\\<>*|:"
-#else
-#define ILLEGAL_FILENAME_CHARS "/"
-#endif
-
-// Replace all characters disallowed in filenames with '_' and return the newly
-// allocated result string.
-static char *sanitize_filename(void *talloc_ctx, const char *s)
-{
- char *res = talloc_strdup(talloc_ctx, s);
- char *cur = res;
- while (*cur) {
- if (strchr(ILLEGAL_FILENAME_CHARS, *cur) || ((unsigned char)*cur) < 32)
- *cur = '_';
- cur++;
- }
- return res;
-}
-
-static void append_filename(char **s, const char *f)
-{
- char *append = sanitize_filename(NULL, f);
- *s = talloc_strdup_append(*s, append);
- talloc_free(append);
-}
-
-static char *create_fname(struct MPContext *mpctx, char *template,
- const char *file_ext, int *sequence, int *frameno)
-{
- char *res = talloc_strdup(NULL, ""); //empty string, non-NULL context
-
- time_t raw_time = time(NULL);
- struct tm *local_time = localtime(&raw_time);
-
- if (!template || *template == '\0')
- template = "shot%n";
-
- for (;;) {
- char *next = strchr(template, '%');
- if (!next)
- break;
- res = talloc_strndup_append(res, template, next - template);
- template = next + 1;
- char fmt = *template++;
- switch (fmt) {
- case '#':
- case '0':
- case 'n': {
- int digits = '4';
- if (fmt == '#') {
- if (!*sequence) {
- *frameno = 1;
- }
- fmt = *template++;
- }
- if (fmt == '0') {
- digits = *template++;
- if (digits < '0' || digits > '9')
- goto error_exit;
- fmt = *template++;
- }
- if (fmt != 'n')
- goto error_exit;
- char fmtstr[] = {'%', '0', digits, 'd', '\0'};
- res = talloc_asprintf_append(res, fmtstr, *frameno);
- if (*frameno < 100000 - 1) {
- (*frameno) += 1;
- (*sequence) += 1;
- }
- break;
- }
- case 'f':
- case 'F': {
- char *video_file = mp_basename(mpctx->filename);
- if (video_file) {
- char *name = video_file;
- if (fmt == 'F')
- name = stripext(res, video_file);
- append_filename(&res, name);
- }
- break;
- }
- case 'p':
- case 'P': {
- char *t = mp_format_time(get_current_time(mpctx), fmt == 'P');
- append_filename(&res, t);
- talloc_free(t);
- break;
- }
- case 'w': {
- char tfmt = *template;
- if (!tfmt)
- goto error_exit;
- template++;
- char fmtstr[] = {'%', tfmt, '\0'};
- char *s = mp_format_time_fmt(fmtstr, get_current_time(mpctx));
- if (!s)
- goto error_exit;
- append_filename(&res, s);
- talloc_free(s);
- break;
- }
- case 't': {
- char tfmt = *template;
- if (!tfmt)
- goto error_exit;
- template++;
- char fmtstr[] = {'%', tfmt, '\0'};
- char buffer[80];
- if (strftime(buffer, sizeof(buffer), fmtstr, local_time) == 0)
- buffer[0] = '\0';
- append_filename(&res, buffer);
- break;
- }
- case '{': {
- char *end = strchr(template, '}');
- if (!end)
- goto error_exit;
- struct bstr prop = bstr_splice(bstr0(template), 0, end - template);
- char *tmp = talloc_asprintf(NULL, "${%.*s}", BSTR_P(prop));
- char *s = mp_property_expand_string(mpctx, tmp);
- talloc_free(tmp);
- if (s)
- append_filename(&res, s);
- talloc_free(s);
- template = end + 1;
- break;
- }
- case '%':
- res = talloc_strdup_append(res, "%");
- break;
- default:
- goto error_exit;
- }
- }
-
- res = talloc_strdup_append(res, template);
- res = talloc_asprintf_append(res, ".%s", file_ext);
- char *fname = mp_get_user_path(NULL, res);
- talloc_free(res);
- return fname;
-
-error_exit:
- talloc_free(res);
- return NULL;
-}
-
-static char *gen_fname(screenshot_ctx *ctx, const char *file_ext)
-{
- int sequence = 0;
- for (;;) {
- int prev_sequence = sequence;
- char *fname = create_fname(ctx->mpctx,
- ctx->mpctx->opts->screenshot_template,
- file_ext,
- &sequence,
- &ctx->frameno);
-
- if (!fname) {
- screenshot_msg(ctx, SMSG_ERR, "Invalid screenshot filename "
- "template! Fix or remove the --screenshot-template "
- "option.");
- return NULL;
- }
-
- if (!mp_path_exists(fname))
- return fname;
-
- if (sequence == prev_sequence) {
- screenshot_msg(ctx, SMSG_ERR, "Can't save screenshot, file '%s' "
- "already exists!", fname);
- talloc_free(fname);
- return NULL;
- }
-
- talloc_free(fname);
- }
-}
-
-static void add_subs(struct MPContext *mpctx, struct mp_image *image)
-{
- int d_w = image->display_w ? image->display_w : image->w;
- int d_h = image->display_h ? image->display_h : image->h;
-
- double sar = (double)image->w / image->h;
- double dar = (double)d_w / d_h;
- struct mp_osd_res res = {
- .w = image->w,
- .h = image->h,
- .display_par = sar / dar,
- };
-
- osd_draw_on_image(mpctx->osd, res, mpctx->osd->vo_pts,
- OSD_DRAW_SUB_ONLY, image);
-}
-
-static void screenshot_save(struct MPContext *mpctx, struct mp_image *image)
-{
- screenshot_ctx *ctx = mpctx->screenshot_ctx;
-
- struct image_writer_opts *opts = mpctx->opts->screenshot_image_opts;
-
- char *filename = gen_fname(ctx, image_writer_file_ext(opts));
- if (filename) {
- screenshot_msg(ctx, SMSG_OK, "Screenshot: '%s'", filename);
- if (!write_image(image, opts, filename))
- screenshot_msg(ctx, SMSG_ERR, "Error writing screenshot!");
- talloc_free(filename);
- }
-}
-
-static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode)
-{
- struct mp_image *image = NULL;
- if (mpctx->video_out && mpctx->video_out->config_ok) {
- if (mode == MODE_SUBTITLES && mpctx->osd->render_subs_in_filter)
- mode = 0;
-
- struct voctrl_screenshot_args args =
- { .full_window = (mode == MODE_FULL_WINDOW) };
-
- if (mpctx->d_video && mpctx->d_video->vfilter)
- vf_control_any(mpctx->d_video->vfilter, VFCTRL_SCREENSHOT, &args);
-
- if (!args.out_image)
- vo_control(mpctx->video_out, VOCTRL_SCREENSHOT, &args);
-
- image = args.out_image;
- if (image) {
- if (mode == MODE_SUBTITLES && !args.has_osd)
- add_subs(mpctx, image);
- }
- }
- return image;
-}
-
-void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode,
- bool osd)
-{
- screenshot_ctx *ctx = mpctx->screenshot_ctx;
- struct image_writer_opts opts = *mpctx->opts->screenshot_image_opts;
- bool old_osd = ctx->osd;
- ctx->osd = osd;
-
- if (mp_path_exists(filename)) {
- screenshot_msg(ctx, SMSG_ERR, "Screenshot: file '%s' already exists.",
- filename);
- goto end;
- }
- char *ext = mp_splitext(filename, NULL);
- if (ext)
- opts.format = ext + 1; // omit '.'
- struct mp_image *image = screenshot_get(mpctx, mode);
- if (!image) {
- screenshot_msg(ctx, SMSG_ERR, "Taking screenshot failed.");
- goto end;
- }
- screenshot_msg(ctx, SMSG_OK, "Screenshot: '%s'", filename);
- if (!write_image(image, &opts, filename))
- screenshot_msg(ctx, SMSG_ERR, "Error writing screenshot!");
- talloc_free(image);
-
-end:
- ctx->osd = old_osd;
-}
-
-void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame,
- bool osd)
-{
- screenshot_ctx *ctx = mpctx->screenshot_ctx;
-
- if (mode == MODE_SUBTITLES && mpctx->osd->render_subs_in_filter)
- mode = 0;
-
- if (each_frame) {
- ctx->each_frame = !ctx->each_frame;
- if (!ctx->each_frame)
- return;
- } else {
- ctx->each_frame = false;
- }
-
- ctx->mode = mode;
- ctx->osd = osd;
-
- struct mp_image *image = screenshot_get(mpctx, mode);
-
- if (image) {
- screenshot_save(mpctx, image);
- } else {
- screenshot_msg(ctx, SMSG_ERR, "Taking screenshot failed.");
- }
-
- talloc_free(image);
-}
-
-void screenshot_flip(struct MPContext *mpctx)
-{
- screenshot_ctx *ctx = mpctx->screenshot_ctx;
-
- if (!ctx->each_frame)
- return;
-
- ctx->each_frame = false;
- screenshot_request(mpctx, ctx->mode, true, ctx->osd);
-}