FFmpeg
Loading...
Searching...
No Matches
dolby_e_parse.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 foo86
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/avassert.h"
22#include "get_bits.h"
23#include "put_bits.h"
24#include "dolby_e.h"
25
26static const uint8_t nb_programs_tab[MAX_PROG_CONF + 1] = {
27 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 8, 1, 2, 3, 3, 4, 5, 6, 1, 2, 3, 4, 1, 1
28};
29
30static const uint8_t nb_channels_tab[MAX_PROG_CONF + 1] = {
31 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8
32};
33
34static const uint16_t sample_rate_tab[16] = {
35 0, 42965, 43008, 44800, 53706, 53760
36};
37
38static int skip_input(DBEContext *s, int nb_words)
39{
40 if (nb_words > s->input_size) {
42 }
43
44 s->input += nb_words * s->word_bytes;
45 s->input_size -= nb_words;
46 return 0;
47}
48
50{
51 if (s->key_present) {
52 const uint8_t *key = s->input;
53 int ret = skip_input(s, 1);
54 if (ret < 0)
55 return ret;
56 return AV_RB24(key) >> 24 - s->word_bits;
57 }
58 return 0;
59}
60
61int ff_dolby_e_convert_input(DBEContext *s, int nb_words, int key)
62{
63 const uint8_t *src = s->input;
64 uint8_t *dst = s->buffer;
66 int i;
67
68 av_assert0(nb_words <= 1024u);
69
70 if (nb_words > s->input_size) {
71 if (s->avctx)
72 av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n");
74 }
75
76 switch (s->word_bits) {
77 case 16:
78 for (i = 0; i < nb_words; i++, src += 2, dst += 2)
80 break;
81 case 20:
82 init_put_bits(&pb, s->buffer, sizeof(s->buffer));
83 for (i = 0; i < nb_words; i++, src += 3)
84 put_bits(&pb, 20, AV_RB24(src) >> 4 ^ key);
85 flush_put_bits(&pb);
86 break;
87 case 24:
88 for (i = 0; i < nb_words; i++, src += 3, dst += 3)
90 break;
91 default:
92 av_unreachable("ff_dolby_e_parse_header() only sets 16, 20, 24 and errors out otherwise");
93 }
94
95 return init_get_bits(&s->gb, s->buffer, nb_words * s->word_bits);
96}
97
98int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size)
99{
100 DolbyEHeaderInfo *const header = &s->metadata;
101 int hdr, ret, key, mtd_size;
102
103 if (buf_size < 3)
104 return AVERROR_INVALIDDATA;
105
106 hdr = AV_RB24(buf);
107 if ((hdr & 0xfffffe) == 0x7888e) {
108 s->word_bits = 24;
109 } else if ((hdr & 0xffffe0) == 0x788e0) {
110 s->word_bits = 20;
111 } else if ((hdr & 0xfffe00) == 0x78e00) {
112 s->word_bits = 16;
113 } else {
114 if (s->avctx)
115 av_log(s->avctx, AV_LOG_ERROR, "Invalid frame header\n");
116 return AVERROR_INVALIDDATA;
117 }
118
119 s->word_bytes = s->word_bits + 7 >> 3;
120 s->input = buf + s->word_bytes;
121 s->input_size = buf_size / s->word_bytes - 1;
122 s->key_present = hdr >> 24 - s->word_bits & 1;
123
124 if ((key = parse_key(s)) < 0)
125 return key;
126 if ((ret = ff_dolby_e_convert_input(s, 1, key)) < 0)
127 return ret;
128
129 skip_bits(&s->gb, 4);
130 mtd_size = get_bits(&s->gb, 10);
131 if (!mtd_size) {
132 if (s->avctx)
133 av_log(s->avctx, AV_LOG_ERROR, "Invalid metadata size\n");
134 return AVERROR_INVALIDDATA;
135 }
136
137 if ((ret = ff_dolby_e_convert_input(s, mtd_size, key)) < 0)
138 return ret;
139
140 skip_bits(&s->gb, 14);
141 header->prog_conf = get_bits(&s->gb, 6);
142 if (header->prog_conf > MAX_PROG_CONF) {
143 if (s->avctx)
144 av_log(s->avctx, AV_LOG_ERROR, "Invalid program configuration\n");
145 return AVERROR_INVALIDDATA;
146 }
147
148 header->nb_channels = nb_channels_tab[header->prog_conf];
149 header->nb_programs = nb_programs_tab[header->prog_conf];
150
151 header->fr_code = get_bits(&s->gb, 4);
152 header->fr_code_orig = get_bits(&s->gb, 4);
153 if (!(header->sample_rate = sample_rate_tab[header->fr_code]) ||
154 !sample_rate_tab[header->fr_code_orig]) {
155 if (s->avctx)
156 av_log(s->avctx, AV_LOG_ERROR, "Invalid frame rate code\n");
157 return AVERROR_INVALIDDATA;
158 }
159
160 skip_bits_long(&s->gb, 88);
161 for (int i = 0; i < header->nb_channels; i++)
162 header->ch_size[i] = get_bits(&s->gb, 10);
163 header->mtd_ext_size = get_bits(&s->gb, 8);
164 header->meter_size = get_bits(&s->gb, 8);
165
166 skip_bits_long(&s->gb, 10 * header->nb_programs);
167 for (int i = 0; i < header->nb_channels; i++) {
168 header->rev_id[i] = get_bits(&s->gb, 4);
169 skip_bits1(&s->gb);
170 header->begin_gain[i] = get_bits(&s->gb, 10);
171 header->end_gain[i] = get_bits(&s->gb, 10);
172 }
173
174 if (get_bits_left(&s->gb) < 0) {
175 if (s->avctx)
176 av_log(s->avctx, AV_LOG_ERROR, "Read past end of metadata\n");
177 return AVERROR_INVALIDDATA;
178 }
179
180 return skip_input(s, mtd_size + 1);
181}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition avassert.h:109
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define MAX_PROG_CONF
Definition dolby_e.h:29
static int parse_key(DBEContext *s)
static const uint8_t nb_channels_tab[MAX_PROG_CONF+1]
static int skip_input(DBEContext *s, int nb_words)
int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size)
Initialize DBEContext and parse Dolby E metadata.
int ff_dolby_e_convert_input(DBEContext *s, int nb_words, int key)
Use the provided key to transform the input into data (put into s->buffer) suitable for further proce...
static const uint8_t nb_programs_tab[MAX_PROG_CONF+1]
static const uint16_t sample_rate_tab[16]
const char * key
bitstream reader API header.
static int get_bits_left(GetBitContext *gb)
Definition get_bits.h:688
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition get_bits.h:280
static void skip_bits(GetBitContext *s, int n)
Definition get_bits.h:383
static void skip_bits1(GetBitContext *s)
Definition get_bits.h:416
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition get_bits.h:517
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
#define AV_WB24(p, d)
#define AV_WB16(p, v)
#define AV_RB24(x)
#define AV_RB16(p)
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition j2kenc.c:154
bitstream writer API
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition put_bits.h:62
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition put_bits.h:153
static const uint8_t header[24]
Definition sdr2.c:68
Dolby E reading context used by decoder and parser.
Definition dolby_e.h:72
Coded Dolby E header values up to end_gain element, plus derived values.
Definition dolby_e.h:37
#define av_log(a,...)
#define src
Definition vp8dsp.c:248