summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authornanahi <130121847+na-na-hi@users.noreply.github.com>2024-03-19 05:06:44 -0400
committerKacper Michajłow <kasper93@gmail.com>2024-03-19 19:30:27 +0100
commitdf01ebaafcd93fdc7d48e4e8292daf5f1e932f16 (patch)
treebcbe5086e07bb97cabd7d0bf30d62e1d3f13c697 /video
parent9a861c930bac32ee3febedc0b0653be4f6f66fef (diff)
downloadmpv-df01ebaafcd93fdc7d48e4e8292daf5f1e932f16.tar.bz2
mpv-df01ebaafcd93fdc7d48e4e8292daf5f1e932f16.tar.xz
image_writer: refactor screenshot write functions
When 3cb9119984b88b31a5b958b1b83efe8d1cf0b818 introduced AVIF screenshot support, FILE * in write functions were replaced by filenames. This resulted in unnecessary duplication of FILE * handling code and the usage of avio_open API made it hard to use exclusive open with it. To unify file handling, use avio_open_dyn_buf instead which writes to memory instead. This way FILE * can be used for the write functions and file handling code can be deduplicated. Since we now control the file opening, exclusive open can now be used for AVIF screenshots.
Diffstat (limited to 'video')
-rw-r--r--video/image_writer.c74
1 files changed, 24 insertions, 50 deletions
diff --git a/video/image_writer.c b/video/image_writer.c
index c3cf930401..cc795735ef 100644
--- a/video/image_writer.c
+++ b/video/image_writer.c
@@ -163,19 +163,8 @@ static void prepare_avframe(AVFrame *pic, AVCodecContext *avctx,
);
}
-static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image,
- const char *filename, bool overwrite)
+static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
{
- FILE *fp = fopen(filename, overwrite ? "wb" : "wbx");
- if (!fp && errno == EEXIST) {
- MP_ERR(ctx, "File '%s' already exists!\n", filename);
- return false;
- }
- if (!fp) {
- MP_ERR(ctx, "Error opening '%s' for writing!\n", filename);
- return false;
- }
-
bool success = false;
AVFrame *pic = NULL;
AVPacket *pkt = NULL;
@@ -265,9 +254,6 @@ error_exit:
avcodec_free_context(&avctx);
av_frame_free(&pic);
av_packet_free(&pkt);
- success = success && !fclose(fp);
- if (!success)
- unlink(filename);
return success;
}
@@ -282,19 +268,8 @@ static void write_jpeg_error_exit(j_common_ptr cinfo)
longjmp(*(jmp_buf*)cinfo->client_data, 1);
}
-static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image,
- const char *filename, bool overwrite)
+static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
{
- FILE *fp = fopen(filename, overwrite ? "wb" : "wbx");
- if (!fp && errno == EEXIST) {
- MP_ERR(ctx, "File '%s' already exists!\n", filename);
- return false;
- }
- if (!fp) {
- MP_ERR(ctx, "Error opening '%s' for writing!\n", filename);
- return false;
- }
-
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
@@ -305,8 +280,6 @@ static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image,
cinfo.client_data = &error_return_jmpbuf;
if (setjmp(cinfo.client_data)) {
jpeg_destroy_compress(&cinfo);
- fclose(fp);
- unlink(filename);
return false;
}
@@ -343,10 +316,7 @@ static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image,
jpeg_destroy_compress(&cinfo);
- if (!fclose(fp))
- return true;
- unlink(filename);
- return false;
+ return true;
}
#endif
@@ -370,8 +340,7 @@ static void log_side_data(struct image_writer_ctx *ctx, AVPacketSideData *data,
}
}
-static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image,
- const char *filename, bool overwrite)
+static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
{
const AVCodec *codec = NULL;
const AVOutputFormat *ofmt = NULL;
@@ -439,16 +408,8 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image,
goto free_data;
}
- if (!overwrite && mp_path_exists(filename)) {
- MP_ERR(ctx, "File '%s' already exists\n", filename);
- goto free_data;
- }
-
- ret = avio_open(&avioctx, filename, AVIO_FLAG_WRITE);
- if (ret < 0) {
- MP_ERR(ctx, "Could not open file '%s' for saving images\n", filename);
- goto free_data;
- }
+ avio_open_dyn_buf(&avioctx);
+ MP_HANDLE_OOM(avioctx);
fmtctx = avformat_alloc_context();
if (!fmtctx) {
@@ -526,10 +487,12 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image,
}
MP_DBG(ctx, "write_avif(): avio_size() = %"PRIi64"\n", avio_size(avioctx));
- success = true;
+ uint8_t *buf = NULL;
+ int written_size = avio_close_dyn_buf(avioctx, &buf);
+ success = fwrite(buf, written_size, 1, fp) == 1;
+ av_freep(&buf);
free_data:
- success = !avio_closep(&avioctx) && success;
avformat_free_context(fmtctx);
avcodec_free_context(&avctx);
av_packet_free(&pkt);
@@ -729,7 +692,7 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
mp_verbose(log, "input: %s\n", mp_image_params_to_str(&image->params));
struct image_writer_ctx ctx = { log, opts, image->fmt };
- bool (*write)(struct image_writer_ctx *, mp_image_t *, const char *, bool) = write_lavc;
+ bool (*write)(struct image_writer_ctx *, mp_image_t *, FILE *) = write_lavc;
int destfmt = 0;
#if HAVE_JPEG
@@ -766,10 +729,21 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
if (!dst)
return false;
- bool success = write(&ctx, dst, filename, overwrite);
- if (!success)
+ bool success = false;
+ FILE *fp = fopen(filename, overwrite ? "wb" : "wbx");
+ if (!fp) {
+ mp_err(log, "Error creating '%s' for writing: %s!\n",
+ filename, mp_strerror(errno));
+ goto done;
+ }
+
+ success = write(&ctx, dst, fp);
+ if (fclose(fp) || !success) {
mp_err(log, "Error writing file '%s'!\n", filename);
+ unlink(filename);
+ }
+done:
talloc_free(dst);
return success;
}