]> git.sesse.net Git - vlc/blob - modules/codec/xwd.c
mediacodec: fix warning
[vlc] / modules / codec / xwd.c
1 /*****************************************************************************
2  * xwd.c: X Window system raster image dump pseudo-decoder
3  *****************************************************************************
4  * Copyright (C) 2012 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <assert.h>
26 #include <arpa/inet.h>
27 #include <X11/XWDFile.h>
28
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
31 #include <vlc_codec.h>
32
33 static int Open(vlc_object_t *);
34
35 vlc_module_begin()
36     set_description(N_("XWD image decoder"))
37     set_capability("decoder", 50)
38     set_category(CAT_INPUT)
39     set_subcategory(SUBCAT_INPUT_VCODEC)
40     set_callbacks(Open, NULL)
41 vlc_module_end()
42
43 static picture_t *Decode(decoder_t *, block_t **);
44
45 static int Open(vlc_object_t *obj)
46 {
47     decoder_t *dec = (decoder_t *)obj;
48
49     if (dec->fmt_in.i_codec != VLC_CODEC_XWD)
50         return VLC_EGENERIC;
51
52     dec->pf_decode_video = Decode;
53     es_format_Copy(&dec->fmt_out, &dec->fmt_in);
54     dec->fmt_out.i_codec = VLC_CODEC_RGB32;
55     dec->fmt_out.i_cat = VIDEO_ES;
56     return VLC_SUCCESS;
57 }
58
59 static picture_t *Decode (decoder_t *dec, block_t **pp)
60 {
61     picture_t *pic = NULL;
62
63     if (pp == NULL)
64         return NULL;
65
66     block_t *block = *pp;
67     if (block == NULL)
68         return NULL;
69     *pp = NULL;
70
71     if (block->i_pts <= VLC_TS_INVALID)
72         goto drop; /* undated block, should never happen */
73     if (block->i_buffer < sz_XWDheader)
74         goto drop;
75
76     /* Skip XWD header */
77     const XWDFileHeader *hdr = (const void *)block->p_buffer;
78     uint32_t hdrlen = ntohl(hdr->header_size);
79     if (hdrlen < sz_XWDheader
80      || ntohl(hdr->file_version) < XWD_FILE_VERSION
81      || ntohl(hdr->pixmap_format) != 2 /* ZPixmap */)
82         goto drop;
83
84     hdrlen += ntohl(hdr->ncolors) * sz_XWDColor;
85     if (hdrlen > block->i_buffer)
86         goto drop;
87     block->p_buffer += hdrlen;
88     block->i_buffer -= hdrlen;
89
90     /* Parse XWD header */
91     vlc_fourcc_t chroma = 0;
92     switch (ntohl(hdr->pixmap_depth))
93     {
94         case 8:
95             if (ntohl(hdr->bits_per_pixel) == 8)
96                 chroma = VLC_CODEC_RGB8;
97             break;
98         case 15:
99             if (ntohl(hdr->bits_per_pixel) == 16)
100                 chroma = VLC_CODEC_RGB15;
101             break;
102         case 16:
103             if (ntohl(hdr->bits_per_pixel) == 16)
104                 chroma = VLC_CODEC_RGB16;
105             break;
106         case 24:
107             switch (ntohl(hdr->bits_per_pixel))
108             {
109                 case 32: chroma = VLC_CODEC_RGB32; break;
110                 case 24: chroma = VLC_CODEC_RGB24; break;
111             }
112             break;
113         case 32:
114             if (ntohl(hdr->bits_per_pixel) == 32)
115                 chroma = VLC_CODEC_ARGB;
116             break;
117     }
118     /* TODO: check image endianess, set RGB mask */
119     if (!chroma)
120         goto drop;
121
122     video_format_Setup(&dec->fmt_out.video, chroma,
123                        ntohl(hdr->pixmap_width), ntohl(hdr->pixmap_height),
124                        ntohl(hdr->pixmap_width), ntohl(hdr->pixmap_height),
125                        dec->fmt_in.video.i_sar_num,
126                        dec->fmt_in.video.i_sar_den);
127
128     const size_t copy = dec->fmt_out.video.i_width
129                         * (dec->fmt_out.video.i_bits_per_pixel / 8);
130     const uint32_t pitch = ntohl(hdr->bytes_per_line);
131
132     /* Build picture */
133     if (pitch < copy
134      || (block->i_buffer / pitch) < dec->fmt_out.video.i_height)
135         goto drop;
136
137     pic = decoder_NewPicture(dec);
138     if (pic == NULL)
139         goto drop;
140
141     const uint8_t *in = block->p_buffer;
142     uint8_t *out = pic->p->p_pixels;
143     for (unsigned i = 0; i < dec->fmt_out.video.i_height; i++)
144     {
145         memcpy(out, in, copy);
146         in += pitch;
147         out += pic->p->i_pitch;
148     }
149     pic->date = block->i_pts;
150     pic->b_progressive = true;
151
152 drop:
153     block_Release(block);
154     return pic;
155 }