preparser: art: use new md5 API
[vlc.git] / modules / mux / extradata.c
blobe0c7365044225579174709b8bc2a1b138ac3a98a
1 /*****************************************************************************
2 * extradata.c: Muxing extradata builder/gatherer
3 *****************************************************************************
4 * Copyright (C) 2018 VideoLabs, VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include <vlc_common.h>
25 #include <vlc_codec.h>
27 #include "extradata.h"
28 #include "../packetizer/av1_obu.h"
29 #include "../packetizer/a52.h"
31 struct mux_extradata_builder_cb
33 int (*pf_init)(mux_extradata_builder_t *);
34 void (*pf_feed)(mux_extradata_builder_t *, const uint8_t *, size_t);
35 void (*pf_deinit)(mux_extradata_builder_t *);
38 struct mux_extradata_builder_t
40 struct mux_extradata_builder_cb cb;
41 void *priv;
42 uint8_t *p_extra;
43 size_t i_extra;
44 vlc_fourcc_t fcc;
47 static void ac3_extradata_builder_Feed(mux_extradata_builder_t *m,
48 const uint8_t *p_data, size_t i_data)
50 if(m->i_extra || i_data < VLC_A52_MIN_HEADER_SIZE ||
51 p_data[0] != 0x0B || p_data[1] != 0x77)
52 return;
54 struct vlc_a52_bitstream_info bsi;
55 if(vlc_a52_ParseAc3BitstreamInfo(&bsi, &p_data[4], /* start code + CRC */
56 VLC_A52_MIN_HEADER_SIZE - 4 ) != VLC_SUCCESS)
57 return;
59 m->p_extra = malloc(3);
60 if(!m->p_extra)
61 return;
62 m->i_extra = 3;
64 bs_t s;
65 bs_write_init(&s, m->p_extra, m->i_extra);
66 bs_write(&s, 2, bsi.i_fscod);
67 bs_write(&s, 5, bsi.i_bsid);
68 bs_write(&s, 3, bsi.i_bsmod);
69 bs_write(&s, 3, bsi.i_acmod);
70 bs_write(&s, 1, bsi.i_lfeon);
71 bs_write(&s, 5, bsi.i_frmsizcod >> 1); // bit_rate_code
72 bs_write(&s, 5, 0); // reserved
75 const struct mux_extradata_builder_cb ac3_cb =
77 NULL,
78 ac3_extradata_builder_Feed,
79 NULL,
82 static void eac3_extradata_builder_Feed(mux_extradata_builder_t *m,
83 const uint8_t *p_data, size_t i_data)
85 if(m->i_extra || i_data < VLC_A52_MIN_HEADER_SIZE ||
86 p_data[0] != 0x0B || p_data[1] != 0x77)
87 return;
89 struct vlc_a52_bitstream_info bsi;
90 if(vlc_a52_ParseEac3BitstreamInfo(&bsi, &p_data[2], /* start code */
91 i_data - 2) != VLC_SUCCESS)
92 return;
94 m->p_extra = malloc(5);
95 if(!m->p_extra)
96 return;
97 m->i_extra = 5;
99 bs_t s;
100 bs_write_init(&s, m->p_extra, m->i_extra);
101 const unsigned rgi_fscod_samplerates[] = { 48000, 44100, 32000 };
102 unsigned fs = rgi_fscod_samplerates[bsi.i_fscod];
103 unsigned numblks = bsi.eac3.i_numblkscod + 1;
104 if(numblks > 3)
105 numblks = 6;
106 unsigned data_rate = (bsi.eac3.i_frmsiz + 1) * fs / (numblks << 4); /* F.6.2.2 */
107 bs_write(&s, 13, data_rate);
108 bs_write(&s, 3, 0); // num_ind_sub - 1
109 bs_write(&s, 2, bsi.i_fscod);
110 bs_write(&s, 5, bsi.i_bsid);
111 bs_write(&s, 5, bsi.i_bsmod);
112 bs_write(&s, 3, bsi.i_acmod);
113 bs_write(&s, 1, bsi.i_lfeon);
114 bs_write(&s, 3, 0); // reserved
115 bs_write(&s, 4, 0); // num_dep_sub
116 bs_write(&s, 1, 0); // reserved
119 const struct mux_extradata_builder_cb eac3_cb =
121 NULL,
122 eac3_extradata_builder_Feed,
123 NULL,
126 static void av1_extradata_builder_Feed(mux_extradata_builder_t *m,
127 const uint8_t *p_data, size_t i_data)
129 if(m->i_extra)
130 return;
132 AV1_OBU_iterator_ctx_t ctx;
133 AV1_OBU_iterator_init(&ctx, p_data, i_data);
134 const uint8_t *p_obu; size_t i_obu;
135 while(AV1_OBU_iterate_next(&ctx, &p_obu, &i_obu))
137 enum av1_obu_type_e OBUtype = AV1_OBUGetType(p_obu);
138 if(OBUtype != AV1_OBU_SEQUENCE_HEADER)
139 continue;
140 av1_OBU_sequence_header_t *p_sh = AV1_OBU_parse_sequence_header(p_obu, i_obu);
141 if(p_sh)
143 m->i_extra = AV1_create_DecoderConfigurationRecord(&m->p_extra, p_sh,
144 1, (const uint8_t **)&p_obu, &i_obu);
145 AV1_release_sequence_header(p_sh);
147 break;
151 const struct mux_extradata_builder_cb av1_cb =
153 NULL,
154 av1_extradata_builder_Feed,
155 NULL,
158 void mux_extradata_builder_Delete(mux_extradata_builder_t *m)
160 if(m->cb.pf_deinit)
161 m->cb.pf_deinit(m);
162 free(m->p_extra);
163 free(m);
166 static const struct
168 enum mux_extradata_type_e type;
169 vlc_fourcc_t fcc;
170 const struct mux_extradata_builder_cb *cb;
171 } mappings[] = {
172 { EXTRADATA_ISOBMFF, VLC_CODEC_AV1, &av1_cb },
173 { EXTRADATA_ISOBMFF, VLC_CODEC_A52, &ac3_cb },
174 { EXTRADATA_ISOBMFF, VLC_CODEC_EAC3, &eac3_cb },
177 mux_extradata_builder_t * mux_extradata_builder_New(vlc_fourcc_t fcc,
178 enum mux_extradata_type_e type)
180 const struct mux_extradata_builder_cb *cb = NULL;
181 for(size_t i=0; i<ARRAY_SIZE(mappings); i++)
183 if(mappings[i].type != type || mappings[i].fcc != fcc)
184 continue;
185 cb = mappings[i].cb;
186 break;
189 if(cb == NULL)
190 return NULL;
192 mux_extradata_builder_t *m = calloc(1, sizeof(*m));
193 if(m)
195 m->fcc = fcc;
196 m->cb = *cb;
197 if(m->cb.pf_init && m->cb.pf_init(m) != 0)
199 free(m);
200 m = NULL;
203 return m;
206 size_t mux_extradata_builder_Get(mux_extradata_builder_t *m, const uint8_t **a)
208 *a = m->p_extra;
209 return m->i_extra;
212 void mux_extradata_builder_Feed(mux_extradata_builder_t *m,
213 const uint8_t *p_data, size_t i_data)
215 m->cb.pf_feed(m, p_data, i_data);