• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer AC3 parser
2  * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
3  * Copyright (C) 2009 Mark Nauwelaerts <mnauw users sf net>
4  * Copyright (C) 2009 Nokia Corporation. All rights reserved.
5  *   Contact: Stefan Kost <stefan.kost@nokia.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 /**
23  * SECTION:element-ac3parse
24  * @title: ac3parse
25  * @short_description: AC3 parser
26  * @see_also: #GstAmrParse, #GstAACParse
27  *
28  * This is an AC3 parser.
29  *
30  * ## Example launch line
31  * |[
32  * gst-launch-1.0 filesrc location=abc.ac3 ! ac3parse ! a52dec ! audioresample ! audioconvert ! autoaudiosink
33  * ]|
34  *
35  */
36 
37 /* TODO:
38  *  - audio/ac3 to audio/x-private1-ac3 is not implemented (done in the muxer)
39  *  - should accept framed and unframed input (needs decodebin fixes first)
40  */
41 
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45 
46 #include <string.h>
47 
48 #include "gstaudioparserselements.h"
49 #include "gstac3parse.h"
50 #include <gst/base/base.h>
51 #include <gst/pbutils/pbutils.h>
52 
53 GST_DEBUG_CATEGORY_STATIC (ac3_parse_debug);
54 #define GST_CAT_DEFAULT ac3_parse_debug
55 
56 static const struct
57 {
58   const guint bit_rate;         /* nominal bit rate */
59   const guint frame_size[3];    /* frame size for 32kHz, 44kHz, and 48kHz */
60 } frmsizcod_table[38] = {
61   {
62     32, {
63   64, 69, 96}}, {
64     32, {
65   64, 70, 96}}, {
66     40, {
67   80, 87, 120}}, {
68     40, {
69   80, 88, 120}}, {
70     48, {
71   96, 104, 144}}, {
72     48, {
73   96, 105, 144}}, {
74     56, {
75   112, 121, 168}}, {
76     56, {
77   112, 122, 168}}, {
78     64, {
79   128, 139, 192}}, {
80     64, {
81   128, 140, 192}}, {
82     80, {
83   160, 174, 240}}, {
84     80, {
85   160, 175, 240}}, {
86     96, {
87   192, 208, 288}}, {
88     96, {
89   192, 209, 288}}, {
90     112, {
91   224, 243, 336}}, {
92     112, {
93   224, 244, 336}}, {
94     128, {
95   256, 278, 384}}, {
96     128, {
97   256, 279, 384}}, {
98     160, {
99   320, 348, 480}}, {
100     160, {
101   320, 349, 480}}, {
102     192, {
103   384, 417, 576}}, {
104     192, {
105   384, 418, 576}}, {
106     224, {
107   448, 487, 672}}, {
108     224, {
109   448, 488, 672}}, {
110     256, {
111   512, 557, 768}}, {
112     256, {
113   512, 558, 768}}, {
114     320, {
115   640, 696, 960}}, {
116     320, {
117   640, 697, 960}}, {
118     384, {
119   768, 835, 1152}}, {
120     384, {
121   768, 836, 1152}}, {
122     448, {
123   896, 975, 1344}}, {
124     448, {
125   896, 976, 1344}}, {
126     512, {
127   1024, 1114, 1536}}, {
128     512, {
129   1024, 1115, 1536}}, {
130     576, {
131   1152, 1253, 1728}}, {
132     576, {
133   1152, 1254, 1728}}, {
134     640, {
135   1280, 1393, 1920}}, {
136     640, {
137   1280, 1394, 1920}}
138 };
139 
140 static const guint fscod_rates[4] = { 48000, 44100, 32000, 0 };
141 static const guint acmod_chans[8] = { 2, 1, 2, 3, 3, 4, 4, 5 };
142 static const guint numblks[4] = { 1, 2, 3, 6 };
143 
144 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
145     GST_PAD_SRC,
146     GST_PAD_ALWAYS,
147     GST_STATIC_CAPS ("audio/x-ac3, framed = (boolean) true, "
148         " channels = (int) [ 1, 6 ], rate = (int) [ 8000, 48000 ], "
149         " alignment = (string) { iec61937, frame}; "
150         "audio/x-eac3, framed = (boolean) true, "
151         " channels = (int) [ 1, 6 ], rate = (int) [ 8000, 48000 ], "
152         " alignment = (string) { iec61937, frame}; "));
153 
154 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
155     GST_PAD_SINK,
156     GST_PAD_ALWAYS,
157     GST_STATIC_CAPS ("audio/x-ac3; " "audio/x-eac3; " "audio/ac3; "
158         "audio/x-private1-ac3"));
159 
160 static void gst_ac3_parse_finalize (GObject * object);
161 
162 static gboolean gst_ac3_parse_start (GstBaseParse * parse);
163 static gboolean gst_ac3_parse_stop (GstBaseParse * parse);
164 static GstFlowReturn gst_ac3_parse_handle_frame (GstBaseParse * parse,
165     GstBaseParseFrame * frame, gint * skipsize);
166 static GstFlowReturn gst_ac3_parse_pre_push_frame (GstBaseParse * parse,
167     GstBaseParseFrame * frame);
168 static gboolean gst_ac3_parse_src_event (GstBaseParse * parse,
169     GstEvent * event);
170 static GstCaps *gst_ac3_parse_get_sink_caps (GstBaseParse * parse,
171     GstCaps * filter);
172 static gboolean gst_ac3_parse_set_sink_caps (GstBaseParse * parse,
173     GstCaps * caps);
174 
175 #define gst_ac3_parse_parent_class parent_class
176 G_DEFINE_TYPE (GstAc3Parse, gst_ac3_parse, GST_TYPE_BASE_PARSE);
177 GST_ELEMENT_REGISTER_DEFINE (ac3parse, "ac3parse",
178     GST_RANK_PRIMARY + 1, GST_TYPE_AC3_PARSE);
179 
180 static void
gst_ac3_parse_class_init(GstAc3ParseClass * klass)181 gst_ac3_parse_class_init (GstAc3ParseClass * klass)
182 {
183   GObjectClass *object_class = G_OBJECT_CLASS (klass);
184   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
185   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
186 
187   GST_DEBUG_CATEGORY_INIT (ac3_parse_debug, "ac3parse", 0,
188       "AC3 audio stream parser");
189 
190   object_class->finalize = gst_ac3_parse_finalize;
191 
192   gst_element_class_add_static_pad_template (element_class, &sink_template);
193   gst_element_class_add_static_pad_template (element_class, &src_template);
194 
195   gst_element_class_set_static_metadata (element_class,
196       "AC3 audio stream parser", "Codec/Parser/Converter/Audio",
197       "AC3 parser", "Tim-Philipp Müller <tim centricular net>");
198 
199   parse_class->start = GST_DEBUG_FUNCPTR (gst_ac3_parse_start);
200   parse_class->stop = GST_DEBUG_FUNCPTR (gst_ac3_parse_stop);
201   parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_handle_frame);
202   parse_class->pre_push_frame =
203       GST_DEBUG_FUNCPTR (gst_ac3_parse_pre_push_frame);
204   parse_class->src_event = GST_DEBUG_FUNCPTR (gst_ac3_parse_src_event);
205   parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_ac3_parse_get_sink_caps);
206   parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ac3_parse_set_sink_caps);
207 }
208 
209 static void
gst_ac3_parse_reset(GstAc3Parse * ac3parse)210 gst_ac3_parse_reset (GstAc3Parse * ac3parse)
211 {
212   ac3parse->channels = -1;
213   ac3parse->sample_rate = -1;
214   ac3parse->blocks = -1;
215   ac3parse->eac = FALSE;
216   ac3parse->sent_codec_tag = FALSE;
217   g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_NONE);
218 }
219 
220 static void
gst_ac3_parse_init(GstAc3Parse * ac3parse)221 gst_ac3_parse_init (GstAc3Parse * ac3parse)
222 {
223   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (ac3parse), 8);
224   gst_ac3_parse_reset (ac3parse);
225   ac3parse->baseparse_chainfunc =
226       GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE (ac3parse))->chainfunc;
227   GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (ac3parse));
228   GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (ac3parse));
229 }
230 
231 static void
gst_ac3_parse_finalize(GObject * object)232 gst_ac3_parse_finalize (GObject * object)
233 {
234   G_OBJECT_CLASS (parent_class)->finalize (object);
235 }
236 
237 static gboolean
gst_ac3_parse_start(GstBaseParse * parse)238 gst_ac3_parse_start (GstBaseParse * parse)
239 {
240   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
241 
242   GST_DEBUG_OBJECT (parse, "starting");
243 
244   gst_ac3_parse_reset (ac3parse);
245 
246   return TRUE;
247 }
248 
249 static gboolean
gst_ac3_parse_stop(GstBaseParse * parse)250 gst_ac3_parse_stop (GstBaseParse * parse)
251 {
252   GST_DEBUG_OBJECT (parse, "stopping");
253 
254   return TRUE;
255 }
256 
257 static void
gst_ac3_parse_set_alignment(GstAc3Parse * ac3parse,gboolean eac)258 gst_ac3_parse_set_alignment (GstAc3Parse * ac3parse, gboolean eac)
259 {
260   GstCaps *caps;
261   GstStructure *st;
262   const gchar *str = NULL;
263   int i;
264 
265   if (G_LIKELY (!eac))
266     goto done;
267 
268   caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (ac3parse));
269 
270   if (!caps)
271     goto done;
272 
273   for (i = 0; i < gst_caps_get_size (caps); i++) {
274     st = gst_caps_get_structure (caps, i);
275 
276     if (!g_str_equal (gst_structure_get_name (st), "audio/x-eac3"))
277       continue;
278 
279     if ((str = gst_structure_get_string (st, "alignment"))) {
280       if (g_str_equal (str, "iec61937")) {
281         g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_IEC61937);
282         GST_DEBUG_OBJECT (ac3parse, "picked iec61937 alignment");
283       } else if (g_str_equal (str, "frame") == 0) {
284         g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
285         GST_DEBUG_OBJECT (ac3parse, "picked frame alignment");
286       } else {
287         g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
288         GST_WARNING_OBJECT (ac3parse, "unknown alignment: %s", str);
289       }
290       break;
291     }
292   }
293 
294   if (caps)
295     gst_caps_unref (caps);
296 
297 done:
298   /* default */
299   if (ac3parse->align == GST_AC3_PARSE_ALIGN_NONE) {
300     g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
301     GST_DEBUG_OBJECT (ac3parse, "picked syncframe alignment");
302   }
303 }
304 
305 static gboolean
gst_ac3_parse_frame_header_ac3(GstAc3Parse * ac3parse,GstBuffer * buf,gint skip,guint * frame_size,guint * rate,guint * chans,guint * blks,guint * sid)306 gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
307     gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks,
308     guint * sid)
309 {
310   GstBitReader bits;
311   GstMapInfo map;
312   guint8 fscod, frmsizcod, bsid, acmod, lfe_on, rate_scale;
313   gboolean ret = FALSE;
314 
315   GST_LOG_OBJECT (ac3parse, "parsing ac3");
316 
317   gst_buffer_map (buf, &map, GST_MAP_READ);
318   gst_bit_reader_init (&bits, map.data, map.size);
319   gst_bit_reader_skip_unchecked (&bits, skip * 8);
320 
321   gst_bit_reader_skip_unchecked (&bits, 16 + 16);
322   fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);
323   frmsizcod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 6);
324 
325   if (G_UNLIKELY (fscod == 3 || frmsizcod >= G_N_ELEMENTS (frmsizcod_table))) {
326     GST_DEBUG_OBJECT (ac3parse, "bad fscod=%d frmsizcod=%d", fscod, frmsizcod);
327     goto cleanup;
328   }
329 
330   bsid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 5);
331   gst_bit_reader_skip_unchecked (&bits, 3);     /* bsmod */
332   acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);
333 
334   /* spec not quite clear here: decoder should decode if less than 8,
335    * but seemingly only defines 6 and 8 cases */
336   /* Files with 9 and 10 happen, and seem to comply with the <= 8
337      format, so let them through. The spec says nothing about 9 and 10 */
338   if (bsid > 10) {
339     GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid);
340     goto cleanup;
341   } else if (bsid != 8 && bsid != 6) {
342     GST_DEBUG_OBJECT (ac3parse, "undefined bsid=%d", bsid);
343   }
344 
345   if ((acmod & 0x1) && (acmod != 0x1))  /* 3 front channels */
346     gst_bit_reader_skip_unchecked (&bits, 2);
347   if ((acmod & 0x4))            /* if a surround channel exists */
348     gst_bit_reader_skip_unchecked (&bits, 2);
349   if (acmod == 0x2)             /* if in 2/0 mode */
350     gst_bit_reader_skip_unchecked (&bits, 2);
351 
352   lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1);
353 
354   /* 6/8->0, 9->1, 10->2,
355      see http://matroska.org/technical/specs/codecid/index.html */
356   rate_scale = (CLAMP (bsid, 8, 10) - 8);
357 
358   if (frame_size)
359     *frame_size = frmsizcod_table[frmsizcod].frame_size[fscod] * 2;
360   if (rate)
361     *rate = fscod_rates[fscod] >> rate_scale;
362   if (chans)
363     *chans = acmod_chans[acmod] + lfe_on;
364   if (blks)
365     *blks = 6;
366   if (sid)
367     *sid = 0;
368 
369   ret = TRUE;
370 
371 cleanup:
372   gst_buffer_unmap (buf, &map);
373 
374   return ret;
375 }
376 
377 static gboolean
gst_ac3_parse_frame_header_eac3(GstAc3Parse * ac3parse,GstBuffer * buf,gint skip,guint * frame_size,guint * rate,guint * chans,guint * blks,guint * sid)378 gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
379     gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks,
380     guint * sid)
381 {
382   GstBitReader bits;
383   GstMapInfo map;
384   guint16 frmsiz, sample_rate, blocks;
385   guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod;
386   gboolean ret = FALSE;
387 
388   GST_LOG_OBJECT (ac3parse, "parsing e-ac3");
389 
390   gst_buffer_map (buf, &map, GST_MAP_READ);
391   gst_bit_reader_init (&bits, map.data, map.size);
392   gst_bit_reader_skip_unchecked (&bits, skip * 8);
393 
394   gst_bit_reader_skip_unchecked (&bits, 16);
395   strmtyp = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* strmtyp     */
396   if (G_UNLIKELY (strmtyp == 3)) {
397     GST_DEBUG_OBJECT (ac3parse, "bad strmtyp %d", strmtyp);
398     goto cleanup;
399   }
400 
401   strmid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);  /* substreamid */
402   frmsiz = gst_bit_reader_get_bits_uint16_unchecked (&bits, 11);        /* frmsiz      */
403   fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);   /* fscod       */
404   if (fscod == 3) {
405     fscod2 = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);        /* fscod2      */
406     if (G_UNLIKELY (fscod2 == 3)) {
407       GST_DEBUG_OBJECT (ac3parse, "invalid fscod2");
408       goto cleanup;
409     }
410     sample_rate = fscod_rates[fscod2] / 2;
411     blocks = 6;
412   } else {
413     numblkscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);    /* numblkscod  */
414     sample_rate = fscod_rates[fscod];
415     blocks = numblks[numblkscod];
416   }
417 
418   acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);   /* acmod       */
419   lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1);  /* lfeon       */
420 
421   gst_bit_reader_skip_unchecked (&bits, 5);     /* bsid        */
422 
423   if (frame_size)
424     *frame_size = (frmsiz + 1) * 2;
425   if (rate)
426     *rate = sample_rate;
427   if (chans)
428     *chans = acmod_chans[acmod] + lfe_on;
429   if (blks)
430     *blks = blocks;
431   if (sid)
432     *sid = (strmtyp & 0x1) << 3 | strmid;
433 
434   ret = TRUE;
435 
436 cleanup:
437   gst_buffer_unmap (buf, &map);
438 
439   return ret;
440 }
441 
442 static gboolean
gst_ac3_parse_frame_header(GstAc3Parse * parse,GstBuffer * buf,gint skip,guint * framesize,guint * rate,guint * chans,guint * blocks,guint * sid,gboolean * eac)443 gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf, gint skip,
444     guint * framesize, guint * rate, guint * chans, guint * blocks,
445     guint * sid, gboolean * eac)
446 {
447   GstBitReader bits;
448   guint16 sync;
449   guint8 bsid;
450   GstMapInfo map;
451   gboolean ret = FALSE;
452 
453   gst_buffer_map (buf, &map, GST_MAP_READ);
454   gst_bit_reader_init (&bits, map.data, map.size);
455 
456   GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", map.data, MIN (map.size, 16));
457 
458   gst_bit_reader_skip_unchecked (&bits, skip * 8);
459 
460   sync = gst_bit_reader_get_bits_uint16_unchecked (&bits, 16);
461   gst_bit_reader_skip_unchecked (&bits, 16 + 8);
462   bsid = gst_bit_reader_peek_bits_uint8_unchecked (&bits, 5);
463 
464   if (G_UNLIKELY (sync != 0x0b77))
465     goto cleanup;
466 
467   GST_LOG_OBJECT (parse, "bsid = %d", bsid);
468 
469   if (bsid <= 10) {
470     if (eac)
471       *eac = FALSE;
472     ret = gst_ac3_parse_frame_header_ac3 (parse, buf, skip, framesize, rate,
473         chans, blocks, sid);
474     goto cleanup;
475   } else if (bsid <= 16) {
476     if (eac)
477       *eac = TRUE;
478     ret = gst_ac3_parse_frame_header_eac3 (parse, buf, skip, framesize, rate,
479         chans, blocks, sid);
480     goto cleanup;
481   } else {
482     GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
483     ret = FALSE;
484     goto cleanup;
485   }
486 
487   GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
488 
489 cleanup:
490   gst_buffer_unmap (buf, &map);
491 
492   return ret;
493 }
494 
495 static GstFlowReturn
gst_ac3_parse_handle_frame(GstBaseParse * parse,GstBaseParseFrame * frame,gint * skipsize)496 gst_ac3_parse_handle_frame (GstBaseParse * parse,
497     GstBaseParseFrame * frame, gint * skipsize)
498 {
499   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
500   GstBuffer *buf = frame->buffer;
501   GstByteReader reader;
502   gint off;
503   gboolean lost_sync, draining, eac, more = FALSE;
504   guint frmsiz, blocks, sid;
505   guint rate, chans;
506   gboolean update_rate = FALSE;
507   gint framesize = 0;
508   gint have_blocks = 0;
509   GstMapInfo map;
510   gboolean ret = FALSE;
511   GstFlowReturn res = GST_FLOW_OK;
512 
513   gst_buffer_map (buf, &map, GST_MAP_READ);
514 
515   if (G_UNLIKELY (map.size < 8)) {
516     *skipsize = 1;
517     goto cleanup;
518   }
519 
520   gst_byte_reader_init (&reader, map.data, map.size);
521   off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
522       0, map.size);
523 
524   GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
525 
526   /* didn't find anything that looks like a sync word, skip */
527   if (off < 0) {
528     *skipsize = map.size - 3;
529     goto cleanup;
530   }
531 
532   /* possible frame header, but not at offset 0? skip bytes before sync */
533   if (off > 0) {
534     *skipsize = off;
535     goto cleanup;
536   }
537 
538   /* make sure the values in the frame header look sane */
539   if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &frmsiz, &rate, &chans,
540           &blocks, &sid, &eac)) {
541     *skipsize = off + 2;
542     goto cleanup;
543   }
544 
545   GST_LOG_OBJECT (parse, "size: %u, blocks: %u, rate: %u, chans: %u", frmsiz,
546       blocks, rate, chans);
547 
548   framesize = frmsiz;
549 
550   if (G_UNLIKELY (g_atomic_int_get (&ac3parse->align) ==
551           GST_AC3_PARSE_ALIGN_NONE))
552     gst_ac3_parse_set_alignment (ac3parse, eac);
553 
554   GST_LOG_OBJECT (parse, "got frame");
555 
556   lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
557   draining = GST_BASE_PARSE_DRAINING (parse);
558 
559   if (g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937) {
560     /* We need 6 audio blocks from each substream, so we keep going forwards
561      * till we have it */
562 
563     g_assert (blocks > 0);
564     GST_LOG_OBJECT (ac3parse, "Need %d frames before pushing", 6 / blocks);
565 
566     if (sid != 0) {
567       /* We need the first substream to be the one with id 0 */
568       GST_LOG_OBJECT (ac3parse, "Skipping till we find sid 0");
569       *skipsize = off + 2;
570       goto cleanup;
571     }
572 
573     framesize = 0;
574 
575     /* Loop till we have 6 blocks per substream */
576     for (have_blocks = 0; !more && have_blocks < 6; have_blocks += blocks) {
577       /* Loop till we get one frame from each substream */
578       do {
579         framesize += frmsiz;
580 
581         if (!gst_byte_reader_skip (&reader, frmsiz)
582             || map.size < (framesize + 6)) {
583           more = TRUE;
584           break;
585         }
586 
587         if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, &frmsiz,
588                 NULL, NULL, NULL, &sid, &eac)) {
589           *skipsize = off + 2;
590           goto cleanup;
591         }
592       } while (sid);
593     }
594 
595     /* We're now at the next frame, so no need to skip if resyncing */
596     frmsiz = 0;
597   }
598 
599   if (lost_sync && !draining) {
600     guint16 word = 0;
601 
602     GST_DEBUG_OBJECT (ac3parse, "resyncing; checking next frame syncword");
603 
604     if (more || !gst_byte_reader_skip (&reader, frmsiz) ||
605         !gst_byte_reader_get_uint16_be (&reader, &word)) {
606       GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
607       gst_base_parse_set_min_frame_size (parse, framesize + 8);
608       *skipsize = 0;
609       goto cleanup;
610     } else {
611       if (word != 0x0b77) {
612         GST_DEBUG_OBJECT (ac3parse, "0x%x not OK", word);
613         *skipsize = off + 2;
614         goto cleanup;
615       } else {
616         /* ok, got sync now, let's assume constant frame size */
617         gst_base_parse_set_min_frame_size (parse, framesize);
618       }
619     }
620   }
621 
622   /* expect to have found a frame here */
623   g_assert (framesize);
624   ret = TRUE;
625 
626   /* arrange for metadata setup */
627   if (G_UNLIKELY (sid)) {
628     /* dependent frame, no need to (ac)count for or consider further */
629     GST_LOG_OBJECT (parse, "sid: %d", sid);
630     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
631     /* TODO maybe also mark as DELTA_UNIT,
632      * if that does not surprise baseparse elsewhere */
633     /* occupies same time space as previous base frame */
634     if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
635       GST_BUFFER_TIMESTAMP (buf) -= GST_BUFFER_DURATION (buf);
636     /* only shortcut if we already arranged for caps */
637     if (G_LIKELY (ac3parse->sample_rate > 0))
638       goto cleanup;
639   }
640 
641   if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
642           || ac3parse->eac != eac)) {
643     GstCaps *caps = gst_caps_new_simple (eac ? "audio/x-eac3" : "audio/x-ac3",
644         "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
645         "channels", G_TYPE_INT, chans, NULL);
646     gst_caps_set_simple (caps, "alignment", G_TYPE_STRING,
647         g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937 ?
648         "iec61937" : "frame", NULL);
649     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
650     gst_caps_unref (caps);
651 
652     ac3parse->sample_rate = rate;
653     ac3parse->channels = chans;
654     ac3parse->eac = eac;
655 
656     update_rate = TRUE;
657   }
658 
659   if (G_UNLIKELY (ac3parse->blocks != blocks)) {
660     ac3parse->blocks = blocks;
661 
662     update_rate = TRUE;
663   }
664 
665   if (G_UNLIKELY (update_rate))
666     gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2);
667 
668 cleanup:
669   gst_buffer_unmap (buf, &map);
670 
671   if (ret && framesize <= map.size) {
672     res = gst_base_parse_finish_frame (parse, frame, framesize);
673   }
674 
675   return res;
676 }
677 
678 
679 /*
680  * MPEG-PS private1 streams add a 2 bytes "Audio Substream Headers" for each
681  * buffer (not each frame) with the offset of the next frame's start.
682  *
683  * Buffer 1:
684  * -------------------------------------------
685  * |firstAccUnit|AC3SyncWord|xxxxxxxxxxxxxxxxx
686  * -------------------------------------------
687  * Buffer 2:
688  * -------------------------------------------
689  * |firstAccUnit|xxxxxx|AC3SyncWord|xxxxxxxxxx
690  * -------------------------------------------
691  *
692  * These 2 bytes can be dropped safely as they do not include any timing
693  * information, only the offset to the start of the next frame.
694  *
695  * From http://stnsoft.com/DVD/ass-hdr.html:
696  * "FirstAccUnit offset to frame which corresponds to PTS value offset 0 is the
697  * last byte of FirstAccUnit, ie add the offset of byte 2 to get the AU's offset
698  * The value 0000 indicates there is no first access unit"
699  * */
700 
701 static GstFlowReturn
gst_ac3_parse_chain_priv(GstPad * pad,GstObject * parent,GstBuffer * buf)702 gst_ac3_parse_chain_priv (GstPad * pad, GstObject * parent, GstBuffer * buf)
703 {
704   GstAc3Parse *ac3parse = GST_AC3_PARSE (parent);
705   GstFlowReturn ret;
706   gsize size;
707   guint8 data[2];
708   gint offset;
709   gint len;
710   GstBuffer *subbuf;
711   gint first_access;
712 
713   size = gst_buffer_get_size (buf);
714   if (size < 2)
715     goto not_enough_data;
716 
717   gst_buffer_extract (buf, 0, data, 2);
718   first_access = (data[0] << 8) | data[1];
719 
720   /* Skip the first_access header */
721   offset = 2;
722 
723   if (first_access > 1) {
724     /* Length of data before first_access */
725     len = first_access - 1;
726 
727     if (len <= 0 || offset + len > size)
728       goto bad_first_access_parameter;
729 
730     subbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, len);
731     GST_BUFFER_DTS (subbuf) = GST_CLOCK_TIME_NONE;
732     GST_BUFFER_PTS (subbuf) = GST_CLOCK_TIME_NONE;
733     ret = ac3parse->baseparse_chainfunc (pad, parent, subbuf);
734     if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
735       gst_buffer_unref (buf);
736       goto done;
737     }
738 
739     offset += len;
740     len = size - offset;
741 
742     if (len > 0) {
743       subbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, len);
744       GST_BUFFER_PTS (subbuf) = GST_BUFFER_PTS (buf);
745       GST_BUFFER_DTS (subbuf) = GST_BUFFER_DTS (buf);
746 
747       ret = ac3parse->baseparse_chainfunc (pad, parent, subbuf);
748     }
749     gst_buffer_unref (buf);
750   } else {
751     /* first_access = 0 or 1, so if there's a timestamp it applies to the first byte */
752     subbuf =
753         gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset,
754         size - offset);
755     GST_BUFFER_PTS (subbuf) = GST_BUFFER_PTS (buf);
756     GST_BUFFER_DTS (subbuf) = GST_BUFFER_DTS (buf);
757     gst_buffer_unref (buf);
758     ret = ac3parse->baseparse_chainfunc (pad, parent, subbuf);
759   }
760 
761 done:
762   return ret;
763 
764 /* ERRORS */
765 not_enough_data:
766   {
767     GST_ELEMENT_ERROR (GST_ELEMENT (ac3parse), STREAM, FORMAT, (NULL),
768         ("Insufficient data in buffer. Can't determine first_acess"));
769     gst_buffer_unref (buf);
770     return GST_FLOW_ERROR;
771   }
772 bad_first_access_parameter:
773   {
774     GST_ELEMENT_ERROR (GST_ELEMENT (ac3parse), STREAM, FORMAT, (NULL),
775         ("Bad first_access parameter (%d) in buffer", first_access));
776     gst_buffer_unref (buf);
777     return GST_FLOW_ERROR;
778   }
779 }
780 
781 static GstFlowReturn
gst_ac3_parse_pre_push_frame(GstBaseParse * parse,GstBaseParseFrame * frame)782 gst_ac3_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
783 {
784   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
785 
786   if (!ac3parse->sent_codec_tag) {
787     GstTagList *taglist;
788     GstCaps *caps;
789 
790     /* codec tag */
791     caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
792     if (G_UNLIKELY (caps == NULL)) {
793       if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
794         GST_INFO_OBJECT (parse, "Src pad is flushing");
795         return GST_FLOW_FLUSHING;
796       } else {
797         GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
798         return GST_FLOW_NOT_NEGOTIATED;
799       }
800     }
801 
802     taglist = gst_tag_list_new_empty ();
803     gst_pb_utils_add_codec_description_to_tag_list (taglist,
804         GST_TAG_AUDIO_CODEC, caps);
805     gst_caps_unref (caps);
806 
807     gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
808     gst_tag_list_unref (taglist);
809 
810     /* also signals the end of first-frame processing */
811     ac3parse->sent_codec_tag = TRUE;
812   }
813 
814   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
815 
816   return GST_FLOW_OK;
817 }
818 
819 static gboolean
gst_ac3_parse_src_event(GstBaseParse * parse,GstEvent * event)820 gst_ac3_parse_src_event (GstBaseParse * parse, GstEvent * event)
821 {
822   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
823 
824   if (G_UNLIKELY (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) &&
825       gst_event_has_name (event, "ac3parse-set-alignment")) {
826     const GstStructure *st = gst_event_get_structure (event);
827     const gchar *align = gst_structure_get_string (st, "alignment");
828 
829     if (g_str_equal (align, "iec61937")) {
830       GST_DEBUG_OBJECT (ac3parse, "Switching to iec61937 alignment");
831       g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_IEC61937);
832     } else if (g_str_equal (align, "frame")) {
833       GST_DEBUG_OBJECT (ac3parse, "Switching to frame alignment");
834       g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
835     } else {
836       g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
837       GST_WARNING_OBJECT (ac3parse, "Got unknown alignment request (%s) "
838           "reverting to frame alignment.",
839           gst_structure_get_string (st, "alignment"));
840     }
841 
842     gst_event_unref (event);
843     return TRUE;
844   }
845 
846   return GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
847 }
848 
849 static void
remove_fields(GstCaps * caps)850 remove_fields (GstCaps * caps)
851 {
852   guint i, n;
853 
854   n = gst_caps_get_size (caps);
855   for (i = 0; i < n; i++) {
856     GstStructure *s = gst_caps_get_structure (caps, i);
857 
858     gst_structure_remove_field (s, "framed");
859     gst_structure_remove_field (s, "alignment");
860   }
861 }
862 
863 static GstCaps *
extend_caps(GstCaps * caps,gboolean add_private)864 extend_caps (GstCaps * caps, gboolean add_private)
865 {
866   guint i, n;
867   GstCaps *ncaps = gst_caps_new_empty ();
868 
869   n = gst_caps_get_size (caps);
870   for (i = 0; i < n; i++) {
871     GstStructure *s = gst_caps_get_structure (caps, i);
872 
873     if (add_private && !gst_structure_has_name (s, "audio/x-private1-ac3")) {
874       GstStructure *ns = gst_structure_copy (s);
875       gst_structure_set_name (ns, "audio/x-private1-ac3");
876       gst_caps_append_structure (ncaps, ns);
877     } else if (!add_private &&
878         gst_structure_has_name (s, "audio/x-private1-ac3")) {
879       GstStructure *ns = gst_structure_copy (s);
880       gst_structure_set_name (ns, "audio/x-ac3");
881       gst_caps_append_structure (ncaps, ns);
882       ns = gst_structure_copy (s);
883       gst_structure_set_name (ns, "audio/x-eac3");
884       gst_caps_append_structure (ncaps, ns);
885     } else if (!add_private) {
886       gst_caps_append_structure (ncaps, gst_structure_copy (s));
887     }
888   }
889 
890   if (add_private) {
891     gst_caps_append (caps, ncaps);
892   } else {
893     gst_caps_unref (caps);
894     caps = ncaps;
895   }
896 
897   return caps;
898 }
899 
900 static GstCaps *
gst_ac3_parse_get_sink_caps(GstBaseParse * parse,GstCaps * filter)901 gst_ac3_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
902 {
903   GstCaps *peercaps, *templ;
904   GstCaps *res;
905 
906   templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
907   if (filter) {
908     GstCaps *fcopy = gst_caps_copy (filter);
909     /* Remove the fields we convert */
910     remove_fields (fcopy);
911     /* we do not ask downstream to handle x-private1-ac3 */
912     fcopy = extend_caps (fcopy, FALSE);
913     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
914     gst_caps_unref (fcopy);
915   } else
916     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
917 
918   if (peercaps) {
919     /* Remove the framed and alignment field. We can convert
920      * between different alignments. */
921     peercaps = gst_caps_make_writable (peercaps);
922     remove_fields (peercaps);
923     /* also allow for x-private1-ac3 input */
924     peercaps = extend_caps (peercaps, TRUE);
925 
926     res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
927     gst_caps_unref (peercaps);
928     gst_caps_unref (templ);
929   } else {
930     res = templ;
931   }
932 
933   if (filter) {
934     GstCaps *intersection;
935 
936     intersection =
937         gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
938     gst_caps_unref (res);
939     res = intersection;
940   }
941 
942   return res;
943 }
944 
945 static gboolean
gst_ac3_parse_set_sink_caps(GstBaseParse * parse,GstCaps * caps)946 gst_ac3_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
947 {
948   GstStructure *s;
949   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
950 
951   s = gst_caps_get_structure (caps, 0);
952   if (gst_structure_has_name (s, "audio/x-private1-ac3")) {
953     gst_pad_set_chain_function (parse->sinkpad, gst_ac3_parse_chain_priv);
954   } else {
955     gst_pad_set_chain_function (parse->sinkpad, ac3parse->baseparse_chainfunc);
956   }
957   return TRUE;
958 }
959