[FFmpeg-devel] [PATCH 06/10] avcodec/dca_parser: improve frame end search

foo86 foobaz86 at gmail.com
Fri May 13 11:48:28 CEST 2016


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.
---
 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);
-- 
2.8.1



More information about the ffmpeg-devel mailing list