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@gmail.com>
... | ... |
@@ -47,6 +47,14 @@ typedef struct DCAParseContext { |
47 | 47 |
#define CORE_MARKER(state) ((state >> 16) & 0xFFFFFFFF) |
48 | 48 |
#define EXSS_MARKER(state) (state & 0xFFFFFFFF) |
49 | 49 |
|
50 |
+#define STATE_LE(state) (((state & 0xFF00FF00) >> 8) | ((state & 0x00FF00FF) << 8)) |
|
51 |
+#define STATE_14(state) (((state & 0x3FFF0000) >> 8) | ((state & 0x00003FFF) >> 6)) |
|
52 |
+ |
|
53 |
+#define CORE_FRAMESIZE(state) (((state >> 4) & 0x3FFF) + 1) |
|
54 |
+#define EXSS_FRAMESIZE(state) ((state & 0x2000000000) ? \ |
|
55 |
+ ((state >> 5) & 0xFFFFF) + 1 : \ |
|
56 |
+ ((state >> 13) & 0x0FFFF) + 1) |
|
57 |
+ |
|
50 | 58 |
/** |
51 | 59 |
* Find the end of the current frame in the bitstream. |
52 | 60 |
* @return the position of the first byte of the next frame, or -1 |
... | ... |
@@ -54,12 +62,13 @@ typedef struct DCAParseContext { |
54 | 54 |
static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf, |
55 | 55 |
int buf_size) |
56 | 56 |
{ |
57 |
- int start_found, i; |
|
57 |
+ int start_found, size, i; |
|
58 | 58 |
uint64_t state; |
59 | 59 |
ParseContext *pc = &pc1->pc; |
60 | 60 |
|
61 | 61 |
start_found = pc->frame_start_found; |
62 | 62 |
state = pc->state64; |
63 |
+ size = pc1->size; |
|
63 | 64 |
|
64 | 65 |
i = 0; |
65 | 66 |
if (!start_found) { |
... | ... |
@@ -80,15 +89,75 @@ static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf, |
80 | 80 |
} |
81 | 81 |
} |
82 | 82 |
} |
83 |
+ |
|
83 | 84 |
if (start_found) { |
84 | 85 |
for (; i < buf_size; i++) { |
85 |
- pc1->size++; |
|
86 |
+ size++; |
|
86 | 87 |
state = (state << 8) | buf[i]; |
88 |
+ |
|
89 |
+ if (start_found == 1) { |
|
90 |
+ switch (pc1->lastmarker) { |
|
91 |
+ case DCA_SYNCWORD_CORE_BE: |
|
92 |
+ if (size == 2) { |
|
93 |
+ pc1->framesize = CORE_FRAMESIZE(state); |
|
94 |
+ start_found = 2; |
|
95 |
+ } |
|
96 |
+ break; |
|
97 |
+ case DCA_SYNCWORD_CORE_LE: |
|
98 |
+ if (size == 2) { |
|
99 |
+ pc1->framesize = CORE_FRAMESIZE(STATE_LE(state)); |
|
100 |
+ start_found = 2; |
|
101 |
+ } |
|
102 |
+ break; |
|
103 |
+ case DCA_SYNCWORD_CORE_14B_BE: |
|
104 |
+ if (size == 4) { |
|
105 |
+ pc1->framesize = CORE_FRAMESIZE(STATE_14(state)) * 8 / 14 * 2; |
|
106 |
+ start_found = 2; |
|
107 |
+ } |
|
108 |
+ break; |
|
109 |
+ case DCA_SYNCWORD_CORE_14B_LE: |
|
110 |
+ if (size == 4) { |
|
111 |
+ pc1->framesize = CORE_FRAMESIZE(STATE_14(STATE_LE(state))) * 8 / 14 * 2; |
|
112 |
+ start_found = 2; |
|
113 |
+ } |
|
114 |
+ break; |
|
115 |
+ case DCA_SYNCWORD_SUBSTREAM: |
|
116 |
+ if (size == 6) { |
|
117 |
+ pc1->framesize = EXSS_FRAMESIZE(state); |
|
118 |
+ start_found = 2; |
|
119 |
+ } |
|
120 |
+ break; |
|
121 |
+ default: |
|
122 |
+ av_assert0(0); |
|
123 |
+ } |
|
124 |
+ continue; |
|
125 |
+ } |
|
126 |
+ |
|
127 |
+ if (pc1->lastmarker == DCA_SYNCWORD_CORE_BE) { |
|
128 |
+ if (pc1->framesize > size + 2) |
|
129 |
+ continue; |
|
130 |
+ |
|
131 |
+ if (start_found == 2 && IS_EXSS_MARKER(state)) { |
|
132 |
+ pc1->framesize = size + 2; |
|
133 |
+ start_found = 3; |
|
134 |
+ continue; |
|
135 |
+ } |
|
136 |
+ |
|
137 |
+ if (start_found == 3) { |
|
138 |
+ if (size == pc1->framesize + 4) { |
|
139 |
+ pc1->framesize += EXSS_FRAMESIZE(state); |
|
140 |
+ start_found = 4; |
|
141 |
+ } |
|
142 |
+ continue; |
|
143 |
+ } |
|
144 |
+ } |
|
145 |
+ |
|
146 |
+ if (pc1->framesize > size) |
|
147 |
+ continue; |
|
148 |
+ |
|
87 | 149 |
if (IS_MARKER(state) && |
88 | 150 |
(pc1->lastmarker == CORE_MARKER(state) || |
89 | 151 |
pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM)) { |
90 |
- if (pc1->framesize > pc1->size) |
|
91 |
- continue; |
|
92 | 152 |
pc->frame_start_found = 0; |
93 | 153 |
pc->state64 = -1; |
94 | 154 |
pc1->size = 0; |
... | ... |
@@ -96,8 +165,10 @@ static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf, |
96 | 96 |
} |
97 | 97 |
} |
98 | 98 |
} |
99 |
+ |
|
99 | 100 |
pc->frame_start_found = start_found; |
100 | 101 |
pc->state64 = state; |
102 |
+ pc1->size = size; |
|
101 | 103 |
return END_NOT_FOUND; |
102 | 104 |
} |
103 | 105 |
|
... | ... |
@@ -110,11 +181,11 @@ static av_cold int dca_parse_init(AVCodecParserContext *s) |
110 | 110 |
} |
111 | 111 |
|
112 | 112 |
static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, |
113 |
- int *sample_rate, int *framesize) |
|
113 |
+ int *sample_rate) |
|
114 | 114 |
{ |
115 | 115 |
GetBitContext gb; |
116 | 116 |
uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 }; |
117 |
- int ret, sample_blocks, sr_code; |
|
117 |
+ int ret, sample_blocks; |
|
118 | 118 |
|
119 | 119 |
if (buf_size < 12) |
120 | 120 |
return AVERROR_INVALIDDATA; |
... | ... |
@@ -130,13 +201,8 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, |
130 | 130 |
return AVERROR_INVALIDDATA; |
131 | 131 |
*duration = 256 * (sample_blocks / 8); |
132 | 132 |
|
133 |
- *framesize = get_bits(&gb, 14) + 1; |
|
134 |
- if (*framesize < 95) |
|
135 |
- return AVERROR_INVALIDDATA; |
|
136 |
- |
|
137 |
- skip_bits(&gb, 6); |
|
138 |
- sr_code = get_bits(&gb, 4); |
|
139 |
- *sample_rate = avpriv_dca_sample_rates[sr_code]; |
|
133 |
+ skip_bits(&gb, 20); |
|
134 |
+ *sample_rate = avpriv_dca_sample_rates[get_bits(&gb, 4)]; |
|
140 | 135 |
if (*sample_rate == 0) |
141 | 136 |
return AVERROR_INVALIDDATA; |
142 | 137 |
|
... | ... |
@@ -164,7 +230,7 @@ static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx, |
164 | 164 |
} |
165 | 165 |
|
166 | 166 |
/* read the duration and sample rate from the frame header */ |
167 |
- if (!dca_parse_params(buf, buf_size, &duration, &sample_rate, &pc1->framesize)) { |
|
167 |
+ if (!dca_parse_params(buf, buf_size, &duration, &sample_rate)) { |
|
168 | 168 |
if (!avctx->sample_rate) |
169 | 169 |
avctx->sample_rate = sample_rate; |
170 | 170 |
s->duration = av_rescale(duration, avctx->sample_rate, sample_rate); |