History

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.

nanahi committed 2 years ago

Commit df01eba1 parent 9a861c91 file · +24 −50Browse files

Unified · Split

video/image_writer.c+24−50
@@ -163,19 +163,8 @@ static void prepare_avframe(AVFrame *pic, AVCodecContext *avctx, · 162 unmodified lines
163163 );
164164 }
165165
166−static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image,
167− const char *filename, bool overwrite)
166+static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
168167 {
169− FILE *fp = fopen(filename, overwrite ? "wb" : "wbx");
170− if (!fp && errno == EEXIST) {
171− MP_ERR(ctx, "File '%s' already exists!\n", filename);
172− return false;
173− }
174− if (!fp) {
175− MP_ERR(ctx, "Error opening '%s' for writing!\n", filename);
176− return false;
177− }
178−
179168 bool success = false;
180169 AVFrame *pic = NULL;
181170 AVPacket *pkt = NULL;
@@ -265,9 +254,6 @@ error_exit: · 83 unmodified lines
265254 avcodec_free_context(&avctx);
266255 av_frame_free(&pic);
267256 av_packet_free(&pkt);
268− success = success && !fclose(fp);
269− if (!success)
270− unlink(filename);
271257 return success;
272258 }
273259
@@ -282,19 +268,8 @@ static void write_jpeg_error_exit(j_common_ptr cinfo) · 8 unmodified lines
282268 longjmp(*(jmp_buf*)cinfo->client_data, 1);
283269 }
284270
285−static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image,
286− const char *filename, bool overwrite)
271+static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
287272 {
288− FILE *fp = fopen(filename, overwrite ? "wb" : "wbx");
289− if (!fp && errno == EEXIST) {
290− MP_ERR(ctx, "File '%s' already exists!\n", filename);
291− return false;
292− }
293− if (!fp) {
294− MP_ERR(ctx, "Error opening '%s' for writing!\n", filename);
295− return false;
296− }
297−
298273 struct jpeg_compress_struct cinfo;
299274 struct jpeg_error_mgr jerr;
300275
@@ -305,8 +280,6 @@ static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, · 4 unmodified lines
305280 cinfo.client_data = &error_return_jmpbuf;
306281 if (setjmp(cinfo.client_data)) {
307282 jpeg_destroy_compress(&cinfo);
308− fclose(fp);
309− unlink(filename);
310283 return false;
311284 }
312285
@@ -343,10 +316,7 @@ static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, · 30 unmodified lines
343316
344317 jpeg_destroy_compress(&cinfo);
345318
346− if (!fclose(fp))
347− return true;
348− unlink(filename);
349− return false;
319+ return true;
350320 }
351321
352322 #endif
@@ -370,8 +340,7 @@ static void log_side_data(struct image_writer_ctx *ctx, AVPacketSideData *data, · 17 unmodified lines
370340 }
371341 }
372342
373−static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image,
374− const char *filename, bool overwrite)
343+static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
375344 {
376345 const AVCodec *codec = NULL;
377346 const AVOutputFormat *ofmt = NULL;
@@ -439,16 +408,8 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, · 61 unmodified lines
439408 goto free_data;
440409 }
441410
442− if (!overwrite && mp_path_exists(filename)) {
443− MP_ERR(ctx, "File '%s' already exists\n", filename);
444− goto free_data;
445− }
446−
447− ret = avio_open(&avioctx, filename, AVIO_FLAG_WRITE);
448− if (ret < 0) {
449− MP_ERR(ctx, "Could not open file '%s' for saving images\n", filename);
450− goto free_data;
451− }
411+ avio_open_dyn_buf(&avioctx);
412+ MP_HANDLE_OOM(avioctx);
452413
453414 fmtctx = avformat_alloc_context();
454415 if (!fmtctx) {
@@ -526,10 +487,12 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, · 71 unmodified lines
526487 }
527488 MP_DBG(ctx, "write_avif(): avio_size() = %"PRIi64"\n", avio_size(avioctx));
528489
529− success = true;
490+ uint8_t *buf = NULL;
491+ int written_size = avio_close_dyn_buf(avioctx, &buf);
492+ success = fwrite(buf, written_size, 1, fp) == 1;
493+ av_freep(&buf);
530494
531495 free_data:
532− success = !avio_closep(&avioctx) && success;
533496 avformat_free_context(fmtctx);
534497 avcodec_free_context(&avctx);
535498 av_packet_free(&pkt);
@@ -729,7 +692,7 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, · 193 unmodified lines
729692 mp_verbose(log, "input: %s\n", mp_image_params_to_str(&image->params));
730693
731694 struct image_writer_ctx ctx = { log, opts, image->fmt };
732− bool (*write)(struct image_writer_ctx *, mp_image_t *, const char *, bool) = write_lavc;
695+ bool (*write)(struct image_writer_ctx *, mp_image_t *, FILE *) = write_lavc;
733696 int destfmt = 0;
734697
735698 #if HAVE_JPEG
@@ -766,10 +729,21 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, · 30 unmodified lines
766729 if (!dst)
767730 return false;
768731
769− bool success = write(&ctx, dst, filename, overwrite);
770− if (!success)
732+ bool success = false;
733+ FILE *fp = fopen(filename, overwrite ? "wb" : "wbx");
734+ if (!fp) {
735+ mp_err(log, "Error creating '%s' for writing: %s!\n",
736+ filename, mp_strerror(errno));
737+ goto done;
738+ }
739+
740+ success = write(&ctx, dst, fp);
741+ if (fclose(fp) || !success) {
771742 mp_err(log, "Error writing file '%s'!\n", filename);
743+ unlink(filename);
744+ }
772745
746+done:
773747 talloc_free(dst);
774748 return success;
775749 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t