1 /*
2 * Copyright 2006, 2007, 2008 Fluendo S.A.
3 * Authors: Jan Schmidt <jan@fluendo.com>
4 * Kapil Agrawal <kapil@fluendo.com>
5 * Julien Moutte <julien@fluendo.com>
6 *
7 * This library is licensed under 3 different licenses and you
8 * can choose to use it under the terms of any one of them. The
9 * three licenses are the MPL 1.1, the LGPL and the MIT license.
10 *
11 * MPL:
12 *
13 * The contents of this file are subject to the Mozilla Public License
14 * Version 1.1 (the "License"); you may not use this file except in
15 * compliance with the License. You may obtain a copy of the License at
16 * http://www.mozilla.org/MPL/.
17 *
18 * Software distributed under the License is distributed on an "AS IS"
19 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
20 * License for the specific language governing rights and limitations
21 * under the License.
22 *
23 * LGPL:
24 *
25 * This library is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU Library General Public
27 * License as published by the Free Software Foundation; either
28 * version 2 of the License, or (at your option) any later version.
29 *
30 * This library is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 * Library General Public License for more details.
34 *
35 * You should have received a copy of the GNU Library General Public
36 * License along with this library; if not, write to the
37 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
39 *
40 * MIT:
41 *
42 * Unless otherwise indicated, Source Code is licensed under MIT license.
43 * See further explanation attached in License Statement (distributed in the file
44 * LICENSE).
45 *
46 * Permission is hereby granted, free of charge, to any person obtaining a copy of
47 * this software and associated documentation files (the "Software"), to deal in
48 * the Software without restriction, including without limitation the rights to
49 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
50 * of the Software, and to permit persons to whom the Software is furnished to do
51 * so, subject to the following conditions:
52 *
53 * The above copyright notice and this permission notice shall be included in all
54 * copies or substantial portions of the Software.
55 *
56 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
59 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
60 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
61 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
62 * SOFTWARE.
63 *
64 * SPDX-License-Identifier: MPL-1.1 OR MIT OR LGPL-2.0-or-later
65 */
66
67 #ifdef HAVE_CONFIG_H
68 #include "config.h"
69 #endif
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include "gstbasetsmuxaac.h"
74 #include <string.h>
75
76 #define GST_CAT_DEFAULT gst_base_ts_mux_debug
77
78 static GstBuffer *
gst_base_ts_mux_prepare_aac_adts(GstBuffer * buf,GstBaseTsMux * mux,gboolean is_mpeg2,guint8 obj_type_profile,guint8 rate_idx,guint8 channels)79 gst_base_ts_mux_prepare_aac_adts (GstBuffer * buf,
80 GstBaseTsMux * mux, gboolean is_mpeg2, guint8 obj_type_profile,
81 guint8 rate_idx, guint8 channels)
82 {
83 guint8 adts_header[7] = { 0, };
84 gsize out_size = gst_buffer_get_size (buf) + 7;
85 GstBuffer *out_buf = gst_buffer_new_and_alloc (out_size);
86 gsize out_offset = 0;
87 GstMapInfo buf_map;
88
89 /* Generate ADTS header */
90 GST_DEBUG_OBJECT (mux, "Preparing AAC buffer for output");
91
92 gst_buffer_copy_into (out_buf, buf,
93 GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_TIMESTAMPS, 0, 0);
94
95 GST_DEBUG_OBJECT (mux, "Rate index %u, channels %u, object type/profile %u",
96 rate_idx, channels, obj_type_profile);
97
98 /* Sync point over a full byte */
99 adts_header[0] = 0xFF;
100 /* Sync point continued over first 4 bits + static 4 bits
101 * (ID, layer, protection)*/
102 adts_header[1] = 0xF1 | (is_mpeg2 ? 0x8 : 0x0);
103 /* Object type (MPEG4) / Profile (MPEG2) over first 2 bits */
104 adts_header[2] = (obj_type_profile - 1) << 6;
105 /* rate index over next 4 bits */
106 adts_header[2] |= (rate_idx << 2);
107 /* channels over last 2 bits */
108 adts_header[2] |= (channels & 0x4) >> 2;
109 /* channels continued over next 2 bits + 4 bits at zero */
110 adts_header[3] = (channels & 0x3) << 6;
111 /* frame size over last 2 bits */
112 adts_header[3] |= (out_size & 0x1800) >> 11;
113 /* frame size continued over full byte */
114 adts_header[4] = (out_size & 0x1FF8) >> 3;
115 /* frame size continued first 3 bits */
116 adts_header[5] = (out_size & 0x7) << 5;
117 /* buffer fullness (0x7FF for VBR) over 5 last bits */
118 adts_header[5] |= 0x1F;
119 /* buffer fullness (0x7FF for VBR) continued over 6 first bits + 2 zeros for
120 * number of raw data blocks */
121 adts_header[6] = 0xFC;
122
123 /* Insert ADTS header */
124 gst_buffer_fill (out_buf, out_offset, adts_header, 7);
125 out_offset += 7;
126
127 gst_buffer_map (buf, &buf_map, GST_MAP_READ);
128
129 /* Now copy complete frame */
130 gst_buffer_fill (out_buf, out_offset, buf_map.data, buf_map.size);
131
132 gst_buffer_unmap (buf, &buf_map);
133
134 return out_buf;
135 }
136
137 /* Constructs a dummy codec_data buffer for generating ADTS headers
138 * from raw MPEG-2 AAC input, where we don't expect codec_data in the caps,
139 * and need to get the info from the profile/channels/rate fields */
140 GstBuffer *
gst_base_ts_mux_aac_mpeg2_make_codec_data(GstBaseTsMux * mux,const GstCaps * caps)141 gst_base_ts_mux_aac_mpeg2_make_codec_data (GstBaseTsMux * mux,
142 const GstCaps * caps)
143 {
144 const GstStructure *s;
145 const gchar *profile_str;
146 gint channels, rate;
147 guint8 profile_idx, channel_idx;
148 gint rate_idx;
149 GstMapInfo map;
150 GstBuffer *ret;
151
152 s = gst_caps_get_structure (caps, 0);
153 profile_str = gst_structure_get_string (s, "profile");
154 if (G_UNLIKELY (profile_str == NULL)) {
155 GST_ERROR_OBJECT (mux, "AAC caps do not contain profile");
156 return NULL;
157 }
158
159 if (G_UNLIKELY (!gst_structure_get_int (s, "rate", &rate))) {
160 GST_ERROR_OBJECT (mux, "AAC caps do not contain a sample rate");
161 return NULL;
162 }
163 if (G_UNLIKELY (!gst_structure_get_int (s, "channels", &channels))) {
164 GST_ERROR_OBJECT (mux, "AAC caps do not contain channel count");
165 return NULL;
166 }
167
168 if (g_strcmp0 (profile_str, "main") == 0) {
169 profile_idx = (guint8) 0U;
170 } else if (g_strcmp0 (profile_str, "lc") == 0) {
171 profile_idx = (guint8) 1U;
172 } else if (g_strcmp0 (profile_str, "ssr") == 0) {
173 profile_idx = (guint8) 2U;
174 } else {
175 GST_ERROR_OBJECT (mux, "Invalid profile %s for MPEG-2 AAC caps",
176 profile_str);
177 return NULL;
178 }
179
180 if (channels >= 1 && channels <= 6) /* Mono up to & including 5.1 */
181 channel_idx = (guint8) channels;
182 else if (channels == 8) /* 7.1 */
183 channel_idx = (guint8) 7U;
184 else {
185 GST_ERROR_OBJECT (mux, "Invalid channel count %d for MPEG-2 AAC caps",
186 channels);
187 return NULL;
188 }
189
190 rate_idx = gst_codec_utils_aac_get_index_from_sample_rate (rate);
191 if (rate_idx < 0) {
192 GST_ERROR_OBJECT (mux, "Invalid samplerate %d for MPEG-2 AAC caps", rate);
193 return NULL;
194 }
195
196 ret = gst_buffer_new_and_alloc (3);
197 gst_buffer_map (ret, &map, GST_MAP_READ);
198 map.data[0] = profile_idx;
199 map.data[1] = (guint8) rate_idx;
200 map.data[2] = channel_idx;
201 gst_buffer_unmap (ret, &map);
202
203 return ret;
204 }
205
206 GstBuffer *
gst_base_ts_mux_prepare_aac_mpeg4(GstBuffer * buf,GstBaseTsMuxPad * pad,GstBaseTsMux * mux)207 gst_base_ts_mux_prepare_aac_mpeg4 (GstBuffer * buf, GstBaseTsMuxPad * pad,
208 GstBaseTsMux * mux)
209 {
210 GstMapInfo codec_data_map;
211 guint8 rate_idx = 0, channels = 0, obj_type = 0;
212
213 g_return_val_if_fail (pad->codec_data != NULL, NULL);
214
215 gst_buffer_map (pad->codec_data, &codec_data_map, GST_MAP_READ);
216
217 obj_type = GST_READ_UINT8 (codec_data_map.data) >> 3;
218 rate_idx = (GST_READ_UINT8 (codec_data_map.data) & 0x7) << 1;
219 rate_idx |= (GST_READ_UINT8 (codec_data_map.data + 1) & 0x80) >> 7;
220 channels = (GST_READ_UINT8 (codec_data_map.data + 1) & 0x78) >> 3;
221 gst_buffer_unmap (pad->codec_data, &codec_data_map);
222
223 return gst_base_ts_mux_prepare_aac_adts (buf, mux, FALSE, obj_type, rate_idx,
224 channels);
225 }
226
227 GstBuffer *
gst_base_ts_mux_prepare_aac_mpeg2(GstBuffer * buf,GstBaseTsMuxPad * pad,GstBaseTsMux * mux)228 gst_base_ts_mux_prepare_aac_mpeg2 (GstBuffer * buf, GstBaseTsMuxPad * pad,
229 GstBaseTsMux * mux)
230 {
231 GstMapInfo codec_data_map;
232 guint8 rate_idx = 0, channels = 0, profile_obj_type = 0;
233
234 g_return_val_if_fail (pad->codec_data != NULL, NULL);
235
236 /* Dummy codec data with 3 bytes of profile_idx, rate_idx, channel_idx */
237 gst_buffer_map (pad->codec_data, &codec_data_map, GST_MAP_READ);
238
239 profile_obj_type = GST_READ_UINT8 (codec_data_map.data);
240 rate_idx = GST_READ_UINT8 (codec_data_map.data + 1);
241 channels = GST_READ_UINT8 (codec_data_map.data + 2);
242
243 gst_buffer_unmap (pad->codec_data, &codec_data_map);
244
245 return gst_base_ts_mux_prepare_aac_adts (buf, mux, TRUE, profile_obj_type,
246 rate_idx, channels);
247 }
248