summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-07-01 15:56:12 +0200
committerwm4 <wm4@nowhere>2017-07-01 15:56:12 +0200
commit91279390710954519be79cff8388873888bf2f42 (patch)
treee166303643359dba10aba888486b6cf642ead30d
parentaee81828e2e627ca33e66f87428add220b06f7a7 (diff)
downloadmpv-91279390710954519be79cff8388873888bf2f42.tar.bz2
mpv-91279390710954519be79cff8388873888bf2f42.tar.xz
x11: load icon differently
Now it's sourced from the etc/ PNG files directly, instead of preprocessing them with imagemagick. Add some ad-hoc code to decode PNG files with libavcodec. At least we can drop the zlib code in exchange.
-rwxr-xr-xTOOLS/gen-x11-icon.sh15
-rw-r--r--video/image_loader.c48
-rw-r--r--video/image_loader.h9
-rw-r--r--video/out/x11_common.c123
-rw-r--r--video/out/x11_icon.binbin8486 -> 0 bytes
-rw-r--r--wscript_build.py17
6 files changed, 112 insertions, 100 deletions
diff --git a/TOOLS/gen-x11-icon.sh b/TOOLS/gen-x11-icon.sh
deleted file mode 100755
index 34823aa710..0000000000
--- a/TOOLS/gen-x11-icon.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-# This script is expected to be called as TOOLS/gen-x11-icon.sh (it will access
-# etc/mpv-icon...), and it will write video/out/x11_icon.bin.
-
-conv() {
- echo
- echo `identify -format "icon: %w %h" "$1"`
- convert "$1" -depth 8 rgba:-
-}
-
-(echo "# File generated by gen-x11-icon.sh" ;
- conv etc/mpv-icon-8bit-16x16.png ;
- conv etc/mpv-icon-8bit-32x32.png ;
- conv etc/mpv-icon-8bit-64x64.png) | gzip -c > video/out/x11_icon.bin
diff --git a/video/image_loader.c b/video/image_loader.c
new file mode 100644
index 0000000000..9efc8b7310
--- /dev/null
+++ b/video/image_loader.c
@@ -0,0 +1,48 @@
+#include <libavcodec/avcodec.h>
+
+#include "common/common.h"
+#include "mp_image.h"
+#include "image_writer.h"
+
+#include "image_loader.h"
+
+struct mp_image *load_image_png_buf(void *buffer, size_t buffer_size, int imgfmt)
+{
+ const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_PNG);
+ if (!codec)
+ return NULL;
+
+ AVCodecContext *avctx = avcodec_alloc_context3(codec);
+ if (!avctx)
+ return NULL;
+
+ if (avcodec_open2(avctx, codec, NULL) < 0) {
+ avcodec_free_context(&avctx);
+ return NULL;
+ }
+
+ AVPacket *pkt = av_packet_alloc();
+ if (pkt) {
+ if (av_new_packet(pkt, buffer_size) >= 0)
+ memcpy(pkt->data, buffer, buffer_size);
+ }
+
+ // (There is only 1 outcome: either it takes it and decodes it, or not.)
+ avcodec_send_packet(avctx, pkt);
+ avcodec_send_packet(avctx, NULL);
+
+ av_packet_free(&pkt);
+
+ struct mp_image *res = NULL;
+ AVFrame *frame = av_frame_alloc();
+ if (frame && avcodec_receive_frame(avctx, frame) >= 0) {
+ struct mp_image *r = mp_image_from_av_frame(frame);
+ if (r)
+ res = convert_image(r, imgfmt, mp_null_log);
+ talloc_free(r);
+ }
+ av_frame_free(&frame);
+
+ avcodec_free_context(&avctx);
+ return res;
+}
diff --git a/video/image_loader.h b/video/image_loader.h
new file mode 100644
index 0000000000..f8b20c8857
--- /dev/null
+++ b/video/image_loader.h
@@ -0,0 +1,9 @@
+#ifndef MP_IMAGE_LOADER_H_
+#define MP_IMAGE_LOADER_H_
+
+#include <stddef.h>
+
+struct mp_image;
+struct mp_image *load_image_png_buf(void *buffer, size_t buffer_size, int imgfmt);
+
+#endif
diff --git a/video/out/x11_common.c b/video/out/x11_common.c
index 670dca9147..f46e78b8d9 100644
--- a/video/out/x11_common.c
+++ b/video/out/x11_common.c
@@ -38,8 +38,6 @@
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xrandr.h>
-#include <zlib.h>
-
#include "config.h"
#include "misc/bstr.h"
#include "options/options.h"
@@ -48,6 +46,8 @@
#include "common/msg.h"
#include "input/input.h"
#include "input/event.h"
+#include "video/image_loader.h"
+#include "video/mp_image.h"
#include "x11_common.h"
#include "mpv_talloc.h"
@@ -57,9 +57,6 @@
#include "osdep/timer.h"
#include "osdep/subprocess.h"
-// Specifically for mp_cancel
-#include "stream/stream.h"
-
#include "input/input.h"
#include "input/keycodes.h"
@@ -109,10 +106,26 @@ typedef struct
long state;
} MotifWmHints;
-static const char x11_icon[] =
-#include "video/out/x11_icon.inc"
+static const char x11_icon_16[] =
+#include "video/out/x11_icon_16.inc"
+;
+
+static const char x11_icon_32[] =
+#include "video/out/x11_icon_32.inc"
+;
+
+static const char x11_icon_64[] =
+#include "video/out/x11_icon_64.inc"
;
+#define ICON_ENTRY(var) { (char *)var, sizeof(var) }
+static const struct bstr x11_icons[] = {
+ ICON_ENTRY(x11_icon_16),
+ ICON_ENTRY(x11_icon_32),
+ ICON_ENTRY(x11_icon_64),
+ {0}
+};
+
static struct mp_log *x11_error_output;
static atomic_int x11_error_silence;
@@ -1318,92 +1331,36 @@ static void vo_x11_xembed_send_message(struct vo_x11_state *x11, long m[4])
XSendEvent(x11->display, x11->parent, False, NoEventMask, &ev);
}
-static bstr decompress_gz(bstr in)
-{
- bstr res = {0};
- z_stream zstream;
- uint8_t *dest;
- size_t size = in.len;
- int result;
-
- zstream.zalloc = (alloc_func) 0;
- zstream.zfree = (free_func) 0;
- zstream.opaque = (voidpf) 0;
- // 32 for gzip header, 15 for max. window bits
- if (inflateInit2(&zstream, 32 + 15) != Z_OK)
- goto error;
- zstream.next_in = (Bytef *) in.start;
- zstream.avail_in = size;
-
- dest = NULL;
- zstream.avail_out = size;
- do {
- size += 4000;
- dest = talloc_realloc_size(NULL, dest, size);
- zstream.next_out = (Bytef *) (dest + zstream.total_out);
- result = inflate(&zstream, Z_NO_FLUSH);
- if (result != Z_OK && result != Z_STREAM_END) {
- talloc_free(dest);
- dest = NULL;
- inflateEnd(&zstream);
- goto error;
- }
- zstream.avail_out += 4000;
- } while (zstream.avail_out == 4000 && zstream.avail_in != 0
- && result != Z_STREAM_END);
-
- size = zstream.total_out;
- inflateEnd(&zstream);
-
- res.start = dest;
- res.len = size;
-error:
- return res;
-}
-
-#define MAX_ICONS 10
-
static void vo_x11_set_wm_icon(struct vo_x11_state *x11)
{
- int num_icons = 0;
- void *icon_data[MAX_ICONS];
- int icon_w[MAX_ICONS], icon_h[MAX_ICONS];
-
- bstr uncompressed = decompress_gz((bstr){(char *)x11_icon, sizeof(x11_icon)});
- bstr data = uncompressed;
- while (data.len && num_icons < MAX_ICONS) {
- bstr line = bstr_getline(data, &data);
- if (bstr_eatstart0(&line, "icon: ")) {
- int w, h;
- if (bstr_sscanf(line, "%d %d", &w, &h) == 2) {
- int size = w * h * 4;
- icon_w[num_icons] = w;
- icon_h[num_icons] = h;
- icon_data[num_icons] = data.start;
- num_icons++;
- data = bstr_cut(data, size);
+ int icon_size = 0;
+ long *icon = talloc_array(NULL, long, 0);
+
+ for (int n = 0; x11_icons[n].start; n++) {
+ struct mp_image *img =
+ load_image_png_buf(x11_icons[n].start, x11_icons[n].len, IMGFMT_RGBA);
+ if (!img)
+ continue;
+ int new_size = 2 + img->w * img->h;
+ MP_RESIZE_ARRAY(NULL, icon, icon_size + new_size);
+ long *cur = icon + icon_size;
+ icon_size += new_size;
+ *cur++ = img->w;
+ *cur++ = img->h;
+ for (int y = 0; y < img->h; y++) {
+ uint8_t *s = (uint8_t *)img->planes[0] + img->stride[0] * y;
+ for (int x = 0; x < img->w; x++) {
+ *cur++ = s[x * 4 + 0] | (s[x * 4 + 1] << 8) |
+ (s[x * 4 + 2] << 16) | ((unsigned)s[x * 4 + 3] << 24);
}
}
- }
-
- int icon_size = 0;
- for (int n = 0; n < num_icons; n++)
- icon_size += 2 + icon_w[n] * icon_h[n];
- long *icon = talloc_array(NULL, long, icon_size);
- long *cur = icon;
- for (int n = 0; n < num_icons; n++) {
- *cur++ = icon_w[n];
- *cur++ = icon_h[n];
- uint8_t *s = icon_data[n];
- for (int i = 0; i < icon_h[n] * icon_w[n]; i++, s += 4)
- *cur++ = s[0] | (s[1] << 8) | (s[2] << 16) | ((unsigned)s[3] << 24);
+ talloc_free(img);
}
XChangeProperty(x11->display, x11->window, XA(x11, _NET_WM_ICON),
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)icon, icon_size);
talloc_free(icon);
- talloc_free(uncompressed.start);
}
static void vo_x11_create_window(struct vo *vo, XVisualInfo *vis,
diff --git a/video/out/x11_icon.bin b/video/out/x11_icon.bin
deleted file mode 100644
index 957d9fcffe..0000000000
--- a/video/out/x11_icon.bin
+++ /dev/null
Binary files differ
diff --git a/wscript_build.py b/wscript_build.py
index 7ecd14bd9f..c6fa552164 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -59,8 +59,20 @@ def build(ctx):
ctx(
features = "file2string",
- source = "video/out/x11_icon.bin",
- target = "video/out/x11_icon.inc",
+ source = "etc/mpv-icon-8bit-16x16.png",
+ target = "video/out/x11_icon_16.inc",
+ )
+
+ ctx(
+ features = "file2string",
+ source = "etc/mpv-icon-8bit-32x32.png",
+ target = "video/out/x11_icon_32.inc",
+ )
+
+ ctx(
+ features = "file2string",
+ source = "etc/mpv-icon-8bit-64x64.png",
+ target = "video/out/x11_icon_64.inc",
)
ctx(
@@ -315,6 +327,7 @@ def build(ctx):
( "video/csputils.c" ),
( "video/fmt-conversion.c" ),
( "video/gpu_memcpy.c", "sse4-intrinsics" ),
+ ( "video/image_loader.c" ),
( "video/image_writer.c" ),
( "video/img_format.c" ),
( "video/hwdec.c" ),