[vlc-commits] stream_filter: skiptags: extract and store tags

Francois Cartegnie git at videolan.org
Tue Jul 18 22:12:21 CEST 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Jul 11 11:15:52 2017 +0200| [65c9ae31bb3f0a1dd14aa93dd7e345804ec40ce5] | committer: Francois Cartegnie

stream_filter: skiptags: extract and store tags

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=65c9ae31bb3f0a1dd14aa93dd7e345804ec40ce5
---

 modules/stream_filter/skiptags.c | 113 +++++++++++++++++++++++++++++----------
 1 file changed, 85 insertions(+), 28 deletions(-)

diff --git a/modules/stream_filter/skiptags.c b/modules/stream_filter/skiptags.c
index 74cb66dba9..b7479d3d35 100644
--- a/modules/stream_filter/skiptags.c
+++ b/modules/stream_filter/skiptags.c
@@ -30,14 +30,36 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_stream.h>
+#include <vlc_block.h>
+
+#define MAX_TAGS 16
+#define MAX_TAG_SIZE (1<<17)
 
 struct skiptags_sys_t
 {
     uint64_t header_skip;
     /* TODO? also discard trailer tags? */
+    block_t *p_tags;
 };
 
-static int SkipID3Tag(stream_t *s)
+static struct skiptags_sys_t * skiptags_sys_New(void)
+{
+    struct skiptags_sys_t *sys = malloc(sizeof (*sys));
+    if(sys)
+    {
+        sys->header_skip = 0;
+        sys->p_tags = NULL;
+    }
+    return sys;
+}
+
+static void skiptags_sys_Delete(struct skiptags_sys_t *sys)
+{
+    block_ChainRelease(sys->p_tags);
+    free(sys);
+}
+
+static uint_fast32_t SkipID3Tag(stream_t *s)
 {
     const uint8_t *peek;
 
@@ -56,13 +78,11 @@ static int SkipID3Tag(stream_t *s)
     /* Skip the entire tag */
     msg_Dbg(s, "ID3v2.%"PRIuFAST8" revision %"PRIuFAST8" tag found, "
             "skipping %"PRIuFAST32" bytes", version, revision, size);
-    if (vlc_stream_Read(s, NULL, size) < (ssize_t)size)
-        return -1;
 
-    return 1;
+    return size;
 }
 
-static int SkipAPETag(stream_t *s)
+static uint_fast32_t SkipAPETag(stream_t *s)
 {
     const uint8_t *peek;
 
@@ -87,26 +107,44 @@ static int SkipAPETag(stream_t *s)
     if (flags & (1u << 30))
         size += 32;
 
-    /* Skip the entire tag */
-    if (vlc_stream_Read(s, NULL, size) < (ssize_t)size)
-        return -1;
-
     msg_Dbg(s, "AP2 v%"PRIuFAST32" tag found, "
             "skipping %"PRIuFAST32" bytes", version / 1000, size);
-    return 1;
+    return size;
 }
 
-static bool SkipTag(stream_t *s, int (*skipper)(stream_t *))
+static bool SkipTag(stream_t *s, uint_fast32_t (*skipper)(stream_t *),
+                    block_t **pp_block, unsigned *pi_tags_count)
 {
     uint_fast64_t offset = vlc_stream_Tell(s);
-    int val = skipper(s);
-    if (unlikely(val < 0))
-    {   /* I/O error, try to restore offset. If it fails, screwed. */
-        if (vlc_stream_Seek(s, offset))
-            msg_Err(s, "seek failure");
-        return false;
+    uint_fast32_t size = skipper(s);
+    if(size> 0)
+    {
+        /* Skip the entire tag */
+        ssize_t read;
+        if(*pi_tags_count < MAX_TAGS && size <= MAX_TAG_SIZE)
+        {
+            *pp_block = vlc_stream_Block(s, size);
+            read = *pp_block ? (ssize_t)(*pp_block)->i_buffer : -1;
+        }
+        else
+        {
+            read = vlc_stream_Read(s, NULL, size);
+        }
+
+        if(read < (ssize_t)size)
+        {
+            block_ChainRelease(*pp_block);
+            *pp_block = NULL;
+            if (unlikely(read < 0))
+            {   /* I/O error, try to restore offset. If it fails, screwed. */
+                if (vlc_stream_Seek(s, offset))
+                    msg_Err(s, "seek failure");
+                return false;
+            }
+        }
+        else (*pi_tags_count)++;
     }
-    return val != 0;
+    return size != 0;
 }
 
 static ssize_t Read(stream_t *stream, void *buf, size_t buflen)
@@ -131,9 +169,16 @@ static int Seek(stream_t *stream, uint64_t offset)
 
 static int Control(stream_t *stream, int query, va_list args)
 {
+    const struct skiptags_sys_t *sys = stream->p_sys;
     /* In principles, we should return the meta-data embedded in the skipped
      * tags in STREAM_GET_META. But the meta engine is devoted to that already.
      */
+    if( query == STREAM_GET_TAGS && sys->p_tags )
+    {
+        *va_arg( args, const block_t ** ) = sys->p_tags;
+        return VLC_SUCCESS;
+    }
+
     return vlc_stream_vaControl(stream->p_source, query, args);
 }
 
@@ -141,19 +186,31 @@ static int Open(vlc_object_t *obj)
 {
     stream_t *stream = (stream_t *)obj;
     stream_t *s = stream->p_source;
-
-    while (SkipTag(s, SkipID3Tag)||
-           SkipTag(s, SkipAPETag));
+    struct skiptags_sys_t *sys;
+
+    block_t *p_tags = NULL, *p_tag = NULL;
+    unsigned i_tagscount = 0;
+
+    while (SkipTag(s, SkipID3Tag, &p_tag, &i_tagscount)||
+           SkipTag(s, SkipAPETag, &p_tag, &i_tagscount))
+    {
+        if(p_tag)
+        {
+            p_tag->p_next = p_tags;
+            p_tags = p_tag;
+            p_tag = NULL;
+        }
+    }
 
     uint_fast64_t offset = vlc_stream_Tell(s);
-    if (offset == 0)
+    if (offset == 0 || !(sys = skiptags_sys_New()))
+    {
+        block_ChainRelease( p_tags );
         return VLC_EGENERIC; /* nothing to do */
-
-    struct skiptags_sys_t *sys = malloc(sizeof (*sys));
-    if (unlikely(sys == NULL))
-        return VLC_ENOMEM;
+    }
 
     sys->header_skip = offset;
+    sys->p_tags = p_tags;
     stream->p_sys = sys;
     stream->pf_read = Read;
     stream->pf_readdir = ReadDir;
@@ -165,9 +222,9 @@ static int Open(vlc_object_t *obj)
 static void Close(vlc_object_t *obj)
 {
     stream_t *stream = (stream_t *)obj;
-    stream_sys_t *sys = stream->p_sys;
+    struct skiptags_sys_t *sys = (struct skiptags_sys_t *) stream->p_sys;
 
-    free(sys);
+    skiptags_sys_Delete(sys);
 }
 
 vlc_module_begin()



More information about the vlc-commits mailing list