vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Mon Feb 1 22:48:50 2016 +0200| [68e80594cb97fe9e9b98bb7793162be2e658773f] | committer: Rémi Denis-Courmont
inflate: stream filter for deflate (refs #16412) This handles deflate encoding or application/zlib type transparently. (Note though that it fails to check and discard the application/zlib content-type from the underlying stream.) > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=68e80594cb97fe9e9b98bb7793162be2e658773f --- NEWS | 1 + modules/MODULES_LIST | 1 + modules/stream_filter/Makefile.am | 6 ++ modules/stream_filter/inflate.c | 202 +++++++++++++++++++++++++++++++++++++ po/POTFILES.in | 1 + 5 files changed, 211 insertions(+) diff --git a/NEWS b/NEWS index a4f4768..1c0a752 100644 --- a/NEWS +++ b/NEWS @@ -94,6 +94,7 @@ Stream filter: * Added ARIB STD-B25 TS streams decoder * Added stream prebuffering plugin * Removed HTTP Live streaming stream filter + * Added zlib (a.k.a. deflate) decompression filter Audio output: * Complete rewrite of the AudioTrack Android module. This is now the default. diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST index 0d57436..d30f8d1 100644 --- a/modules/MODULES_LIST +++ b/modules/MODULES_LIST @@ -193,6 +193,7 @@ $Id$ * idummy: dummy input * image: Image file video output * imem: memory input access module + * inflate: zlib decompression stream_filter module * integer_mixer: Integer audio mixer * invert: inverse video filter * iomx: IPC/OpenMaxIL for Android diff --git a/modules/stream_filter/Makefile.am b/modules/stream_filter/Makefile.am index d99cad0..064e229 100644 --- a/modules/stream_filter/Makefile.am +++ b/modules/stream_filter/Makefile.am @@ -16,6 +16,12 @@ stream_filter_LTLIBRARIES += libdecomp_plugin.la endif endif +libinflate_plugin_la_SOURCES = stream_filter/inflate.c +libinflate_plugin_la_LIBADD = -lz +if HAVE_ZLIB +stream_filter_LTLIBRARIES += libinflate_plugin.la +endif + libprefetch_plugin_la_SOURCES = stream_filter/prefetch.c libprefetch_plugin_la_LIBADD = $(LIBPTHREAD) stream_filter_LTLIBRARIES += libprefetch_plugin.la diff --git a/modules/stream_filter/inflate.c b/modules/stream_filter/inflate.c new file mode 100644 index 0000000..c915b60 --- /dev/null +++ b/modules/stream_filter/inflate.c @@ -0,0 +1,202 @@ +/***************************************************************************** + * inflate.c: zlib decompression module for VLC + ***************************************************************************** + * Copyright © 2016 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> +#include <zlib.h> + +#include <vlc_common.h> +#include <vlc_plugin.h> +#include <vlc_stream.h> + +struct stream_sys_t +{ + z_stream zstream; + bool eof; + unsigned char buffer[16384]; +}; + +static ssize_t Read(stream_t *stream, void *buf, size_t buflen) +{ + stream_sys_t *sys = stream->p_sys; + ssize_t val; + + if (sys->eof || unlikely(buflen == 0)) + return 0; + + if (buf == NULL) + { + char dummy[buflen > 4096 ? 4096 : buflen]; + + return Read(stream, dummy, sizeof (dummy)); + } + + sys->zstream.next_out = buf; + sys->zstream.avail_out = buflen; + + if (sys->zstream.avail_in == 0) + sys->zstream.next_in = sys->buffer; + + val = (sys->buffer + sizeof (sys->buffer)) + - (sys->zstream.next_in + sys->zstream.avail_in); + + if (val > 0) + { /* Fill input buffer if there is space left */ + val = stream_Read(stream->p_source, + sys->zstream.next_in + sys->zstream.avail_in, val); + if (val >= 0) + sys->zstream.avail_in += val; + } + + if (sys->zstream.avail_in == 0) + { + msg_Err(stream, "unexpected end of stream"); + return 0; + } + + val = inflate(&sys->zstream, Z_SYNC_FLUSH); + switch (val) + { + case Z_STREAM_END: + msg_Dbg(stream, "end of stream"); + sys->eof = true; + /* fall through */ + case Z_OK: + return buflen - sys->zstream.avail_out; + case Z_DATA_ERROR: + msg_Err(stream, "corrupt stream"); + sys->eof = true; + return -1; + case Z_BUF_ERROR: + if (sys->zstream.next_in == sys->buffer) + break; + + memmove(sys->buffer, sys->zstream.next_in, sys->zstream.avail_in); + sys->zstream.next_in = sys->buffer; + return Read(stream, buf, buflen); + } + + msg_Err(stream, "unhandled decompression error (%zd)", val); + return -1; +} + +static input_item_t *ReadDir(stream_t *stream) +{ + (void) stream; + return NULL; +} + +static int Seek(stream_t *stream, uint64_t offset) +{ + (void) stream; (void) offset; + return -1; +} + +static int Control(stream_t *stream, int query, va_list args) +{ + switch (query) + { + case STREAM_CAN_SEEK: + case STREAM_CAN_FASTSEEK: + *va_arg(args, bool *) = false; + break; + case STREAM_CAN_PAUSE: + case STREAM_CAN_CONTROL_PACE: + case STREAM_GET_PTS_DELAY: + case STREAM_GET_META: + case STREAM_GET_CONTENT_TYPE: + case STREAM_GET_SIGNAL: + case STREAM_SET_PAUSE_STATE: + return stream_vaControl(stream->p_source, query, args); + case STREAM_IS_DIRECTORY: + case STREAM_GET_SIZE: + case STREAM_GET_TITLE_INFO: + case STREAM_GET_TITLE: + case STREAM_GET_SEEKPOINT: + case STREAM_SET_TITLE: + case STREAM_SET_SEEKPOINT: + case STREAM_SET_PRIVATE_ID_STATE: + case STREAM_SET_PRIVATE_ID_CA: + case STREAM_GET_PRIVATE_ID_STATE: + return VLC_EGENERIC; + default: + msg_Err(stream, "unimplemented query (%d) in control", query); + return VLC_EGENERIC; + } + return VLC_SUCCESS; +} + +static int Open(vlc_object_t *obj) +{ + stream_t *stream = (stream_t *)obj; + const uint8_t *peek; + + /* See IETF RFC6713 */ + if (stream_Peek(stream->p_source, &peek, 2) < 2 + || (peek[0] & 0xF) != 8 || (peek[0] >> 4) > 7 || (U16_AT(peek) % 31) != 0) + return VLC_EGENERIC; + + stream_sys_t *sys = malloc(sizeof (*sys)); + if (unlikely(sys == NULL)) + return VLC_ENOMEM; + + sys->zstream.next_in = sys->buffer; + sys->zstream.avail_in = 0; + sys->zstream.zalloc = Z_NULL; + sys->zstream.zfree = Z_NULL; + sys->zstream.opaque = Z_NULL; + sys->eof = false; + + int ret = inflateInit(&sys->zstream); + if (ret != Z_OK) + { + free(sys); + return (ret == Z_MEM_ERROR) ? VLC_ENOMEM : VLC_EGENERIC; + } + + stream->p_sys = sys; + stream->pf_read = Read; + stream->pf_readdir = ReadDir; + stream->pf_seek = Seek; + stream->pf_control = Control; + return VLC_SUCCESS; +} + +static void Close (vlc_object_t *obj) +{ + stream_t *stream = (stream_t *)obj; + stream_sys_t *sys = stream->p_sys; + + inflateEnd(&sys->zstream); + free(sys); +} + +vlc_module_begin() + set_category(CAT_INPUT) + set_subcategory(SUBCAT_INPUT_STREAM_FILTER) + set_capability("stream_filter", 30) + + set_description(N_("Zlib decompression filter")) + set_callbacks(Open, Close) +vlc_module_end() diff --git a/po/POTFILES.in b/po/POTFILES.in index cdaf3da..1355098 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1033,6 +1033,7 @@ modules/stream_filter/cache_block.c modules/stream_filter/cache_read.c modules/stream_filter/decomp.c modules/stream_filter/hds/hds.c +modules/stream_filter/inflate.c modules/stream_filter/prefetch.c modules/stream_filter/record.c modules/stream_out/autodel.c _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
