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 *****************************************************************************/
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
31 #include <vlc_stream.h>
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
;
45 if (sys
->eof
|| unlikely(buflen
== 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
);
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
);
62 sys
->zstream
.avail_in
+= val
;
65 if (sys
->zstream
.avail_in
== 0)
67 msg_Err(stream
, "unexpected end of stream");
71 val
= inflate(&sys
->zstream
, Z_SYNC_FLUSH
);
75 msg_Dbg(stream
, "end of stream");
79 return buflen
- sys
->zstream
.avail_out
;
81 msg_Err(stream
, "corrupt stream");
85 if (sys
->zstream
.next_in
== sys
->buffer
)
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
);
97 static int ReadDir(stream_t
*stream
, input_item_node_t
*node
)
99 (void) stream
; (void) node
;
103 static int Seek(stream_t
*stream
, uint64_t offset
)
105 (void) stream
; (void) offset
;
109 static int Control(stream_t
*stream
, int query
, va_list args
)
113 case STREAM_CAN_SEEK
:
114 case STREAM_CAN_FASTSEEK
:
115 *va_arg(args
, bool *) = false;
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
:
137 msg_Err(stream
, "unimplemented query (%d) in control", query
);
143 static int Open(vlc_object_t
*obj
)
145 stream_t
*stream
= (stream_t
*)obj
;
149 /* See IETF RFC6713 */
150 if (vlc_stream_Peek(stream
->s
, &peek
, 2) < 2)
153 if ((peek
[0] & 0xF) == 8 && (peek
[0] >> 4) < 8 && (U16_AT(peek
) % 31) == 0)
154 bits
= 15; /* zlib */
156 if (!memcmp(peek
, "\x1F\x8B", 2))
157 bits
= 15 + 32; /* gzip */
161 stream_sys_t
*sys
= malloc(sizeof (*sys
));
162 if (unlikely(sys
== NULL
))
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
;
172 int ret
= inflateInit2(&sys
->zstream
, bits
);
176 return (ret
== Z_MEM_ERROR
) ? VLC_ENOMEM
: VLC_EGENERIC
;
180 stream
->pf_read
= Read
;
181 stream
->pf_readdir
= ReadDir
;
182 stream
->pf_seek
= Seek
;
183 stream
->pf_control
= Control
;
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
);
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
)