summaryrefslogtreecommitdiffstats
path: root/image_writer.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /image_writer.c
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2
mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in a more logical way. Make the top-level directory less cluttered as well. Renames the following directories: libaf -> audio/filter libao2 -> audio/out libvo -> video/out libmpdemux -> demux Split libmpcodecs: vf* -> video/filter vd*, dec_video.* -> video/decode mp_image*, img_format*, ... -> video/ ad*, dec_audio.* -> audio/decode libaf/format.* is moved to audio/ - this is similar to how mp_image.* is located in video/. Move most top-level .c/.h files to core. (talloc.c/.h is left on top- level, because it's external.) Park some of the more annoying files in compat/. Some of these are relicts from the time mplayer used ffmpeg internals. sub/ is not split, because it's too much of a mess (subtitle code is mixed with OSD display and rendering). Maybe the organization of core is not ideal: it mixes playback core (like mplayer.c) and utility helpers (like bstr.c/h). Should the need arise, the playback core will be moved somewhere else, while core contains all helper and common code.
Diffstat (limited to 'image_writer.c')
-rw-r--r--image_writer.c327
1 files changed, 0 insertions, 327 deletions
diff --git a/image_writer.c b/image_writer.c
deleted file mode 100644
index 877c89e700..0000000000
--- a/image_writer.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * This file is part of mplayer.
- *
- * mplayer 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.
- *
- * mplayer 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 mplayer. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <setjmp.h>
-
-#include <libswscale/swscale.h>
-#include <libavcodec/avcodec.h>
-
-#include "config.h"
-
-#ifdef CONFIG_JPEG
-#include <jpeglib.h>
-#endif
-
-#include "osdep/io.h"
-
-#include "image_writer.h"
-#include "talloc.h"
-#include "libmpcodecs/img_format.h"
-#include "libmpcodecs/mp_image.h"
-#include "libmpcodecs/dec_video.h"
-#include "libmpcodecs/vf.h"
-#include "fmt-conversion.h"
-
-#include "libmpcodecs/sws_utils.h"
-#include "libmpcodecs/vf.h"
-
-#include "m_option.h"
-
-const struct image_writer_opts image_writer_opts_defaults = {
- .format = "jpg",
- .png_compression = 7,
- .jpeg_quality = 90,
- .jpeg_optimize = 100,
- .jpeg_smooth = 0,
- .jpeg_dpi = 72,
- .jpeg_progressive = 0,
- .jpeg_baseline = 1,
-};
-
-#undef OPT_BASE_STRUCT
-#define OPT_BASE_STRUCT struct image_writer_opts
-
-const struct m_sub_options image_writer_conf = {
- .opts = (m_option_t[]) {
- OPT_INTRANGE("jpeg-quality", jpeg_quality, 0, 0, 100),
- OPT_INTRANGE("jpeg-optimize", jpeg_optimize, 0, 0, 100),
- OPT_INTRANGE("jpeg-smooth", jpeg_smooth, 0, 0, 100),
- OPT_INTRANGE("jpeg-dpi", jpeg_dpi, M_OPT_MIN, 1, 99999),
- OPT_MAKE_FLAGS("jpeg-progressive", jpeg_progressive, 0),
- OPT_MAKE_FLAGS("jpeg-baseline", jpeg_baseline, 0),
- OPT_INTRANGE("png-compression", png_compression, 0, 0, 9),
- OPT_STRING("format", format, 0),
- {0},
- },
- .size = sizeof(struct image_writer_opts),
- .defaults = &image_writer_opts_defaults,
-};
-
-struct image_writer_ctx {
- const struct image_writer_opts *opts;
- const struct img_writer *writer;
-};
-
-struct img_writer {
- const char *file_ext;
- int (*write)(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp);
- int *pixfmts;
- int lavc_codec;
-};
-
-static int write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
-{
- void *outbuffer = NULL;
- int success = 0;
- AVFrame *pic = NULL;
-
- struct AVCodec *codec = avcodec_find_encoder(ctx->writer->lavc_codec);
- AVCodecContext *avctx = NULL;
- if (!codec)
- goto print_open_fail;
- avctx = avcodec_alloc_context3(codec);
- if (!avctx)
- goto print_open_fail;
-
- avctx->time_base = AV_TIME_BASE_Q;
- avctx->width = image->width;
- avctx->height = image->height;
- avctx->pix_fmt = imgfmt2pixfmt(image->imgfmt);
- if (ctx->writer->lavc_codec == CODEC_ID_PNG)
- avctx->compression_level = ctx->opts->png_compression;
-
- if (avcodec_open2(avctx, codec, NULL) < 0) {
- print_open_fail:
- mp_msg(MSGT_CPLAYER, MSGL_INFO, "Could not open libavcodec encoder"
- " for saving images\n");
- goto error_exit;
- }
-
- size_t outbuffer_size = image->width * image->height * 3 * 2;
- outbuffer = malloc(outbuffer_size);
- if (!outbuffer)
- goto error_exit;
-
- pic = avcodec_alloc_frame();
- if (!pic)
- goto error_exit;
- avcodec_get_frame_defaults(pic);
- for (int n = 0; n < 4; n++) {
- pic->data[n] = image->planes[n];
- pic->linesize[n] = image->stride[n];
- }
- int size = avcodec_encode_video(avctx, outbuffer, outbuffer_size, pic);
- if (size < 1)
- goto error_exit;
-
- fwrite(outbuffer, size, 1, fp);
-
- success = 1;
-error_exit:
- if (avctx)
- avcodec_close(avctx);
- av_free(avctx);
- avcodec_free_frame(&pic);
- free(outbuffer);
- return success;
-}
-
-#ifdef CONFIG_JPEG
-
-static void write_jpeg_error_exit(j_common_ptr cinfo)
-{
- // NOTE: do not write error message, too much effort to connect the libjpeg
- // log callbacks with mplayer's log function mp_msp()
-
- // Return control to the setjmp point
- longjmp(*(jmp_buf*)cinfo->client_data, 1);
-}
-
-static int write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
-{
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
-
- cinfo.err = jpeg_std_error(&jerr);
- jerr.error_exit = write_jpeg_error_exit;
-
- jmp_buf error_return_jmpbuf;
- cinfo.client_data = &error_return_jmpbuf;
- if (setjmp(cinfo.client_data)) {
- jpeg_destroy_compress(&cinfo);
- return 0;
- }
-
- jpeg_create_compress(&cinfo);
- jpeg_stdio_dest(&cinfo, fp);
-
- cinfo.image_width = image->width;
- cinfo.image_height = image->height;
- cinfo.input_components = 3;
- cinfo.in_color_space = JCS_RGB;
-
- cinfo.write_JFIF_header = TRUE;
- cinfo.JFIF_major_version = 1;
- cinfo.JFIF_minor_version = 2;
- cinfo.density_unit = 1; /* 0=unknown, 1=dpi, 2=dpcm */
- /* Image DPI is determined by Y_density, so we leave that at
- jpeg_dpi if possible and crunch X_density instead (PAR > 1) */
- // NOTE: write_image never passes anamorphic images currently
- cinfo.X_density = ctx->opts->jpeg_dpi*image->width/image->w;
- cinfo.Y_density = ctx->opts->jpeg_dpi*image->height/image->h;
- cinfo.write_Adobe_marker = TRUE;
-
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, ctx->opts->jpeg_quality, ctx->opts->jpeg_baseline);
- cinfo.optimize_coding = ctx->opts->jpeg_optimize;
- cinfo.smoothing_factor = ctx->opts->jpeg_smooth;
-
- if (ctx->opts->jpeg_progressive)
- jpeg_simple_progression(&cinfo);
-
- jpeg_start_compress(&cinfo, TRUE);
-
- while (cinfo.next_scanline < cinfo.image_height) {
- JSAMPROW row_pointer[1];
- row_pointer[0] = image->planes[0] +
- cinfo.next_scanline * image->stride[0];
- jpeg_write_scanlines(&cinfo, row_pointer,1);
- }
-
- jpeg_finish_compress(&cinfo);
-
- jpeg_destroy_compress(&cinfo);
-
- return 1;
-}
-
-#endif
-
-static const struct img_writer img_writers[] = {
- { "png", write_lavc, .lavc_codec = CODEC_ID_PNG },
- { "ppm", write_lavc, .lavc_codec = CODEC_ID_PPM },
- { "pgm", write_lavc,
- .lavc_codec = CODEC_ID_PGM,
- .pixfmts = (int[]) { IMGFMT_Y800, 0 },
- },
- { "pgmyuv", write_lavc,
- .lavc_codec = CODEC_ID_PGMYUV,
- .pixfmts = (int[]) { IMGFMT_YV12, 0 },
- },
- { "tga", write_lavc,
- .lavc_codec = CODEC_ID_TARGA,
- .pixfmts = (int[]) { IMGFMT_BGR24, IMGFMT_BGRA, IMGFMT_BGR15LE,
- IMGFMT_Y800, 0},
- },
-#ifdef CONFIG_JPEG
- { "jpg", write_jpeg },
- { "jpeg", write_jpeg },
-#endif
-};
-
-static const struct img_writer *get_writer(const struct image_writer_opts *opts)
-{
- const char *type = opts->format;
-
- for (size_t n = 0; n < sizeof(img_writers) / sizeof(img_writers[0]); n++) {
- const struct img_writer *writer = &img_writers[n];
- if (type && strcmp(type, writer->file_ext) == 0)
- return writer;
- }
-
- return &img_writers[0];
-}
-
-const char *image_writer_file_ext(const struct image_writer_opts *opts)
-{
- struct image_writer_opts defs = image_writer_opts_defaults;
-
- if (!opts)
- opts = &defs;
-
- return get_writer(opts)->file_ext;
-}
-
-int write_image(struct mp_image *image, const struct image_writer_opts *opts,
- const char *filename)
-{
- struct mp_image *allocated_image = NULL;
- struct image_writer_opts defs = image_writer_opts_defaults;
- int d_w = image->display_w ? image->display_w : image->w;
- int d_h = image->display_h ? image->display_h : image->h;
- bool is_anamorphic = image->w != d_w || image->h != d_h;
-
- if (!opts)
- opts = &defs;
-
- const struct img_writer *writer = get_writer(opts);
- struct image_writer_ctx ctx = { opts, writer };
- int destfmt = IMGFMT_RGB24;
-
- if (writer->pixfmts) {
- destfmt = writer->pixfmts[0]; // default to first pixel format
- for (int *fmt = writer->pixfmts; *fmt; fmt++) {
- if (*fmt == image->imgfmt) {
- destfmt = *fmt;
- break;
- }
- }
- }
-
- // Caveat: - no colorspace/levels conversion done if pixel formats equal
- // - RGB->YUV assumes BT.601
- // - color levels broken in various ways thanks to libswscale
- if (image->imgfmt != destfmt || is_anamorphic) {
- struct mp_image *dst = alloc_mpi(d_w, d_h, destfmt);
- vf_clone_mpi_attributes(dst, image);
-
- int flags = SWS_LANCZOS | SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP |
- SWS_ACCURATE_RND | SWS_BITEXACT;
-
- mp_image_swscale(dst, image, flags);
-
- allocated_image = dst;
- image = dst;
- }
-
- FILE *fp = fopen(filename, "wb");
- int success = 0;
- if (fp == NULL) {
- mp_msg(MSGT_CPLAYER, MSGL_ERR,
- "Error opening '%s' for writing!\n", filename);
- } else {
- success = writer->write(&ctx, image, fp);
- success = !fclose(fp) && success;
- if (!success)
- mp_msg(MSGT_CPLAYER, MSGL_ERR, "Error writing file '%s'!\n",
- filename);
- }
-
- free_mp_image(allocated_image);
-
- return success;
-}
-
-void dump_png(struct mp_image *image, const char *filename)
-{
- struct image_writer_opts opts = image_writer_opts_defaults;
- opts.format = "png";
- write_image(image, &opts, filename);
-}