diff options
author | nanahi <130121847+na-na-hi@users.noreply.github.com> | 2024-03-19 05:06:44 -0400 |
---|---|---|
committer | Kacper Michajłow <kasper93@gmail.com> | 2024-03-19 19:30:27 +0100 |
commit | df01ebaafcd93fdc7d48e4e8292daf5f1e932f16 (patch) | |
tree | bcbe5086e07bb97cabd7d0bf30d62e1d3f13c697 /video | |
parent | 9a861c930bac32ee3febedc0b0653be4f6f66fef (diff) | |
download | mpv-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.c | 74 |
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; } |