• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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