[FFmpeg-devel] [PATCH/TOY] zip files

Peter Ross pross at xvid.org
Fri Mar 27 13:07:51 CET 2015


---
this was created to test the idea proposed in https://trac.ffmpeg.org/ticket/4374
as result, i think a zip:// protocol has some problems

- strict uri syntax can only open files in current directory
- user shouldn't have to specify the archive format. this should be autodetected (zip, rar, ... arj)
- want ability to grab zip files over other protocols 'vfs:http://subtitles.org/amovie.zip:amovie.srt'
- default action to open the first inner file?

 configure                |  4 +++
 libavformat/Makefile     |  1 +
 libavformat/allformats.c |  1 +
 libavformat/libzip.c     | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 97 insertions(+)
 create mode 100644 libavformat/libzip.c

diff --git a/configure b/configure
index a96bfb7..102361b 100755
--- a/configure
+++ b/configure
@@ -240,6 +240,7 @@ External library support:
   --enable-libsoxr         enable Include libsoxr resampling [no]
   --enable-libspeex        enable Speex de/encoding via libspeex [no]
   --enable-libssh          enable SFTP protocol via libssh [no]
+  --enable-libzip          enable zip protocol via libzip [no]
   --enable-libstagefright-h264  enable H.264 decoding via libstagefright [no]
   --enable-libtheora       enable Theora encoding via libtheora [no]
   --enable-libtwolame      enable MP2 encoding via libtwolame [no]
@@ -1404,6 +1405,7 @@ EXTERNAL_LIBRARY_LIST="
     libxcb_shape
     libxcb_xfixes
     libxvid
+    libzip
     libzmq
     libzvbi
     lzma
@@ -2561,6 +2563,7 @@ librtmpt_protocol_deps="librtmp"
 librtmpte_protocol_deps="librtmp"
 libsmbclient_protocol_deps="libsmbclient gplv3"
 libssh_protocol_deps="libssh"
+libzip_protocol_deps="libzip"
 mmsh_protocol_select="http_protocol"
 mmst_protocol_select="network"
 rtmp_protocol_deps="!librtmp_protocol"
@@ -4996,6 +4999,7 @@ enabled libx265           && require_pkg_config x265 x265.h x265_encoder_encode
                                die "ERROR: libx265 version must be >= 17."; }
 enabled libxavs           && require libxavs xavs.h xavs_encoder_encode -lxavs
 enabled libxvid           && require libxvid xvid.h xvid_global -lxvidcore
+enabled libzip            && require_pkg_config libzip zip.h zip_open
 enabled libzmq            && require_pkg_config libzmq zmq.h zmq_ctx_new
 enabled libzvbi           && require libzvbi libzvbi.h vbi_decoder_new -lzvbi
 enabled nvenc             && { check_header nvEncodeAPI.h || die "ERROR: nvEncodeAPI.h not found."; } &&
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 2118ff2..325628c 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -485,6 +485,7 @@ OBJS-$(CONFIG_LIBQUVI_DEMUXER)           += libquvi.o
 OBJS-$(CONFIG_LIBRTMP)                   += librtmp.o
 OBJS-$(CONFIG_LIBSSH_PROTOCOL)           += libssh.o
 OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL)     += libsmbclient.o
+OBJS-$(CONFIG_LIBZIP_PROTOCOL)           += libzip.o
 
 # protocols I/O
 OBJS-$(CONFIG_APPLEHTTP_PROTOCOL)        += hlsproto.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 26ccc27..93cd2e8 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -392,4 +392,5 @@ void av_register_all(void)
     REGISTER_PROTOCOL(LIBRTMPTE,        librtmpte);
     REGISTER_PROTOCOL(LIBSSH,           libssh);
     REGISTER_PROTOCOL(LIBSMBCLIENT,     libsmbclient);
+    REGISTER_PROTOCOL(LIBZIP,           libzip);
 }
diff --git a/libavformat/libzip.c b/libavformat/libzip.c
new file mode 100644
index 0000000..e6cfb50
--- /dev/null
+++ b/libavformat/libzip.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 Peter Ross <pross at xvid.org>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zip.h>
+#include "avformat.h"
+#include "internal.h"
+#include "url.h"
+
+//FIXME: url syntax cannot distinguish 'real zip file path' from 'virtual file path'
+// OK:  zip://tarball.zip/lol.gif
+// BROKEN: zip:///tmp/tarball.zip/lol.gif
+
+typedef struct {
+    const AVClass *class;
+    struct zip *zip;
+    struct zip_file *file;
+} ZipContext;
+
+static av_cold int libzip_open(URLContext *h, const char *url, int flags)
+{
+    ZipContext *libzip = h->priv_data;
+    char proto[10], password[1024], hostname[1024], path[MAX_URL_SIZE], *p;
+    int error;
+
+    av_url_split(proto, sizeof(proto),
+                 password, sizeof(password),
+                 hostname, sizeof(hostname),
+                 NULL,
+                 path, sizeof(path),
+                 url);
+
+    libzip->zip = zip_open(hostname, 0, &error);
+    if (!libzip->zip) {
+        char buf[1024];
+        zip_error_to_str(buf, sizeof(buf), error, errno);
+        av_log(h, AV_LOG_ERROR, "zip_open: %s\n", buf);
+        return AVERROR(EIO);
+    }
+
+    zip_set_default_password(libzip->zip, password);
+
+    for (p = path; *p == '/'; p++) ;
+    libzip->file = zip_fopen(libzip->zip, p, 0);
+    if (!libzip->file) {
+        av_log(h, AV_LOG_ERROR, "zip_fopen: %s\n", zip_strerror(libzip->zip));
+        zip_close(libzip->zip);
+        return AVERROR(EIO);
+    }
+
+    return 0;
+}
+
+static av_cold int libzip_close(URLContext *h)
+{
+    ZipContext *libzip = h->priv_data;
+    zip_fclose(libzip->file);
+    zip_close(libzip->zip);
+    return 0;
+}
+
+static int libzip_read(URLContext *h, unsigned char *buf, int size)
+{
+    ZipContext *libzip = h->priv_data;
+    int bytes_read = zip_fread(libzip->file, buf, size);
+    return bytes_read < 0 ? AVERROR(EIO) : bytes_read;
+}
+
+URLProtocol ff_libzip_protocol = {
+    .name                = "zip",
+    .url_open            = libzip_open,
+    .url_read            = libzip_read,
+    .url_close           = libzip_close,
+    .priv_data_size      = sizeof(ZipContext),
+};
-- 
2.1.0

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150327/7281686a/attachment.asc>


More information about the ffmpeg-devel mailing list