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 Seek(stream_t
*stream
, uint64_t offset
)
99 (void) stream
; (void) offset
;
103 static int Control(stream_t
*stream
, int query
, va_list args
)
107 case STREAM_CAN_SEEK
:
108 case STREAM_CAN_FASTSEEK
:
109 *va_arg(args
, bool *) = false;
111 case STREAM_CAN_PAUSE
:
112 case STREAM_CAN_CONTROL_PACE
:
113 case STREAM_GET_PTS_DELAY
:
114 case STREAM_GET_META
:
115 case STREAM_GET_CONTENT_TYPE
:
116 case STREAM_GET_SIGNAL
:
117 case STREAM_SET_PAUSE_STATE
:
118 return vlc_stream_vaControl(stream
->s
, query
, args
);
119 case STREAM_GET_SIZE
:
120 case STREAM_GET_TITLE_INFO
:
121 case STREAM_GET_TITLE
:
122 case STREAM_GET_SEEKPOINT
:
123 case STREAM_SET_TITLE
:
124 case STREAM_SET_SEEKPOINT
:
125 case STREAM_SET_PRIVATE_ID_STATE
:
126 case STREAM_SET_PRIVATE_ID_CA
:
127 case STREAM_GET_PRIVATE_ID_STATE
:
130 msg_Err(stream
, "unimplemented query (%d) in control", query
);
136 static int Open(vlc_object_t
*obj
)
138 stream_t
*stream
= (stream_t
*)obj
;
142 /* See IETF RFC6713 */
143 if (vlc_stream_Peek(stream
->s
, &peek
, 2) < 2)
146 if ((peek
[0] & 0xF) == 8 && (peek
[0] >> 4) < 8 && (U16_AT(peek
) % 31) == 0)
147 bits
= 15; /* zlib */
149 if (!memcmp(peek
, "\x1F\x8B", 2))
150 bits
= 15 + 32; /* gzip */
154 stream_sys_t
*sys
= malloc(sizeof (*sys
));
155 if (unlikely(sys
== NULL
))
158 sys
->zstream
.next_in
= sys
->buffer
;
159 sys
->zstream
.avail_in
= 0;
160 sys
->zstream
.zalloc
= Z_NULL
;
161 sys
->zstream
.zfree
= Z_NULL
;
162 sys
->zstream
.opaque
= Z_NULL
;
165 int ret
= inflateInit2(&sys
->zstream
, bits
);
169 return (ret
== Z_MEM_ERROR
) ? VLC_ENOMEM
: VLC_EGENERIC
;
173 stream
->pf_read
= Read
;
174 stream
->pf_seek
= Seek
;
175 stream
->pf_control
= Control
;
179 static void Close (vlc_object_t
*obj
)
181 stream_t
*stream
= (stream_t
*)obj
;
182 stream_sys_t
*sys
= stream
->p_sys
;
184 inflateEnd(&sys
->zstream
);
189 set_category(CAT_INPUT
)
190 set_subcategory(SUBCAT_INPUT_STREAM_FILTER
)
191 set_capability("stream_filter", 330)
193 set_description(N_("Zlib decompression filter"))
194 set_callbacks(Open
, Close
)