[FFmpeg-cvslog] avcodec/dnxhd_parser: take into account compressed frame size and skip it

Paul B Mahol git at videolan.org
Fri Mar 24 16:59:27 EET 2017


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Mar 20 22:47:48 2017 +0100| [e1940d2458353943e2fab6bdb87d2278077e22a5] | committer: Paul B Mahol

avcodec/dnxhd_parser: take into account compressed frame size and skip it

Fixes #6214 and vsynth1-dnxhd-720p-hr-lb.

Signed-off-by: Paul B Mahol <onemda at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e1940d2458353943e2fab6bdb87d2278077e22a5
---

 libavcodec/dnxhd_parser.c                 | 65 +++++++++++++++++++++++++++----
 tests/ref/vsynth/vsynth1-dnxhd-720p-hr-lb |  4 +-
 2 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/libavcodec/dnxhd_parser.c b/libavcodec/dnxhd_parser.c
index 033b8ee..4f9bbce 100644
--- a/libavcodec/dnxhd_parser.c
+++ b/libavcodec/dnxhd_parser.c
@@ -31,8 +31,24 @@ typedef struct {
     ParseContext pc;
     int interlaced;
     int cur_field; /* first field is 0, second is 1 */
+    int cur_byte;
+    int remaining;
+    int w, h;
 } DNXHDParserContext;
 
+static int dnxhd_get_hr_frame_size(int cid, int w, int h)
+{
+    int result, i = ff_dnxhd_get_cid_table(cid);
+
+    if (i < 0)
+        return i;
+
+    result = ((h + 15) / 16) * ((w + 15) / 16) * ff_dnxhd_cid_table[i].packet_scale.num / ff_dnxhd_cid_table[i].packet_scale.den;
+    result = (result + 2048) / 4096 * 4096;
+
+    return FFMAX(result, 8192);
+}
+
 static int dnxhd_find_frame_end(DNXHDParserContext *dctx,
                                 const uint8_t *buf, int buf_size)
 {
@@ -51,30 +67,65 @@ static int dnxhd_find_frame_end(DNXHDParserContext *dctx,
                 pic_found = 1;
                 interlaced = (state&2)>>1; /* byte following the 5-byte header prefix */
                 cur_field = state&1;
+                dctx->cur_byte = 0;
+                dctx->remaining = 0;
                 break;
             }
         }
     }
 
-    if (pic_found) {
+    if (pic_found && !dctx->remaining) {
         if (!buf_size) /* EOF considered as end of frame */
             return 0;
         for (; i < buf_size; i++) {
+            dctx->cur_byte++;
             state = (state << 8) | buf[i];
-            if (ff_dnxhd_check_header_prefix(state & 0xffffffffff00LL) != 0) {
-                if (!interlaced || dctx->cur_field) {
+
+            if (dctx->cur_byte == 24) {
+                dctx->h = (state >> 32) & 0xFFFF;
+            } else if (dctx->cur_byte == 26) {
+                dctx->w = (state >> 32) & 0xFFFF;
+            } else if (dctx->cur_byte == 42) {
+                int cid = (state >> 32) & 0xFFFFFFFF;
+
+                if (cid <= 0)
+                    continue;
+
+                dctx->remaining = avpriv_dnxhd_get_frame_size(cid);
+                if (dctx->remaining <= 0) {
+                    dctx->remaining = dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h);
+                    if (dctx->remaining <= 0)
+                        return dctx->remaining;
+                }
+                if (buf_size - i >= dctx->remaining && (!dctx->interlaced || dctx->cur_field)) {
+                    int remaining = dctx->remaining;
+
                     pc->frame_start_found = 0;
                     pc->state64 = -1;
                     dctx->interlaced = interlaced;
                     dctx->cur_field = 0;
-                    return i - 5;
+                    dctx->cur_byte = 0;
+                    dctx->remaining = 0;
+                    return remaining;
                 } else {
-                    /* continue, to get the second field */
-                    dctx->interlaced = interlaced = (state&2)>>1;
-                    dctx->cur_field = cur_field = state&1;
+                    dctx->remaining -= buf_size;
                 }
             }
         }
+    } else if (pic_found) {
+        if (dctx->remaining > buf_size) {
+            dctx->remaining -= buf_size;
+        } else {
+            int remaining = dctx->remaining;
+
+            pc->frame_start_found = 0;
+            pc->state64 = -1;
+            dctx->interlaced = interlaced;
+            dctx->cur_field = 0;
+            dctx->cur_byte = 0;
+            dctx->remaining = 0;
+            return remaining;
+        }
     }
     pc->frame_start_found = pic_found;
     pc->state64 = state;
diff --git a/tests/ref/vsynth/vsynth1-dnxhd-720p-hr-lb b/tests/ref/vsynth/vsynth1-dnxhd-720p-hr-lb
index 3490d4a..27e5931 100644
--- a/tests/ref/vsynth/vsynth1-dnxhd-720p-hr-lb
+++ b/tests/ref/vsynth/vsynth1-dnxhd-720p-hr-lb
@@ -1,4 +1,4 @@
 08cbfe9b9f671cdb9dddc9307121d107 *tests/data/fate/vsynth1-dnxhd-720p-hr-lb.dnxhd
 409600 tests/data/fate/vsynth1-dnxhd-720p-hr-lb.dnxhd
-22eb87f0f8a50278355006fef70073a9 *tests/data/fate/vsynth1-dnxhd-720p-hr-lb.out.rawvideo
-stddev:    7.49 PSNR: 30.63 MAXDIFF:   64 bytes:  7603200/   608256
+77e510e3538313b1cbafb86ed248d2df *tests/data/fate/vsynth1-dnxhd-720p-hr-lb.out.rawvideo
+stddev:    7.50 PSNR: 30.62 MAXDIFF:   64 bytes:  7603200/   760320



More information about the ffmpeg-cvslog mailing list