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
163 );163 );
164}164}
165 165
166static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image,166static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
167 const char *filename, bool overwrite)
168{167{
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
179 bool success = false;168 bool success = false;
180 AVFrame *pic = NULL;169 AVFrame *pic = NULL;
181 AVPacket *pkt = NULL;170 AVPacket *pkt = NULL;
@@ -265,9 +254,6 @@ error_exit: · 83 unmodified lines
265 avcodec_free_context(&avctx);254 avcodec_free_context(&avctx);
266 av_frame_free(&pic);255 av_frame_free(&pic);
267 av_packet_free(&pkt);256 av_packet_free(&pkt);
268 success = success && !fclose(fp);
269 if (!success)
270 unlink(filename);
271 return success;257 return success;
272}258}
273 259
@@ -282,19 +268,8 @@ static void write_jpeg_error_exit(j_common_ptr cinfo) · 8 unmodified lines
282 longjmp(*(jmp_buf*)cinfo->client_data, 1);268 longjmp(*(jmp_buf*)cinfo->client_data, 1);
283}269}
284 270
285static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image,271static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
286 const char *filename, bool overwrite)
287{272{
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
298 struct jpeg_compress_struct cinfo;273 struct jpeg_compress_struct cinfo;
299 struct jpeg_error_mgr jerr;274 struct jpeg_error_mgr jerr;
300 275
@@ -305,8 +280,6 @@ static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, · 4 unmodified lines
305 cinfo.client_data = &error_return_jmpbuf;280 cinfo.client_data = &error_return_jmpbuf;
306 if (setjmp(cinfo.client_data)) {281 if (setjmp(cinfo.client_data)) {
307 jpeg_destroy_compress(&cinfo);282 jpeg_destroy_compress(&cinfo);
308 fclose(fp);
309 unlink(filename);
310 return false;283 return false;
311 }284 }
312 285
@@ -343,10 +316,7 @@ static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, · 30 unmodified lines
343 316
344 jpeg_destroy_compress(&cinfo);317 jpeg_destroy_compress(&cinfo);
345 318
346 if (!fclose(fp))319 return true;
347 return true;
348 unlink(filename);
349 return false;
350}320}
351 321
352#endif322#endif
@@ -370,8 +340,7 @@ static void log_side_data(struct image_writer_ctx *ctx, AVPacketSideData *data, · 17 unmodified lines
370 }340 }
371}341}
372 342
373static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image,343static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
374 const char *filename, bool overwrite)
375{344{
376 const AVCodec *codec = NULL;345 const AVCodec *codec = NULL;
377 const AVOutputFormat *ofmt = NULL;346 const AVOutputFormat *ofmt = NULL;
@@ -439,16 +408,8 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, · 61 unmodified lines
439 goto free_data;408 goto free_data;
440 }409 }
441 410
442 if (!overwrite && mp_path_exists(filename)) {411 avio_open_dyn_buf(&avioctx);
443 MP_ERR(ctx, "File '%s' already exists\n", filename);412 MP_HANDLE_OOM(avioctx);
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 }
452 413
453 fmtctx = avformat_alloc_context();414 fmtctx = avformat_alloc_context();
454 if (!fmtctx) {415 if (!fmtctx) {
@@ -526,10 +487,12 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, · 71 unmodified lines
526 }487 }
527 MP_DBG(ctx, "write_avif(): avio_size() = %"PRIi64"\n", avio_size(avioctx));488 MP_DBG(ctx, "write_avif(): avio_size() = %"PRIi64"\n", avio_size(avioctx));
528 489
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);
530 494
531free_data:495free_data:
532 success = !avio_closep(&avioctx) && success;
533 avformat_free_context(fmtctx);496 avformat_free_context(fmtctx);
534 avcodec_free_context(&avctx);497 avcodec_free_context(&avctx);
535 av_packet_free(&pkt);498 av_packet_free(&pkt);
@@ -729,7 +692,7 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, · 193 unmodified lines
729 mp_verbose(log, "input: %s\n", mp_image_params_to_str(&image->params));692 mp_verbose(log, "input: %s\n", mp_image_params_to_str(&image->params));
730 693
731 struct image_writer_ctx ctx = { log, opts, image->fmt };694 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;
733 int destfmt = 0;696 int destfmt = 0;
734 697
735#if HAVE_JPEG698#if HAVE_JPEG
@@ -766,10 +729,21 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, · 30 unmodified lines
766 if (!dst)729 if (!dst)
767 return false;730 return false;
768 731
769 bool success = write(&ctx, dst, filename, overwrite);732 bool success = false;
770 if (!success)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) {
771 mp_err(log, "Error writing file '%s'!\n", filename);742 mp_err(log, "Error writing file '%s'!\n", filename);
743 unlink(filename);
744 }
772 745
746done:
773 talloc_free(dst);747 talloc_free(dst);
774 return success;748 return success;
775}749}

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