xref: /third_party/ffmpeg/libavcodec/tak.c (revision cabdff1a)
1/*
2 * TAK common code
3 * Copyright (c) 2012 Paul B Mahol
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavutil/channel_layout.h"
23#include "libavutil/crc.h"
24#include "libavutil/intreadwrite.h"
25
26#define BITSTREAM_READER_LE
27#include "tak.h"
28
29static const int64_t tak_channel_layouts[] = {
30    0,
31    AV_CH_FRONT_LEFT,
32    AV_CH_FRONT_RIGHT,
33    AV_CH_FRONT_CENTER,
34    AV_CH_LOW_FREQUENCY,
35    AV_CH_BACK_LEFT,
36    AV_CH_BACK_RIGHT,
37    AV_CH_FRONT_LEFT_OF_CENTER,
38    AV_CH_FRONT_RIGHT_OF_CENTER,
39    AV_CH_BACK_CENTER,
40    AV_CH_SIDE_LEFT,
41    AV_CH_SIDE_RIGHT,
42    AV_CH_TOP_CENTER,
43    AV_CH_TOP_FRONT_LEFT,
44    AV_CH_TOP_FRONT_CENTER,
45    AV_CH_TOP_FRONT_RIGHT,
46    AV_CH_TOP_BACK_LEFT,
47    AV_CH_TOP_BACK_CENTER,
48    AV_CH_TOP_BACK_RIGHT,
49};
50
51static const uint16_t frame_duration_type_quants[] = {
52    3, 4, 6, 8, 4096, 8192, 16384, 512, 1024, 2048,
53};
54
55static int tak_get_nb_samples(int sample_rate, enum TAKFrameSizeType type)
56{
57    int nb_samples, max_nb_samples;
58
59    if (type <= TAK_FST_250ms) {
60        nb_samples     = sample_rate * frame_duration_type_quants[type] >>
61                         TAK_FRAME_DURATION_QUANT_SHIFT;
62        max_nb_samples = 16384;
63    } else if (type < FF_ARRAY_ELEMS(frame_duration_type_quants)) {
64        nb_samples     = frame_duration_type_quants[type];
65        max_nb_samples = sample_rate *
66                         frame_duration_type_quants[TAK_FST_250ms] >>
67                         TAK_FRAME_DURATION_QUANT_SHIFT;
68    } else {
69        return AVERROR_INVALIDDATA;
70    }
71
72    if (nb_samples <= 0 || nb_samples > max_nb_samples)
73        return AVERROR_INVALIDDATA;
74
75    return nb_samples;
76}
77
78int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size)
79{
80    uint32_t crc, CRC;
81
82    if (buf_size < 4)
83        return AVERROR_INVALIDDATA;
84    buf_size -= 3;
85
86    CRC = AV_RB24(buf + buf_size);
87    crc = av_crc(av_crc_get_table(AV_CRC_24_IEEE), 0xCE04B7U, buf, buf_size);
88    if (CRC != crc)
89        return AVERROR_INVALIDDATA;
90
91    return 0;
92}
93
94void ff_tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb)
95{
96    uint64_t channel_mask = 0;
97    int frame_type, i;
98
99    s->codec = get_bits(gb, TAK_ENCODER_CODEC_BITS);
100    skip_bits(gb, TAK_ENCODER_PROFILE_BITS);
101
102    frame_type = get_bits(gb, TAK_SIZE_FRAME_DURATION_BITS);
103    s->samples = get_bits64(gb, TAK_SIZE_SAMPLES_NUM_BITS);
104
105    s->data_type   = get_bits(gb, TAK_FORMAT_DATA_TYPE_BITS);
106    s->sample_rate = get_bits(gb, TAK_FORMAT_SAMPLE_RATE_BITS) +
107                     TAK_SAMPLE_RATE_MIN;
108    s->bps         = get_bits(gb, TAK_FORMAT_BPS_BITS) +
109                     TAK_BPS_MIN;
110    s->channels    = get_bits(gb, TAK_FORMAT_CHANNEL_BITS) +
111                     TAK_CHANNELS_MIN;
112
113    if (get_bits1(gb)) {
114        skip_bits(gb, TAK_FORMAT_VALID_BITS);
115        if (get_bits1(gb)) {
116            for (i = 0; i < s->channels; i++) {
117                int value = get_bits(gb, TAK_FORMAT_CH_LAYOUT_BITS);
118
119                if (value < FF_ARRAY_ELEMS(tak_channel_layouts))
120                    channel_mask |= tak_channel_layouts[value];
121            }
122        }
123    }
124
125    s->ch_layout     = channel_mask;
126    s->frame_samples = tak_get_nb_samples(s->sample_rate, frame_type);
127}
128
129int avpriv_tak_parse_streaminfo(TAKStreamInfo *s, const uint8_t *buf, int size)
130{
131    GetBitContext gb;
132    int ret = init_get_bits8(&gb, buf, size);
133
134    if (ret < 0)
135        return AVERROR_INVALIDDATA;
136
137    ff_tak_parse_streaminfo(s, &gb);
138
139    return 0;
140}
141
142int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb,
143                               TAKStreamInfo *ti, int log_level_offset)
144{
145    if (get_bits(gb, TAK_FRAME_HEADER_SYNC_ID_BITS) != TAK_FRAME_HEADER_SYNC_ID) {
146        av_log(avctx, AV_LOG_ERROR + log_level_offset, "missing sync id\n");
147        return AVERROR_INVALIDDATA;
148    }
149
150    ti->flags     = get_bits(gb, TAK_FRAME_HEADER_FLAGS_BITS);
151    ti->frame_num = get_bits(gb, TAK_FRAME_HEADER_NO_BITS);
152
153    if (ti->flags & TAK_FRAME_FLAG_IS_LAST) {
154        ti->last_frame_samples = get_bits(gb, TAK_FRAME_HEADER_SAMPLE_COUNT_BITS) + 1;
155        skip_bits(gb, 2);
156    } else {
157        ti->last_frame_samples = 0;
158    }
159
160    if (ti->flags & TAK_FRAME_FLAG_HAS_INFO) {
161        ff_tak_parse_streaminfo(ti, gb);
162
163        if (get_bits(gb, 6))
164            skip_bits(gb, 25);
165        align_get_bits(gb);
166    }
167
168    if (ti->flags & TAK_FRAME_FLAG_HAS_METADATA)
169        return AVERROR_INVALIDDATA;
170
171    if (get_bits_left(gb) < 24)
172        return AVERROR_INVALIDDATA;
173
174    skip_bits(gb, 24);
175
176    return 0;
177}
178