qt: add device preferences for mmdevice
[vlc.git] / modules / stream_filter / inflate.c
blob36fa8e09c2f2f636e9840b5c1b88e7bb42b1f9eb
1 /*****************************************************************************
2 * inflate.c: zlib decompression module for VLC
3 *****************************************************************************
4 * Copyright © 2016 Rémi Denis-Courmont
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.
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.
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 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <stdlib.h>
26 #include <string.h>
27 #include <zlib.h>
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
31 #include <vlc_stream.h>
33 struct stream_sys_t
35 z_stream zstream;
36 bool eof;
37 unsigned char buffer[16384];
40 static ssize_t Read(stream_t *stream, void *buf, size_t buflen)
42 stream_sys_t *sys = stream->p_sys;
43 ssize_t val;
45 if (sys->eof || unlikely(buflen == 0))
46 return 0;
48 sys->zstream.next_out = buf;
49 sys->zstream.avail_out = buflen;
51 if (sys->zstream.avail_in == 0)
52 sys->zstream.next_in = sys->buffer;
54 val = (sys->buffer + sizeof (sys->buffer))
55 - (sys->zstream.next_in + sys->zstream.avail_in);
57 if (val > 0)
58 { /* Fill input buffer if there is space left */
59 val = vlc_stream_Read(stream->s,
60 sys->zstream.next_in + sys->zstream.avail_in, val);
61 if (val >= 0)
62 sys->zstream.avail_in += val;
65 if (sys->zstream.avail_in == 0)
67 msg_Err(stream, "unexpected end of stream");
68 return 0;
71 val = inflate(&sys->zstream, Z_SYNC_FLUSH);
72 switch (val)
74 case Z_STREAM_END:
75 msg_Dbg(stream, "end of stream");
76 sys->eof = true;
77 /* fall through */
78 case Z_OK:
79 return buflen - sys->zstream.avail_out;
80 case Z_DATA_ERROR:
81 msg_Err(stream, "corrupt stream");
82 sys->eof = true;
83 return -1;
84 case Z_BUF_ERROR:
85 if (sys->zstream.next_in == sys->buffer)
86 break;
88 memmove(sys->buffer, sys->zstream.next_in, sys->zstream.avail_in);
89 sys->zstream.next_in = sys->buffer;
90 return Read(stream, buf, buflen);
93 msg_Err(stream, "unhandled decompression error (%zd)", val);
94 return -1;
97 static int ReadDir(stream_t *stream, input_item_node_t *node)
99 (void) stream; (void) node;
100 return VLC_EGENERIC;
103 static int Seek(stream_t *stream, uint64_t offset)
105 (void) stream; (void) offset;
106 return -1;
109 static int Control(stream_t *stream, int query, va_list args)
111 switch (query)
113 case STREAM_CAN_SEEK:
114 case STREAM_CAN_FASTSEEK:
115 *va_arg(args, bool *) = false;
116 break;
117 case STREAM_CAN_PAUSE:
118 case STREAM_CAN_CONTROL_PACE:
119 case STREAM_GET_PTS_DELAY:
120 case STREAM_GET_META:
121 case STREAM_GET_CONTENT_TYPE:
122 case STREAM_GET_SIGNAL:
123 case STREAM_SET_PAUSE_STATE:
124 return vlc_stream_vaControl(stream->s, query, args);
125 case STREAM_IS_DIRECTORY:
126 case STREAM_GET_SIZE:
127 case STREAM_GET_TITLE_INFO:
128 case STREAM_GET_TITLE:
129 case STREAM_GET_SEEKPOINT:
130 case STREAM_SET_TITLE:
131 case STREAM_SET_SEEKPOINT:
132 case STREAM_SET_PRIVATE_ID_STATE:
133 case STREAM_SET_PRIVATE_ID_CA:
134 case STREAM_GET_PRIVATE_ID_STATE:
135 return VLC_EGENERIC;
136 default:
137 msg_Err(stream, "unimplemented query (%d) in control", query);
138 return VLC_EGENERIC;
140 return VLC_SUCCESS;
143 static int Open(vlc_object_t *obj)
145 stream_t *stream = (stream_t *)obj;
146 const uint8_t *peek;
147 int bits;
149 /* See IETF RFC6713 */
150 if (vlc_stream_Peek(stream->s, &peek, 2) < 2)
151 return VLC_EGENERIC;
153 if ((peek[0] & 0xF) == 8 && (peek[0] >> 4) < 8 && (U16_AT(peek) % 31) == 0)
154 bits = 15; /* zlib */
155 else
156 if (!memcmp(peek, "\x1F\x8B", 2))
157 bits = 15 + 32; /* gzip */
158 else
159 return VLC_EGENERIC;
161 stream_sys_t *sys = malloc(sizeof (*sys));
162 if (unlikely(sys == NULL))
163 return VLC_ENOMEM;
165 sys->zstream.next_in = sys->buffer;
166 sys->zstream.avail_in = 0;
167 sys->zstream.zalloc = Z_NULL;
168 sys->zstream.zfree = Z_NULL;
169 sys->zstream.opaque = Z_NULL;
170 sys->eof = false;
172 int ret = inflateInit2(&sys->zstream, bits);
173 if (ret != Z_OK)
175 free(sys);
176 return (ret == Z_MEM_ERROR) ? VLC_ENOMEM : VLC_EGENERIC;
179 stream->p_sys = sys;
180 stream->pf_read = Read;
181 stream->pf_readdir = ReadDir;
182 stream->pf_seek = Seek;
183 stream->pf_control = Control;
184 return VLC_SUCCESS;
187 static void Close (vlc_object_t *obj)
189 stream_t *stream = (stream_t *)obj;
190 stream_sys_t *sys = stream->p_sys;
192 inflateEnd(&sys->zstream);
193 free(sys);
196 vlc_module_begin()
197 set_category(CAT_INPUT)
198 set_subcategory(SUBCAT_INPUT_STREAM_FILTER)
199 set_capability("stream_filter", 330)
201 set_description(N_("Zlib decompression filter"))
202 set_callbacks(Open, Close)
203 vlc_module_end()