Stop the avio input at a point where amf_parse_object can
continue parsing the end of the object seamlessly, when all
data is available.

If unsupported data is encountered within the keyframes object,
try seeking to the start of the keyframes object - if the seek
back was successful, the caller can continue parsing the rest
of the AMF data.
---

This should achieve the same thing as Luca B's patch -
allowing parsing this in a single pass without seeking,
but falling back to trying to seek if running into something
unexpected. If we can't seek back, we can't do anything but
to abort parsing the rest of the AMF tree, but if we still
can seek back, we can parse the rest as normally (since
unexpected data within the keyframes object isn't an
error in the data in any way).

This should be a decent compromise between error resilience
and behaving well in the normal cases. (I had a look at the
original patch with hooks within amf_parse_object, and that
was indeed much messier than this.)

 libavformat/flvdec.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 62d25c8..52ba14f 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -135,7 +135,7 @@ static int parse_keyframes_index(AVFormatContext *s, 
AVIOContext *ioc, AVStream
     char str_val[256];
     int64_t *times = NULL;
     int64_t *filepositions = NULL;
-    int ret = 0;
+    int ret = AVERROR(ENOSYS);
     int64_t initial_pos = avio_tell(ioc);
 
     while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, 
sizeof(str_val)) > 0) {
@@ -173,6 +173,12 @@ static int parse_keyframes_index(AVFormatContext *s, 
AVIOContext *ioc, AVStream
             num_val = av_int2dbl(avio_rb64(ioc));
             current_array[i] = num_val;
         }
+        if (times && filepositions) {
+            // All done, exiting at a position allowing amf_parse_object
+            // to finish parsing the object
+            ret = 0;
+            break;
+        }
     }
 
     if (timeslen == fileposlen)
@@ -184,7 +190,10 @@ static int parse_keyframes_index(AVFormatContext *s, 
AVIOContext *ioc, AVStream
 finish:
     av_freep(&times);
     av_freep(&filepositions);
-    avio_seek(ioc, initial_pos, SEEK_SET);
+    // If we got unexpected data, but successfully reset back to
+    // the start pos, the caller can continue parsing
+    if (ret < 0 && avio_seek(ioc, initial_pos, SEEK_SET) > 0)
+        return 0;
     return ret;
 }
 
-- 
1.7.3.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to