[FFmpeg-devel] [PATCH] lavf: add zip protocol

Alexander Strasser eclipse7 at gmx.net
Wed Apr 1 21:22:28 CEST 2015


On 2015-03-28 23:30 +0100, Lukasz Marek wrote:
> W dniu sobota, 28 marca 2015 Peter Ross <pross at xvid.org> napisał(a):
> 
> > On Sat, Mar 28, 2015 at 08:38:40PM +0100, Lukasz Marek wrote:
> > > I assumed it is local file (no other option so far). So I stat full path
> > > (/tmp/outer.zip/tmp/inner.zip/tmp/data.bin) for being a file, if so then
> > I
> > > opened it as zip file and used fallback to open first file.
> > > If not then I stat by path components: /tmp/, /tmp/outer.zip, and so
> > on...
> > > /tmp/outer.zip is a file so I open it and treat rest of the uri as a path
> > > inside zip.
> >
> > walking the path means that the archive protocol must know about the
> > syntax of the underlying protocol (file, http, ftp, etc.). that seems
> > messy.
> > also inefficient if you have got to walk a long ftp path.
> 
> 
>  I think filesystem looks the same on every server, no matter it is http,
> ftp or any other server.
> 
> wouldn't we be better off defining a special character that seperates the
> > zip
> > path from the inner path. obviously we'd need some way of escaping the
> > character
> > if it is legitimately part of either path.
> 
> > In real life you might assume that archive has extension zip, rar,
> 7z,... and try to open according to it in first try, if user has archive
> with "ass" extension in directory called "data.zip" then they have to wait.
> i really would avoid to escape anything. this is just annoying. i remember
> i used to escape urls with so many ifs, if file then dont escape, if http
> then escape, and so on. handling archives with its own escapes is kinda
> stupid. it would be easier just to add an option to pass inner file.

  What about the following?

  ffplay zip://dir/a.zip/m.mkv  # open dir/a.zip, read file m.mkv inside
  ffplay -file m.mkv zip://dir/a.zip  # same effect as above
  ffplay zip://dir.zip/a.ass/m.txt # open dir.zip, read file a.ass/m.txt inside
  ffplay -file m.txt zip://dir.zip/a.ass # open dir.zip/a.ass, read file m.txt inside

  Patch that implements that on top of Lukasz's patch is attached.
Beware it is quickly implemented and only lightly tested, just to
show that it is possible to implement that behaviour. Do not expect
it to be beautiful and flawless.

  Also I didn't even attempt to work out details like option name and if
we should match first or last .zip occurrence when guessing.
 
  Alexander
-------------- next part --------------
From 0af78adac09fb6b93a4cc39c71d6e562f9689153 Mon Sep 17 00:00:00 2001
Message-Id: <0af78adac09fb6b93a4cc39c71d6e562f9689153.1427915596.git.eclipse7 at gmx.net>
From: Alexander Strasser <eclipse7 at gmx.net>
Date: Wed, 1 Apr 2015 21:08:42 +0200
Subject: [PATCH] WIP: lavf/zip: Guess zip file or use full path and option to
 select the file inside the archive

Signed-off-by: Alexander Strasser <eclipse7 at gmx.net>
---
 libavformat/zip.c | 33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/libavformat/zip.c b/libavformat/zip.c
index c9d6679..a240002 100644
--- a/libavformat/zip.c
+++ b/libavformat/zip.c
@@ -32,6 +32,7 @@ typedef struct {
     struct zip *z;
     struct zip_file *f;
 
+    char *file; //< file path relative to the root of the archive
     char *password;
     int file_index;
     int64_t filesize;
@@ -56,8 +57,7 @@ static int ffzip_split_url(URLContext *h, const char *url, char **file)
 {
     ZIPContext *zip = h->priv_data;
     int ret = 0;
-    struct stat st;
-    char *filename, *pos;
+    char *filename;
 
     *file = NULL;
 
@@ -68,25 +68,23 @@ static int ffzip_split_url(URLContext *h, const char *url, char **file)
     if (!filename)
         return AVERROR(ENOMEM);
 
-    pos = filename;
-    while (pos) {
-        if (pos != filename)
-            *pos = 0;
-        if ((stat(filename, &st) == 0) && S_ISREG(st.st_mode)) {
-            av_log(h, AV_LOG_DEBUG, "Trying to open file: %s\n", filename);
-            zip->z = zip_open(filename, 0, NULL);
-            break;
+    if (zip->file) {
+        *file = zip->file;
+    } else {
+        char * ext = filename;
+        while ((ext = strchr(ext, '.')) && ext) {
+            if (!strncmp(ext, ".zip/", 5)) {
+                *file = av_strdup(ext + 5);
+                *(ext + 5-1) = 0;
+                break;
+            }
+            ++ext;
         }
-        if (pos != filename)
-            *pos = '/';
-        pos = strchr(pos + 1, '/');
     }
+            av_log(h, AV_LOG_DEBUG, "Trying to open file: %s\n", filename);
+            zip->z = zip_open(filename, 0, NULL);
     if (!zip->z) {
         ret = AVERROR(EIO);
-    } else if (pos != filename && pos[1]) {
-        *file = av_strdup(pos + 1);
-        if (!*file)
-            ret = AVERROR(ENOMEM);
     }
     av_free(filename);
     return ret;
@@ -154,6 +152,7 @@ static int64_t ffzip_seek(URLContext *h, int64_t pos, int whence)
 #define E AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
     {"file_index", "set file index", OFFSET(file_index), AV_OPT_TYPE_INT, {.i64 = 0}, -1, INT_MAX, D|E },
+    {"file",       "set file", OFFSET(file), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
     {"password",   "set password", OFFSET(password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
     {NULL}
 };
-- 
1.8.4

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150401/347b4cb9/attachment.asc>


More information about the ffmpeg-devel mailing list