1/*
2 * copyright (c) 2008 Paul Kendall <paul@kcbbs.gen.nz>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/**
22 * @file
23 * AAC LATM parser
24 */
25
26#include <stdint.h>
27#include "parser.h"
28
29#define LATM_HEADER     0x56e000        // 0x2b7 (11 bits)
30#define LATM_MASK       0xFFE000        // top 11 bits
31#define LATM_SIZE_MASK  0x001FFF        // bottom 13 bits
32
33typedef struct LATMParseContext{
34    ParseContext pc;
35    int count;
36} LATMParseContext;
37
38/**
39 * Find the end of the current frame in the bitstream.
40 * @return the position of the first byte of the next frame, or -1
41 */
42static int latm_find_frame_end(AVCodecParserContext *s1, const uint8_t *buf,
43                               int buf_size)
44{
45    LATMParseContext *s = s1->priv_data;
46    ParseContext *pc    = &s->pc;
47    int pic_found, i;
48    uint32_t state;
49
50    pic_found = pc->frame_start_found;
51    state     = pc->state;
52
53    i = 0;
54    if (!pic_found) {
55        for (i = 0; i < buf_size; i++) {
56            state = (state<<8) | buf[i];
57            if ((state & LATM_MASK) == LATM_HEADER) {
58                i++;
59                s->count  = -i;
60                pic_found = 1;
61                break;
62            }
63        }
64    }
65
66    if (pic_found) {
67        /* EOF considered as end of frame */
68        if (buf_size == 0)
69            return 0;
70        if ((state & LATM_SIZE_MASK) - s->count <= buf_size) {
71            pc->frame_start_found = 0;
72            pc->state             = -1;
73            return (state & LATM_SIZE_MASK) - s->count;
74        }
75    }
76
77    s->count             += buf_size;
78    pc->frame_start_found = pic_found;
79    pc->state             = state;
80
81    return END_NOT_FOUND;
82}
83
84static int latm_parse(AVCodecParserContext *s1, AVCodecContext *avctx,
85                      const uint8_t **poutbuf, int *poutbuf_size,
86                      const uint8_t *buf, int buf_size)
87{
88    LATMParseContext *s = s1->priv_data;
89    ParseContext *pc    = &s->pc;
90    int next;
91
92    if (s1->flags & PARSER_FLAG_COMPLETE_FRAMES) {
93        next = buf_size;
94    } else {
95        next = latm_find_frame_end(s1, buf, buf_size);
96
97        if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
98            *poutbuf      = NULL;
99            *poutbuf_size = 0;
100            return buf_size;
101        }
102    }
103    *poutbuf      = buf;
104    *poutbuf_size = buf_size;
105    return next;
106}
107
108AVCodecParser ff_aac_latm_parser = {
109    .codec_ids      = { CODEC_ID_AAC_LATM },
110    .priv_data_size = sizeof(LATMParseContext),
111    .parser_parse   = latm_parse,
112    .parser_close   = ff_parse_close
113};
114