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 "get_bits.h"
22 #include "put_bits.h"
23 #include "dolby_e.h"
24 
25 static const uint8_t nb_programs_tab[MAX_PROG_CONF + 1] = {
26  2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 8, 1, 2, 3, 3, 4, 5, 6, 1, 2, 3, 4, 1, 1
27 };
28 
29 static const uint8_t nb_channels_tab[MAX_PROG_CONF + 1] = {
30  8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8
31 };
32 
33 static const uint16_t sample_rate_tab[16] = {
34  0, 42965, 43008, 44800, 53706, 53760
35 };
36 
37 static int skip_input(DBEContext *s, int nb_words)
38 {
39  if (nb_words > s->input_size) {
40  return AVERROR_INVALIDDATA;
41  }
42 
43  s->input += nb_words * s->word_bytes;
44  s->input_size -= nb_words;
45  return 0;
46 }
47 
48 static int parse_key(DBEContext *s)
49 {
50  if (s->key_present) {
51  const uint8_t *key = s->input;
52  int ret = skip_input(s, 1);
53  if (ret < 0)
54  return ret;
55  return AV_RB24(key) >> 24 - s->word_bits;
56  }
57  return 0;
58 }
59 
60 int ff_dolby_e_convert_input(DBEContext *s, int nb_words, int key)
61 {
62  const uint8_t *src = s->input;
63  uint8_t *dst = s->buffer;
64  PutBitContext pb;
65  int i;
66 
67  av_assert0(nb_words <= 1024u);
68 
69  if (nb_words > s->input_size) {
70  if (s->avctx)
71  av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n");
72  return AVERROR_INVALIDDATA;
73  }
74 
75  switch (s->word_bits) {
76  case 16:
77  for (i = 0; i < nb_words; i++, src += 2, dst += 2)
78  AV_WB16(dst, AV_RB16(src) ^ key);
79  break;
80  case 20:
81  init_put_bits(&pb, s->buffer, sizeof(s->buffer));
82  for (i = 0; i < nb_words; i++, src += 3)
83  put_bits(&pb, 20, AV_RB24(src) >> 4 ^ key);
84  flush_put_bits(&pb);
85  break;
86  case 24:
87  for (i = 0; i < nb_words; i++, src += 3, dst += 3)
88  AV_WB24(dst, AV_RB24(src) ^ key);
89  break;
90  default:
91  av_assert0(0);
92  }
93 
94  return init_get_bits(&s->gb, s->buffer, nb_words * s->word_bits);
95 }
96 
97 int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size)
98 {
99  DolbyEHeaderInfo *const header = &s->metadata;
100  int hdr, ret, key, mtd_size;
101 
102  if (buf_size < 3)
103  return AVERROR_INVALIDDATA;
104 
105  hdr = AV_RB24(buf);
106  if ((hdr & 0xfffffe) == 0x7888e) {
107  s->word_bits = 24;
108  } else if ((hdr & 0xffffe0) == 0x788e0) {
109  s->word_bits = 20;
110  } else if ((hdr & 0xfffe00) == 0x78e00) {
111  s->word_bits = 16;
112  } else {
113  if (s->avctx)
114  av_log(s->avctx, AV_LOG_ERROR, "Invalid frame header\n");
115  return AVERROR_INVALIDDATA;
116  }
117 
118  s->word_bytes = s->word_bits + 7 >> 3;
119  s->input = buf + s->word_bytes;
120  s->input_size = buf_size / s->word_bytes - 1;
121  s->key_present = hdr >> 24 - s->word_bits & 1;
122 
123  if ((key = parse_key(s)) < 0)
124  return key;
125  if ((ret = ff_dolby_e_convert_input(s, 1, key)) < 0)
126  return ret;
127 
128  skip_bits(&s->gb, 4);
129  mtd_size = get_bits(&s->gb, 10);
130  if (!mtd_size) {
131  if (s->avctx)
132  av_log(s->avctx, AV_LOG_ERROR, "Invalid metadata size\n");
133  return AVERROR_INVALIDDATA;
134  }
135 
136  if ((ret = ff_dolby_e_convert_input(s, mtd_size, key)) < 0)
137  return ret;
138 
139  skip_bits(&s->gb, 14);
140  header->prog_conf = get_bits(&s->gb, 6);
141  if (header->prog_conf > MAX_PROG_CONF) {
142  if (s->avctx)
143  av_log(s->avctx, AV_LOG_ERROR, "Invalid program configuration\n");
144  return AVERROR_INVALIDDATA;
145  }
146 
147  header->nb_channels = nb_channels_tab[header->prog_conf];
148  header->nb_programs = nb_programs_tab[header->prog_conf];
149 
150  header->fr_code = get_bits(&s->gb, 4);
151  header->fr_code_orig = get_bits(&s->gb, 4);
152  if (!(header->sample_rate = sample_rate_tab[header->fr_code]) ||
153  !sample_rate_tab[header->fr_code_orig]) {
154  if (s->avctx)
155  av_log(s->avctx, AV_LOG_ERROR, "Invalid frame rate code\n");
156  return AVERROR_INVALIDDATA;
157  }
158 
159  skip_bits_long(&s->gb, 88);
160  for (int i = 0; i < header->nb_channels; i++)
161  header->ch_size[i] = get_bits(&s->gb, 10);
162  header->mtd_ext_size = get_bits(&s->gb, 8);
163  header->meter_size = get_bits(&s->gb, 8);
164 
165  skip_bits_long(&s->gb, 10 * header->nb_programs);
166  for (int i = 0; i < header->nb_channels; i++) {
167  header->rev_id[i] = get_bits(&s->gb, 4);
168  skip_bits1(&s->gb);
169  header->begin_gain[i] = get_bits(&s->gb, 10);
170  header->end_gain[i] = get_bits(&s->gb, 10);
171  }
172 
173  if (get_bits_left(&s->gb) < 0) {
174  if (s->avctx)
175  av_log(s->avctx, AV_LOG_ERROR, "Read past end of metadata\n");
176  return AVERROR_INVALIDDATA;
177  }
178 
179  return skip_input(s, mtd_size + 1);
180 }
skip_bits_long
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition: get_bits.h:278
get_bits_left
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:695
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
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:37
init_get_bits
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:514
skip_bits
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:381
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:335
DBEContext
Definition: dolby_e.h:72
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
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:40
nb_channels_tab
static const uint8_t nb_channels_tab[MAX_PROG_CONF+1]
Definition: dolby_e_parse.c:29
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
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:97
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
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:413
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:48
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:143
sample_rate_tab
static const uint16_t sample_rate_tab[16]
Definition: dolby_e_parse.c:33
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:60
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:25