From 91279390710954519be79cff8388873888bf2f42 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 1 Jul 2017 15:56:12 +0200 Subject: 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. --- TOOLS/gen-x11-icon.sh | 15 ------ video/image_loader.c | 48 +++++++++++++++++++ video/image_loader.h | 9 ++++ video/out/x11_common.c | 123 ++++++++++++++++--------------------------------- video/out/x11_icon.bin | Bin 8486 -> 0 bytes wscript_build.py | 17 ++++++- 6 files changed, 112 insertions(+), 100 deletions(-) delete mode 100755 TOOLS/gen-x11-icon.sh create mode 100644 video/image_loader.c create mode 100644 video/image_loader.h delete mode 100644 video/out/x11_icon.bin 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 + +#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 + +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 #include -#include - #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 Binary files a/video/out/x11_icon.bin and /dev/null 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" ), -- cgit v1.2.3