]> git.sesse.net Git - ffmpeg/blob - libavcodec/dca_parser.c
avcodec: Constify all the AVCodecParsers
[ffmpeg] / libavcodec / dca_parser.c
1 /*
2  * DCA parser
3  * Copyright (C) 2004 Gildas Bazin
4  * Copyright (C) 2004 Benjamin Zores
5  * Copyright (C) 2006 Benjamin Larsson
6  * Copyright (C) 2007 Konstantin Shishkov
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24
25 #include "dca.h"
26 #include "dca_core.h"
27 #include "dca_exss.h"
28 #include "dca_lbr.h"
29 #include "dca_syncwords.h"
30 #include "get_bits.h"
31 #include "parser.h"
32
33 typedef struct DCAParseContext {
34     ParseContext pc;
35     uint32_t lastmarker;
36     int size;
37     int framesize;
38     unsigned int startpos;
39     DCAExssParser exss;
40     unsigned int sr_code;
41 } DCAParseContext;
42
43 #define IS_CORE_MARKER(state) \
44     (((state & 0xFFFFFFFFF0FF) == (((uint64_t)DCA_SYNCWORD_CORE_14B_LE << 16) | 0xF007)) || \
45      ((state & 0xFFFFFFFFFFF0) == (((uint64_t)DCA_SYNCWORD_CORE_14B_BE << 16) | 0x07F0)) || \
46      ((state & 0xFFFFFFFF00FC) == (((uint64_t)DCA_SYNCWORD_CORE_LE     << 16) | 0x00FC)) || \
47      ((state & 0xFFFFFFFFFC00) == (((uint64_t)DCA_SYNCWORD_CORE_BE     << 16) | 0xFC00)))
48
49 #define IS_EXSS_MARKER(state)   ((state & 0xFFFFFFFF) == DCA_SYNCWORD_SUBSTREAM)
50
51 #define IS_MARKER(state)        (IS_CORE_MARKER(state) || IS_EXSS_MARKER(state))
52
53 #define CORE_MARKER(state)      ((state >> 16) & 0xFFFFFFFF)
54 #define EXSS_MARKER(state)      (state & 0xFFFFFFFF)
55
56 #define STATE_LE(state)     (((state & 0xFF00FF00) >> 8) | ((state & 0x00FF00FF) << 8))
57 #define STATE_14(state)     (((state & 0x3FFF0000) >> 8) | ((state & 0x00003FFF) >> 6))
58
59 #define CORE_FRAMESIZE(state)   (((state >> 4) & 0x3FFF) + 1)
60 #define EXSS_FRAMESIZE(state)   ((state & 0x2000000000) ? \
61                                  ((state >>  5) & 0xFFFFF) + 1 : \
62                                  ((state >> 13) & 0x0FFFF) + 1)
63
64 /**
65  * Find the end of the current frame in the bitstream.
66  * @return the position of the first byte of the next frame, or -1
67  */
68 static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
69                               int buf_size)
70 {
71     int start_found, size, i;
72     uint64_t state;
73     ParseContext *pc = &pc1->pc;
74
75     start_found = pc->frame_start_found;
76     state       = pc->state64;
77     size        = pc1->size;
78
79     i = 0;
80     if (!start_found) {
81         for (; i < buf_size; i++) {
82             size++;
83             state = (state << 8) | buf[i];
84
85             if (IS_MARKER(state) &&
86                 (!pc1->lastmarker ||
87                   pc1->lastmarker == CORE_MARKER(state) ||
88                   pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM)) {
89                 if (!pc1->lastmarker)
90                     pc1->startpos = IS_EXSS_MARKER(state) ? size - 4 : size - 6;
91
92                 if (IS_EXSS_MARKER(state))
93                     pc1->lastmarker = EXSS_MARKER(state);
94                 else
95                     pc1->lastmarker = CORE_MARKER(state);
96
97                 start_found = 1;
98                 size        = 0;
99
100                 i++;
101                 break;
102             }
103         }
104     }
105
106     if (start_found) {
107         for (; i < buf_size; i++) {
108             size++;
109             state = (state << 8) | buf[i];
110
111             if (start_found == 1) {
112                 switch (pc1->lastmarker) {
113                 case DCA_SYNCWORD_CORE_BE:
114                     if (size == 2) {
115                         pc1->framesize = CORE_FRAMESIZE(state);
116                         start_found    = 2;
117                     }
118                     break;
119                 case DCA_SYNCWORD_CORE_LE:
120                     if (size == 2) {
121                         pc1->framesize = CORE_FRAMESIZE(STATE_LE(state));
122                         start_found    = 4;
123                     }
124                     break;
125                 case DCA_SYNCWORD_CORE_14B_BE:
126                     if (size == 4) {
127                         pc1->framesize = CORE_FRAMESIZE(STATE_14(state));
128                         start_found    = 4;
129                     }
130                     break;
131                 case DCA_SYNCWORD_CORE_14B_LE:
132                     if (size == 4) {
133                         pc1->framesize = CORE_FRAMESIZE(STATE_14(STATE_LE(state)));
134                         start_found    = 4;
135                     }
136                     break;
137                 case DCA_SYNCWORD_SUBSTREAM:
138                     if (size == 6) {
139                         pc1->framesize = EXSS_FRAMESIZE(state);
140                         start_found    = 4;
141                     }
142                     break;
143                 default:
144                     av_assert0(0);
145                 }
146                 continue;
147             }
148
149             if (start_found == 2 && IS_EXSS_MARKER(state) &&
150                 pc1->framesize <= size + 2) {
151                 pc1->framesize  = size + 2;
152                 start_found     = 3;
153                 continue;
154             }
155
156             if (start_found == 3) {
157                 if (size == pc1->framesize + 4) {
158                     pc1->framesize += EXSS_FRAMESIZE(state);
159                     start_found     = 4;
160                 }
161                 continue;
162             }
163
164             if (pc1->framesize > size)
165                 continue;
166
167             if (IS_MARKER(state) &&
168                 (pc1->lastmarker == CORE_MARKER(state) ||
169                  pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM)) {
170                 pc->frame_start_found = 0;
171                 pc->state64           = -1;
172                 pc1->size             = 0;
173                 return IS_EXSS_MARKER(state) ? i - 3 : i - 5;
174             }
175         }
176     }
177
178     pc->frame_start_found = start_found;
179     pc->state64           = state;
180     pc1->size             = size;
181     return END_NOT_FOUND;
182 }
183
184 static av_cold int dca_parse_init(AVCodecParserContext *s)
185 {
186     DCAParseContext *pc1 = s->priv_data;
187
188     pc1->lastmarker = 0;
189     pc1->sr_code = -1;
190     return 0;
191 }
192
193 static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf,
194                             int buf_size, int *duration, int *sample_rate,
195                             int *profile)
196 {
197     DCAExssAsset *asset = &pc1->exss.assets[0];
198     GetBitContext gb;
199     DCACoreFrameHeader h;
200     uint8_t hdr[DCA_CORE_FRAME_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 };
201     int ret, frame_size;
202
203     if (buf_size < DCA_CORE_FRAME_HEADER_SIZE)
204         return AVERROR_INVALIDDATA;
205
206     if (AV_RB32(buf) == DCA_SYNCWORD_SUBSTREAM) {
207         if ((ret = ff_dca_exss_parse(&pc1->exss, buf, buf_size)) < 0)
208             return ret;
209
210         if (asset->extension_mask & DCA_EXSS_LBR) {
211             if ((ret = init_get_bits8(&gb, buf + asset->lbr_offset, asset->lbr_size)) < 0)
212                 return ret;
213
214             if (get_bits_long(&gb, 32) != DCA_SYNCWORD_LBR)
215                 return AVERROR_INVALIDDATA;
216
217             switch (get_bits(&gb, 8)) {
218             case DCA_LBR_HEADER_DECODER_INIT:
219                 pc1->sr_code = get_bits(&gb, 8);
220             case DCA_LBR_HEADER_SYNC_ONLY:
221                 break;
222             default:
223                 return AVERROR_INVALIDDATA;
224             }
225
226             if (pc1->sr_code >= FF_ARRAY_ELEMS(ff_dca_sampling_freqs))
227                 return AVERROR_INVALIDDATA;
228
229             *sample_rate = ff_dca_sampling_freqs[pc1->sr_code];
230             *duration = 1024 << ff_dca_freq_ranges[pc1->sr_code];
231             *profile = FF_PROFILE_DTS_EXPRESS;
232             return 0;
233         }
234
235         if (asset->extension_mask & DCA_EXSS_XLL) {
236             int nsamples_log2;
237
238             if ((ret = init_get_bits8(&gb, buf + asset->xll_offset, asset->xll_size)) < 0)
239                 return ret;
240
241             if (get_bits_long(&gb, 32) != DCA_SYNCWORD_XLL)
242                 return AVERROR_INVALIDDATA;
243
244             if (get_bits(&gb, 4))
245                 return AVERROR_INVALIDDATA;
246
247             skip_bits(&gb, 8);
248             skip_bits_long(&gb, get_bits(&gb, 5) + 1);
249             skip_bits(&gb, 4);
250             nsamples_log2 = get_bits(&gb, 4) + get_bits(&gb, 4);
251             if (nsamples_log2 > 24)
252                 return AVERROR_INVALIDDATA;
253
254             *sample_rate = asset->max_sample_rate;
255             *duration = (1 + (*sample_rate > 96000)) << nsamples_log2;
256             *profile = FF_PROFILE_DTS_HD_MA;
257             return 0;
258         }
259
260         return AVERROR_INVALIDDATA;
261     }
262
263     if ((ret = avpriv_dca_convert_bitstream(buf, DCA_CORE_FRAME_HEADER_SIZE,
264                                             hdr, DCA_CORE_FRAME_HEADER_SIZE)) < 0)
265         return ret;
266     if (avpriv_dca_parse_core_frame_header(&h, hdr, ret) < 0)
267         return AVERROR_INVALIDDATA;
268
269     *duration = h.npcmblocks * DCA_PCMBLOCK_SAMPLES;
270     *sample_rate = avpriv_dca_sample_rates[h.sr_code];
271     if (*profile != FF_PROFILE_UNKNOWN)
272         return 0;
273
274     *profile = FF_PROFILE_DTS;
275     if (h.ext_audio_present) {
276         switch (h.ext_audio_type) {
277         case DCA_EXT_AUDIO_XCH:
278         case DCA_EXT_AUDIO_XXCH:
279             *profile = FF_PROFILE_DTS_ES;
280             break;
281         case DCA_EXT_AUDIO_X96:
282             *profile = FF_PROFILE_DTS_96_24;
283             break;
284         }
285     }
286
287     frame_size = FFALIGN(h.frame_size, 4);
288     if (buf_size - 4 < frame_size)
289         return 0;
290
291     buf      += frame_size;
292     buf_size -= frame_size;
293     if (AV_RB32(buf) != DCA_SYNCWORD_SUBSTREAM)
294         return 0;
295     if (ff_dca_exss_parse(&pc1->exss, buf, buf_size) < 0)
296         return 0;
297
298     if (asset->extension_mask & DCA_EXSS_XLL)
299         *profile = FF_PROFILE_DTS_HD_MA;
300     else if (asset->extension_mask & (DCA_EXSS_XBR | DCA_EXSS_XXCH | DCA_EXSS_X96))
301         *profile = FF_PROFILE_DTS_HD_HRA;
302
303     return 0;
304 }
305
306 static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx,
307                      const uint8_t **poutbuf, int *poutbuf_size,
308                      const uint8_t *buf, int buf_size)
309 {
310     DCAParseContext *pc1 = s->priv_data;
311     ParseContext *pc = &pc1->pc;
312     int next, duration, sample_rate;
313
314     if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
315         next = buf_size;
316     } else {
317         next = dca_find_frame_end(pc1, buf, buf_size);
318
319         if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
320             *poutbuf      = NULL;
321             *poutbuf_size = 0;
322             return buf_size;
323         }
324
325         /* skip initial padding */
326         if (buf_size  > pc1->startpos) {
327             buf      += pc1->startpos;
328             buf_size -= pc1->startpos;
329         }
330         pc1->startpos = 0;
331     }
332
333     /* read the duration and sample rate from the frame header */
334     if (!dca_parse_params(pc1, buf, buf_size, &duration, &sample_rate, &avctx->profile)) {
335         if (!avctx->sample_rate)
336             avctx->sample_rate = sample_rate;
337         s->duration = av_rescale(duration, avctx->sample_rate, sample_rate);
338     } else
339         s->duration = 0;
340
341     *poutbuf      = buf;
342     *poutbuf_size = buf_size;
343     return next;
344 }
345
346 const AVCodecParser ff_dca_parser = {
347     .codec_ids      = { AV_CODEC_ID_DTS },
348     .priv_data_size = sizeof(DCAParseContext),
349     .parser_init    = dca_parse_init,
350     .parser_parse   = dca_parse,
351     .parser_close   = ff_parse_close,
352 };