[FFmpeg-cvslog] avcodec/dca_parser: improve frame end search

foo86 git at videolan.org
Fri May 20 21:45:46 CEST 2016


ffmpeg | branch: master | foo86 <foobaz86 at gmail.com> | Fri May 13 12:48:28 2016 +0300| [a0349ae27c127df8c72de1c30dc4090360ec7ef4] | committer: James Almer

avcodec/dca_parser: improve frame end search

Parse core frame size directly when searching for frame end instead of
using value extracted from previous frame.

Account for unused bits when calculating sync word distance for 14-bit
streams to avoid alias sync detection.

Parse EXSS frame size and skip over EXSS frame to avoid alias sync
detection.

Signed-off-by: James Almer <jamrial at gmail.com>

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

 libavcodec/dca_parser.c |   94 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 80 insertions(+), 14 deletions(-)

diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c
index bde7dfe..0b09ba5 100644
--- a/libavcodec/dca_parser.c
+++ b/libavcodec/dca_parser.c
@@ -47,6 +47,14 @@ typedef struct DCAParseContext {
 #define CORE_MARKER(state)      ((state >> 16) & 0xFFFFFFFF)
 #define EXSS_MARKER(state)      (state & 0xFFFFFFFF)
 
+#define STATE_LE(state)     (((state & 0xFF00FF00) >> 8) | ((state & 0x00FF00FF) << 8))
+#define STATE_14(state)     (((state & 0x3FFF0000) >> 8) | ((state & 0x00003FFF) >> 6))
+
+#define CORE_FRAMESIZE(state)   (((state >> 4) & 0x3FFF) + 1)
+#define EXSS_FRAMESIZE(state)   ((state & 0x2000000000) ? \
+                                 ((state >>  5) & 0xFFFFF) + 1 : \
+                                 ((state >> 13) & 0x0FFFF) + 1)
+
 /**
  * Find the end of the current frame in the bitstream.
  * @return the position of the first byte of the next frame, or -1
@@ -54,12 +62,13 @@ typedef struct DCAParseContext {
 static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
                               int buf_size)
 {
-    int start_found, i;
+    int start_found, size, i;
     uint64_t state;
     ParseContext *pc = &pc1->pc;
 
     start_found = pc->frame_start_found;
     state       = pc->state64;
+    size        = pc1->size;
 
     i = 0;
     if (!start_found) {
@@ -80,15 +89,75 @@ static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
             }
         }
     }
+
     if (start_found) {
         for (; i < buf_size; i++) {
-            pc1->size++;
+            size++;
             state = (state << 8) | buf[i];
+
+            if (start_found == 1) {
+                switch (pc1->lastmarker) {
+                case DCA_SYNCWORD_CORE_BE:
+                    if (size == 2) {
+                        pc1->framesize = CORE_FRAMESIZE(state);
+                        start_found    = 2;
+                    }
+                    break;
+                case DCA_SYNCWORD_CORE_LE:
+                    if (size == 2) {
+                        pc1->framesize = CORE_FRAMESIZE(STATE_LE(state));
+                        start_found    = 2;
+                    }
+                    break;
+                case DCA_SYNCWORD_CORE_14B_BE:
+                    if (size == 4) {
+                        pc1->framesize = CORE_FRAMESIZE(STATE_14(state)) * 8 / 14 * 2;
+                        start_found    = 2;
+                    }
+                    break;
+                case DCA_SYNCWORD_CORE_14B_LE:
+                    if (size == 4) {
+                        pc1->framesize = CORE_FRAMESIZE(STATE_14(STATE_LE(state))) * 8 / 14 * 2;
+                        start_found    = 2;
+                    }
+                    break;
+                case DCA_SYNCWORD_SUBSTREAM:
+                    if (size == 6) {
+                        pc1->framesize = EXSS_FRAMESIZE(state);
+                        start_found    = 2;
+                    }
+                    break;
+                default:
+                    av_assert0(0);
+                }
+                continue;
+            }
+
+            if (pc1->lastmarker == DCA_SYNCWORD_CORE_BE) {
+                if (pc1->framesize > size + 2)
+                    continue;
+
+                if (start_found == 2 && IS_EXSS_MARKER(state)) {
+                    pc1->framesize = size + 2;
+                    start_found    = 3;
+                    continue;
+                }
+
+                if (start_found == 3) {
+                    if (size == pc1->framesize + 4) {
+                        pc1->framesize += EXSS_FRAMESIZE(state);
+                        start_found     = 4;
+                    }
+                    continue;
+                }
+            }
+
+            if (pc1->framesize > size)
+                continue;
+
             if (IS_MARKER(state) &&
                 (pc1->lastmarker == CORE_MARKER(state) ||
                  pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM)) {
-                if (pc1->framesize > pc1->size)
-                    continue;
                 pc->frame_start_found = 0;
                 pc->state64           = -1;
                 pc1->size             = 0;
@@ -96,8 +165,10 @@ static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
             }
         }
     }
+
     pc->frame_start_found = start_found;
     pc->state64           = state;
+    pc1->size             = size;
     return END_NOT_FOUND;
 }
 
@@ -110,11 +181,11 @@ static av_cold int dca_parse_init(AVCodecParserContext *s)
 }
 
 static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration,
-                            int *sample_rate, int *framesize)
+                            int *sample_rate)
 {
     GetBitContext gb;
     uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 };
-    int ret, sample_blocks, sr_code;
+    int ret, sample_blocks;
 
     if (buf_size < 12)
         return AVERROR_INVALIDDATA;
@@ -130,13 +201,8 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration,
         return AVERROR_INVALIDDATA;
     *duration = 256 * (sample_blocks / 8);
 
-    *framesize = get_bits(&gb, 14) + 1;
-    if (*framesize < 95)
-        return AVERROR_INVALIDDATA;
-
-    skip_bits(&gb, 6);
-    sr_code      = get_bits(&gb, 4);
-    *sample_rate = avpriv_dca_sample_rates[sr_code];
+    skip_bits(&gb, 20);
+    *sample_rate = avpriv_dca_sample_rates[get_bits(&gb, 4)];
     if (*sample_rate == 0)
         return AVERROR_INVALIDDATA;
 
@@ -164,7 +230,7 @@ static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx,
     }
 
     /* read the duration and sample rate from the frame header */
-    if (!dca_parse_params(buf, buf_size, &duration, &sample_rate, &pc1->framesize)) {
+    if (!dca_parse_params(buf, buf_size, &duration, &sample_rate)) {
         if (!avctx->sample_rate)
             avctx->sample_rate = sample_rate;
         s->duration = av_rescale(duration, avctx->sample_rate, sample_rate);



More information about the ffmpeg-cvslog mailing list