FFmpeg
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 
26 static 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 
30 static 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 
34 static const uint16_t sample_rate_tab[16] = {
35  0, 42965, 43008, 44800, 53706, 53760
36 };
37 
38 static int skip_input(DBEContext *s, int nb_words)
39 {
40  if (nb_words > s->input_size) {
41  return AVERROR_INVALIDDATA;
42  }
43 
44  s->input += nb_words * s->word_bytes;
45  s->input_size -= nb_words;
46  return 0;
47 }
48 
49 static int parse_key(DBEContext *s)
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 
61 int 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;
65  PutBitContext pb;
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");
73  return AVERROR_INVALIDDATA;
74  }
75 
76  switch (s->word_bits) {
77  case 16:
78  for (i = 0; i < nb_words; i++, src += 2, dst += 2)
79  AV_WB16(dst, AV_RB16(src) ^ key);
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)
89  AV_WB24(dst, AV_RB24(src) ^ key);
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 
98 int 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 }
skip_bits_long
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition: get_bits.h:261
get_bits_left
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:678
init_put_bits
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition: put_bits.h:62
put_bits
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition: j2kenc.c:223
skip_input
static int skip_input(DBEContext *s, int nb_words)
Definition: dolby_e_parse.c:38
init_get_bits
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:497
skip_bits
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:364
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:318
u
#define u(width, name, range_min, range_max)
Definition: cbs_apv.c:83
DBEContext
Definition: dolby_e.h:72
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
s
#define s(width, name)
Definition: cbs_vp9.c:198
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:41
nb_channels_tab
static const uint8_t nb_channels_tab[MAX_PROG_CONF+1]
Definition: dolby_e_parse.c:30
get_bits.h
key
const char * key
Definition: hwcontext_opencl.c:189
PutBitContext
Definition: put_bits.h:50
DolbyEHeaderInfo
Definition: dolby_e.h:37
AV_WB16
#define AV_WB16(p, v)
Definition: intreadwrite.h:401
av_unreachable
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition: avassert.h:109
ff_dolby_e_parse_header
int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size)
Initialize DBEContext and parse Dolby E metadata.
Definition: dolby_e_parse.c:98
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
MAX_PROG_CONF
#define MAX_PROG_CONF
Definition: dolby_e.h:29
AV_WB24
#define AV_WB24(p, d)
Definition: intreadwrite.h:446
header
static const uint8_t header[24]
Definition: sdr2.c:68
skip_bits1
static void skip_bits1(GetBitContext *s)
Definition: get_bits.h:396
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
parse_key
static int parse_key(DBEContext *s)
Definition: dolby_e_parse.c:49
ret
ret
Definition: filter_design.txt:187
flush_put_bits
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition: put_bits.h:153
sample_rate_tab
static const uint16_t sample_rate_tab[16]
Definition: dolby_e_parse.c:34
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
dolby_e.h
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
AV_RB24
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_RB24
Definition: bytestream.h:97
put_bits.h
ff_dolby_e_convert_input
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...
Definition: dolby_e_parse.c:61
src
#define src
Definition: vp8dsp.c:248
AV_RB16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:98
nb_programs_tab
static const uint8_t nb_programs_tab[MAX_PROG_CONF+1]
Definition: dolby_e_parse.c:26