1 /* GStreamer AAC parser plugin
2 * Copyright (C) 2008 Nokia Corporation. All rights reserved.
4 * Contact: Stefan Kost <stefan.kost@nokia.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
23 * SECTION:element-aacparse
24 * @short_description: AAC parser
25 * @see_also: #GstAmrParse
27 * This is an AAC parser which handles both ADIF and ADTS stream formats.
29 * As ADIF format is not framed, it is not seekable and stream duration cannot
30 * be determined either. However, ADTS format AAC clips can be seeked, and parser
31 * can also estimate playback position and clip duration.
34 * <title>Example launch line</title>
36 * gst-launch-1.0 filesrc location=abc.aac ! aacparse ! faad ! audioresample ! audioconvert ! alsasink
47 #include <gst/base/gstbitreader.h>
48 #include <gst/pbutils/pbutils.h>
49 #include "gstaacparse.h"
52 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
55 GST_STATIC_CAPS ("audio/mpeg, "
56 "framed = (boolean) true, " "mpegversion = (int) { 2, 4 }, "
57 "stream-format = (string) { raw, adts, adif, loas };"));
59 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
62 GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) { 2, 4 };"));
64 GST_DEBUG_CATEGORY_STATIC (aacparse_debug);
65 #define GST_CAT_DEFAULT aacparse_debug
68 #define ADIF_MAX_SIZE 40 /* Should be enough */
69 #define ADTS_MAX_SIZE 10 /* Should be enough */
70 #define LOAS_MAX_SIZE 3 /* Should be enough */
71 #define RAW_MAX_SIZE 1 /* Correct framing is required */
73 #define ADTS_HEADERS_LENGTH 7UL /* Total byte-length of fixed and variable
74 headers prepended during raw to ADTS
77 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION /* to get more accurate duration */
78 #define AAC_MAX_ESTIMATE_DURATION_BUF (1024 * 1024) /* use first 1 Mbyte */
79 #define AAC_SAMPLE_PER_FRAME 1024
81 #define AAC_MAX_PULL_RANGE_BUF (1 * 1024 * 1024) /* 1 MByte */
82 #define AAC_LARGE_FILE_SIZE (2 * 1024 * 1024) /* 2 MByte */
83 #define gst_aac_parse_parent_class parent_class
86 #define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
88 static const gint loas_sample_rate_table[16] = {
89 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
90 16000, 12000, 11025, 8000, 7350, 0, 0, 0
93 static const gint loas_channels_table[16] = {
94 0, 1, 2, 3, 4, 5, 6, 8,
95 0, 0, 0, 7, 8, 0, 8, 0
98 static gboolean gst_aac_parse_start (GstBaseParse * parse);
99 static gboolean gst_aac_parse_stop (GstBaseParse * parse);
101 static gboolean gst_aac_parse_sink_setcaps (GstBaseParse * parse,
103 static GstCaps *gst_aac_parse_sink_getcaps (GstBaseParse * parse,
106 static GstFlowReturn gst_aac_parse_handle_frame (GstBaseParse * parse,
107 GstBaseParseFrame * frame, gint * skipsize);
108 static GstFlowReturn gst_aac_parse_pre_push_frame (GstBaseParse * parse,
109 GstBaseParseFrame * frame);
110 static gboolean gst_aac_parse_src_event (GstBaseParse * parse,
113 static gboolean gst_aac_parse_read_audio_specific_config (GstAacParse *
114 aacparse, GstBitReader * br, gint * object_type, gint * sample_rate,
115 gint * channels, gint * frame_samples);
117 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
118 static guint gst_aac_parse_adts_get_fast_frame_len (const guint8 * data);
119 /* make full aac(adts) index table when seek */
120 static gboolean gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse,
122 int get_aac_parse_get_adts_frame_length (const unsigned char *data,
124 static gboolean gst_aac_parse_estimate_duration (GstBaseParse * parse);
127 #define gst_aac_parse_parent_class parent_class
128 G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE);
130 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
132 gst_aac_parse_get_sample_rate_from_index (guint sr_idx)
134 static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
135 32000, 24000, 22050, 16000, 12000, 11025, 8000
138 if (sr_idx < G_N_ELEMENTS (aac_sample_rates))
139 return aac_sample_rates[sr_idx];
140 GST_WARNING ("Invalid sample rate index %u", sr_idx);
145 * gst_aac_parse_class_init:
146 * @klass: #GstAacParseClass.
150 gst_aac_parse_class_init (GstAacParseClass * klass)
152 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
153 GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
155 GST_DEBUG_CATEGORY_INIT (aacparse_debug, "aacparse", 0,
156 "AAC audio stream parser");
158 gst_element_class_add_static_pad_template (element_class, &sink_template);
159 gst_element_class_add_static_pad_template (element_class, &src_template);
161 gst_element_class_set_static_metadata (element_class,
162 "AAC audio stream parser", "Codec/Parser/Audio",
163 "Advanced Audio Coding parser", "Stefan Kost <stefan.kost@nokia.com>");
165 parse_class->start = GST_DEBUG_FUNCPTR (gst_aac_parse_start);
166 parse_class->stop = GST_DEBUG_FUNCPTR (gst_aac_parse_stop);
167 parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_setcaps);
168 parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_getcaps);
169 parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_handle_frame);
170 parse_class->pre_push_frame =
171 GST_DEBUG_FUNCPTR (gst_aac_parse_pre_push_frame);
172 parse_class->src_event = GST_DEBUG_FUNCPTR (gst_aac_parse_src_event);
177 * gst_aac_parse_init:
178 * @aacparse: #GstAacParse.
179 * @klass: #GstAacParseClass.
183 gst_aac_parse_init (GstAacParse * aacparse)
185 GST_DEBUG ("initialized");
186 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (aacparse));
187 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (aacparse));
189 aacparse->last_parsed_sample_rate = 0;
190 aacparse->last_parsed_channels = 0;
191 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
192 /* to get more correct duration */
193 aacparse->first_frame = TRUE;
199 * gst_aac_parse_set_src_caps:
200 * @aacparse: #GstAacParse.
201 * @sink_caps: (proposed) caps of sink pad
203 * Set source pad caps according to current knowledge about the
206 * Returns: TRUE if caps were successfully set.
209 gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
212 GstCaps *src_caps = NULL, *allowed;
213 gboolean res = FALSE;
214 const gchar *stream_format;
215 guint8 codec_data[2];
216 guint16 codec_data_data;
217 gint sample_rate_idx;
219 GST_DEBUG_OBJECT (aacparse, "sink caps: %" GST_PTR_FORMAT, sink_caps);
221 src_caps = gst_caps_copy (sink_caps);
223 src_caps = gst_caps_new_empty_simple ("audio/mpeg");
225 gst_caps_set_simple (src_caps, "framed", G_TYPE_BOOLEAN, TRUE,
226 "mpegversion", G_TYPE_INT, aacparse->mpegversion, NULL);
228 aacparse->output_header_type = aacparse->header_type;
229 switch (aacparse->header_type) {
230 case DSPAAC_HEADER_NONE:
231 stream_format = "raw";
233 case DSPAAC_HEADER_ADTS:
234 stream_format = "adts";
236 case DSPAAC_HEADER_ADIF:
237 stream_format = "adif";
239 case DSPAAC_HEADER_LOAS:
240 stream_format = "loas";
243 stream_format = NULL;
246 /* Generate codec data to be able to set profile/level on the caps */
248 gst_codec_utils_aac_get_index_from_sample_rate (aacparse->sample_rate);
249 if (sample_rate_idx < 0)
250 goto not_a_known_rate;
252 (aacparse->object_type << 11) |
253 (sample_rate_idx << 7) | (aacparse->channels << 3);
254 GST_WRITE_UINT16_BE (codec_data, codec_data_data);
255 gst_codec_utils_aac_caps_set_level_and_profile (src_caps, codec_data, 2);
257 s = gst_caps_get_structure (src_caps, 0);
258 if (aacparse->sample_rate > 0)
259 gst_structure_set (s, "rate", G_TYPE_INT, aacparse->sample_rate, NULL);
260 if (aacparse->channels > 0)
261 gst_structure_set (s, "channels", G_TYPE_INT, aacparse->channels, NULL);
263 gst_structure_set (s, "stream-format", G_TYPE_STRING, stream_format, NULL);
265 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
266 if (!gst_structure_get_value (s, "codec_data")) {
267 GstBuffer *codec_data_buffer;
268 GST_WARNING("Insert codec_data to src_caps");
269 /* The codec_data data is according to AudioSpecificConfig,
270 ISO/IEC 14496-3, 1.6.2.1 */
271 codec_data_buffer = gst_buffer_new_and_alloc (2);
272 gst_buffer_fill (codec_data_buffer, 0, codec_data, 2);
273 gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER, codec_data_buffer, NULL);
274 gst_buffer_unref (codec_data_buffer);
278 allowed = gst_pad_get_allowed_caps (GST_BASE_PARSE (aacparse)->srcpad);
279 if (allowed && !gst_caps_can_intersect (src_caps, allowed)) {
280 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
281 "Caps can not intersect");
282 if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
283 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
284 "Input is ADTS, trying raw");
285 gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "raw",
287 if (gst_caps_can_intersect (src_caps, allowed)) {
288 GstBuffer *codec_data_buffer;
290 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
291 "Caps can intersect, we will drop the ADTS layer");
292 aacparse->output_header_type = DSPAAC_HEADER_NONE;
294 /* The codec_data data is according to AudioSpecificConfig,
295 ISO/IEC 14496-3, 1.6.2.1 */
296 codec_data_buffer = gst_buffer_new_and_alloc (2);
297 gst_buffer_fill (codec_data_buffer, 0, codec_data, 2);
298 gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER,
299 codec_data_buffer, NULL);
300 gst_buffer_unref (codec_data_buffer);
302 } else if (aacparse->header_type == DSPAAC_HEADER_NONE) {
303 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
304 "Input is raw, trying ADTS");
305 gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adts",
307 if (gst_caps_can_intersect (src_caps, allowed)) {
308 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
309 "Caps can intersect, we will prepend ADTS headers");
310 aacparse->output_header_type = DSPAAC_HEADER_ADTS;
315 gst_caps_unref (allowed);
317 aacparse->last_parsed_channels = 0;
318 aacparse->last_parsed_sample_rate = 0;
320 GST_DEBUG_OBJECT (aacparse, "setting src caps: %" GST_PTR_FORMAT, src_caps);
322 res = gst_pad_set_caps (GST_BASE_PARSE (aacparse)->srcpad, src_caps);
323 gst_caps_unref (src_caps);
327 GST_ERROR_OBJECT (aacparse, "Not a known sample rate: %d",
328 aacparse->sample_rate);
329 gst_caps_unref (src_caps);
335 * gst_aac_parse_sink_setcaps:
339 * Implementation of "set_sink_caps" vmethod in #GstBaseParse class.
341 * Returns: TRUE on success.
344 gst_aac_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
346 GstAacParse *aacparse;
347 GstStructure *structure;
351 aacparse = GST_AAC_PARSE (parse);
352 structure = gst_caps_get_structure (caps, 0);
353 caps_str = gst_caps_to_string (caps);
355 GST_DEBUG_OBJECT (aacparse, "setcaps: %s", caps_str);
358 /* This is needed at least in case of RTP
359 * Parses the codec_data information to get ObjectType,
360 * number of channels and samplerate */
361 value = gst_structure_get_value (structure, "codec_data");
363 GstBuffer *buf = gst_value_get_buffer (value);
365 if (buf && gst_buffer_get_size (buf) >= 2) {
369 if (!gst_buffer_map (buf, &map, GST_MAP_READ))
371 gst_bit_reader_init (&br, map.data, map.size);
372 gst_aac_parse_read_audio_specific_config (aacparse, &br,
373 &aacparse->object_type, &aacparse->sample_rate, &aacparse->channels,
374 &aacparse->frame_samples);
376 aacparse->header_type = DSPAAC_HEADER_NONE;
377 aacparse->mpegversion = 4;
378 gst_buffer_unmap (buf, &map);
380 GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d, "
381 "samples=%d", aacparse->object_type, aacparse->sample_rate,
382 aacparse->channels, aacparse->frame_samples);
384 /* arrange for metadata and get out of the way */
385 gst_aac_parse_set_src_caps (aacparse, caps);
386 if (aacparse->header_type == aacparse->output_header_type)
387 gst_base_parse_set_passthrough (parse, TRUE);
389 /* input is already correctly framed */
390 gst_base_parse_set_min_frame_size (parse, RAW_MAX_SIZE);
395 /* caps info overrides */
396 gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
397 gst_structure_get_int (structure, "channels", &aacparse->channels);
399 const gchar *stream_format =
400 gst_structure_get_string (structure, "stream-format");
402 if (g_strcmp0 (stream_format, "raw") == 0) {
403 GST_ERROR_OBJECT (parse, "Need codec_data for raw AAC");
406 aacparse->sample_rate = 0;
407 aacparse->channels = 0;
408 aacparse->header_type = DSPAAC_HEADER_NOT_PARSED;
409 gst_base_parse_set_passthrough (parse, FALSE);
417 * gst_aac_parse_adts_get_frame_len:
418 * @data: block of data containing an ADTS header.
420 * This function calculates ADTS frame length from the given header.
422 * Returns: size of the ADTS frame.
425 gst_aac_parse_adts_get_frame_len (const guint8 * data)
427 return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
432 * gst_aac_parse_check_adts_frame:
433 * @aacparse: #GstAacParse.
434 * @data: Data to be checked.
435 * @avail: Amount of data passed.
436 * @framesize: If valid ADTS frame was found, this will be set to tell the
437 * found frame size in bytes.
438 * @needed_data: If frame was not found, this may be set to tell how much
439 * more data is needed in the next round to detect the frame
440 * reliably. This may happen when a frame header candidate
441 * is found but it cannot be guaranteed to be the header without
442 * peeking the following data.
444 * Check if the given data contains contains ADTS frame. The algorithm
445 * will examine ADTS frame header and calculate the frame size. Also, another
446 * consecutive ADTS frame header need to be present after the found frame.
447 * Otherwise the data is not considered as a valid ADTS frame. However, this
448 * "extra check" is omitted when EOS has been received. In this case it is
449 * enough when data[0] contains a valid ADTS header.
451 * This function may set the #needed_data to indicate that a possible frame
452 * candidate has been found, but more data (#needed_data bytes) is needed to
453 * be absolutely sure. When this situation occurs, FALSE will be returned.
455 * When a valid frame is detected, this function will use
456 * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
457 * to set the needed bytes for next frame.This way next data chunk is already
460 * Returns: TRUE if the given data contains a valid ADTS header.
463 gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
464 const guint8 * data, const guint avail, gboolean drain,
465 guint * framesize, guint * needed_data)
471 /* Absolute minimum to perform the ADTS syncword,
472 layer and sampling frequency tests */
473 if (G_UNLIKELY (avail < 3)) {
478 /* Syncword and layer tests */
479 if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
481 /* Sampling frequency test */
482 if (G_UNLIKELY ((data[2] & 0x3C) >> 2 == 15))
485 /* This looks like an ADTS frame header but
486 we need at least 6 bytes to proceed */
487 if (G_UNLIKELY (avail < 6)) {
492 *framesize = gst_aac_parse_adts_get_frame_len (data);
494 /* If frame has CRC, it needs 2 bytes
495 for it at the end of the header */
496 crc_size = (data[1] & 0x01) ? 0 : 2;
499 if (*framesize < 7 + crc_size) {
500 *needed_data = 7 + crc_size;
504 /* In EOS mode this is enough. No need to examine the data further.
505 We also relax the check when we have sync, on the assumption that
506 if we're not looking at random data, we have a much higher chance
507 to get the correct sync, and this avoids losing two frames when
508 a single bit corruption happens. */
509 if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
513 if (*framesize + ADTS_MAX_SIZE > avail) {
514 /* We have found a possible frame header candidate, but can't be
515 sure since we don't have enough data to check the next frame */
516 GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
517 *framesize + ADTS_MAX_SIZE, avail);
518 *needed_data = *framesize + ADTS_MAX_SIZE;
519 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
520 *framesize + ADTS_MAX_SIZE);
524 if ((data[*framesize] == 0xff) && ((data[*framesize + 1] & 0xf6) == 0xf0)) {
525 guint nextlen = gst_aac_parse_adts_get_frame_len (data + (*framesize));
527 GST_LOG ("ADTS frame found, len: %d bytes", *framesize);
528 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
529 nextlen + ADTS_MAX_SIZE);
537 gst_aac_parse_latm_get_value (GstAacParse * aacparse, GstBitReader * br,
540 guint8 bytes, i, byte;
543 if (!gst_bit_reader_get_bits_uint8 (br, &bytes, 2))
545 for (i = 0; i <= bytes; ++i) {
547 if (!gst_bit_reader_get_bits_uint8 (br, &byte, 8))
555 gst_aac_parse_get_audio_object_type (GstAacParse * aacparse, GstBitReader * br,
556 guint8 * audio_object_type)
558 if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 5))
560 if (*audio_object_type == 31) {
561 if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 6))
563 *audio_object_type += 32;
565 GST_LOG_OBJECT (aacparse, "audio object type %u", *audio_object_type);
570 gst_aac_parse_get_audio_sample_rate (GstAacParse * aacparse, GstBitReader * br,
573 guint8 sampling_frequency_index;
574 if (!gst_bit_reader_get_bits_uint8 (br, &sampling_frequency_index, 4))
576 GST_LOG_OBJECT (aacparse, "sampling_frequency_index: %u",
577 sampling_frequency_index);
578 if (sampling_frequency_index == 0xf) {
579 guint32 sampling_rate;
580 if (!gst_bit_reader_get_bits_uint32 (br, &sampling_rate, 24))
582 *sample_rate = sampling_rate;
584 *sample_rate = loas_sample_rate_table[sampling_frequency_index];
588 aacparse->last_parsed_sample_rate = *sample_rate;
592 /* See table 1.13 in ISO/IEC 14496-3 */
594 gst_aac_parse_read_audio_specific_config (GstAacParse * aacparse,
595 GstBitReader * br, gint * object_type, gint * sample_rate, gint * channels,
596 gint * frame_samples)
598 guint8 audio_object_type;
599 guint8 G_GNUC_UNUSED extension_audio_object_type;
600 guint8 channel_configuration, extension_channel_configuration;
601 gboolean G_GNUC_UNUSED sbr = FALSE, ps = FALSE;
603 if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type))
606 *object_type = audio_object_type;
608 if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
611 if (!gst_bit_reader_get_bits_uint8 (br, &channel_configuration, 4))
613 *channels = loas_channels_table[channel_configuration];
614 GST_LOG_OBJECT (aacparse, "channel_configuration: %d", channel_configuration);
618 if (audio_object_type == 5 || audio_object_type == 29) {
619 extension_audio_object_type = 5;
621 if (audio_object_type == 29) {
623 /* Parametric stereo. If we have a one-channel configuration, we can
624 * override it to stereo */
629 GST_LOG_OBJECT (aacparse,
630 "Audio object type 5 or 29, so rereading sampling rate (was %d)...",
632 if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
635 if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type))
638 if (audio_object_type == 22) {
639 /* extension channel configuration */
640 if (!gst_bit_reader_get_bits_uint8 (br, &extension_channel_configuration,
643 GST_LOG_OBJECT (aacparse, "extension channel_configuration: %d",
644 extension_channel_configuration);
645 *channels = loas_channels_table[extension_channel_configuration];
650 extension_audio_object_type = 0;
653 GST_INFO_OBJECT (aacparse, "Parsed AudioSpecificConfig: %d Hz, %d channels",
654 *sample_rate, *channels);
656 if (frame_samples && audio_object_type == 23) {
658 /* Read the Decoder Configuration (GASpecificConfig) if present */
659 /* We only care about the first bit to know what the number of samples
661 if (!gst_bit_reader_get_bits_uint8 (br, &frame_flag, 1))
663 *frame_samples = frame_flag ? 960 : 1024;
666 /* There's LOTS of stuff next, but we ignore it for now as we have
667 what we want (sample rate and number of channels */
668 GST_DEBUG_OBJECT (aacparse,
669 "Need more code to parse humongous LOAS data, currently ignored");
670 aacparse->last_parsed_channels = *channels;
676 gst_aac_parse_read_loas_config (GstAacParse * aacparse, const guint8 * data,
677 guint avail, gint * sample_rate, gint * channels, gint * version)
682 /* No version in the bitstream, but the spec has LOAS in the MPEG-4 section */
686 gst_bit_reader_init (&br, data, avail);
688 /* skip sync word (11 bits) and size (13 bits) */
689 if (!gst_bit_reader_skip (&br, 11 + 13))
692 /* First bit is "use last config" */
693 if (!gst_bit_reader_get_bits_uint8 (&br, &u8, 1))
696 GST_LOG_OBJECT (aacparse, "Frame uses previous config");
697 if (!aacparse->last_parsed_sample_rate || !aacparse->last_parsed_channels) {
698 GST_DEBUG_OBJECT (aacparse,
699 "No previous config to use. We'll look for more data.");
702 *sample_rate = aacparse->last_parsed_sample_rate;
703 *channels = aacparse->last_parsed_channels;
707 GST_DEBUG_OBJECT (aacparse, "Frame contains new config");
709 /* audioMuxVersion */
710 if (!gst_bit_reader_get_bits_uint8 (&br, &v, 1))
713 /* audioMuxVersionA */
714 if (!gst_bit_reader_get_bits_uint8 (&br, &vA, 1))
719 GST_LOG_OBJECT (aacparse, "v %d, vA %d", v, vA);
721 guint8 same_time, subframes, num_program, prog;
724 /* taraBufferFullness */
725 if (!gst_aac_parse_latm_get_value (aacparse, &br, &value))
728 if (!gst_bit_reader_get_bits_uint8 (&br, &same_time, 1))
730 if (!gst_bit_reader_get_bits_uint8 (&br, &subframes, 6))
732 if (!gst_bit_reader_get_bits_uint8 (&br, &num_program, 4))
734 GST_LOG_OBJECT (aacparse, "same_time %d, subframes %d, num_program %d",
735 same_time, subframes, num_program);
737 for (prog = 0; prog <= num_program; ++prog) {
738 guint8 num_layer, layer;
739 if (!gst_bit_reader_get_bits_uint8 (&br, &num_layer, 3))
741 GST_LOG_OBJECT (aacparse, "Program %d: %d layers", prog, num_layer);
743 for (layer = 0; layer <= num_layer; ++layer) {
744 guint8 use_same_config;
745 if (prog == 0 && layer == 0) {
748 if (!gst_bit_reader_get_bits_uint8 (&br, &use_same_config, 1))
751 if (!use_same_config) {
753 if (!gst_aac_parse_read_audio_specific_config (aacparse, &br, NULL,
754 sample_rate, channels, NULL))
758 if (!gst_aac_parse_latm_get_value (aacparse, &br, &asc_len))
760 if (!gst_aac_parse_read_audio_specific_config (aacparse, &br, NULL,
761 sample_rate, channels, NULL))
763 if (!gst_bit_reader_skip (&br, asc_len))
769 GST_LOG_OBJECT (aacparse, "More data ignored");
771 GST_WARNING_OBJECT (aacparse, "Spec says \"TBD\"...");
778 * gst_aac_parse_loas_get_frame_len:
779 * @data: block of data containing a LOAS header.
781 * This function calculates LOAS frame length from the given header.
783 * Returns: size of the LOAS frame.
786 gst_aac_parse_loas_get_frame_len (const guint8 * data)
788 return (((data[1] & 0x1f) << 8) | data[2]) + 3;
793 * gst_aac_parse_check_loas_frame:
794 * @aacparse: #GstAacParse.
795 * @data: Data to be checked.
796 * @avail: Amount of data passed.
797 * @framesize: If valid LOAS frame was found, this will be set to tell the
798 * found frame size in bytes.
799 * @needed_data: If frame was not found, this may be set to tell how much
800 * more data is needed in the next round to detect the frame
801 * reliably. This may happen when a frame header candidate
802 * is found but it cannot be guaranteed to be the header without
803 * peeking the following data.
805 * Check if the given data contains contains LOAS frame. The algorithm
806 * will examine LOAS frame header and calculate the frame size. Also, another
807 * consecutive LOAS frame header need to be present after the found frame.
808 * Otherwise the data is not considered as a valid LOAS frame. However, this
809 * "extra check" is omitted when EOS has been received. In this case it is
810 * enough when data[0] contains a valid LOAS header.
812 * This function may set the #needed_data to indicate that a possible frame
813 * candidate has been found, but more data (#needed_data bytes) is needed to
814 * be absolutely sure. When this situation occurs, FALSE will be returned.
816 * When a valid frame is detected, this function will use
817 * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
818 * to set the needed bytes for next frame.This way next data chunk is already
821 * LOAS can have three different formats, if I read the spec correctly. Only
822 * one of them is supported here, as the two samples I have use this one.
824 * Returns: TRUE if the given data contains a valid LOAS header.
827 gst_aac_parse_check_loas_frame (GstAacParse * aacparse,
828 const guint8 * data, const guint avail, gboolean drain,
829 guint * framesize, guint * needed_data)
834 if (G_UNLIKELY (avail < 3)) {
839 if ((data[0] == 0x56) && ((data[1] & 0xe0) == 0xe0)) {
840 *framesize = gst_aac_parse_loas_get_frame_len (data);
841 GST_DEBUG_OBJECT (aacparse, "Found possible %u byte LOAS frame",
844 /* In EOS mode this is enough. No need to examine the data further.
845 We also relax the check when we have sync, on the assumption that
846 if we're not looking at random data, we have a much higher chance
847 to get the correct sync, and this avoids losing two frames when
848 a single bit corruption happens. */
849 if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
853 if (*framesize + LOAS_MAX_SIZE > avail) {
854 /* We have found a possible frame header candidate, but can't be
855 sure since we don't have enough data to check the next frame */
856 GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
857 *framesize + LOAS_MAX_SIZE, avail);
858 *needed_data = *framesize + LOAS_MAX_SIZE;
859 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
860 *framesize + LOAS_MAX_SIZE);
864 if ((data[*framesize] == 0x56) && ((data[*framesize + 1] & 0xe0) == 0xe0)) {
865 guint nextlen = gst_aac_parse_loas_get_frame_len (data + (*framesize));
867 GST_LOG ("LOAS frame found, len: %d bytes", *framesize);
868 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
869 nextlen + LOAS_MAX_SIZE);
872 GST_DEBUG_OBJECT (aacparse, "That was a false positive");
878 /* caller ensure sufficient data */
880 gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
881 gint * rate, gint * channels, gint * object, gint * version)
885 gint sr_idx = (data[2] & 0x3c) >> 2;
887 *rate = gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
890 *channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
896 *version = (data[1] & 0x08) ? 2 : 4;
898 *object = ((data[2] & 0xc0) >> 6) + 1;
902 * gst_aac_parse_detect_stream:
903 * @aacparse: #GstAacParse.
904 * @data: A block of data that needs to be examined for stream characteristics.
905 * @avail: Size of the given datablock.
906 * @framesize: If valid stream was found, this will be set to tell the
907 * first frame size in bytes.
908 * @skipsize: If valid stream was found, this will be set to tell the first
909 * audio frame position within the given data.
911 * Examines the given piece of data and try to detect the format of it. It
912 * checks for "ADIF" header (in the beginning of the clip) and ADTS frame
913 * header. If the stream is detected, TRUE will be returned and #framesize
914 * is set to indicate the found frame size. Additionally, #skipsize might
915 * be set to indicate the number of bytes that need to be skipped, a.k.a. the
916 * position of the frame inside given data chunk.
918 * Returns: TRUE on success.
921 gst_aac_parse_detect_stream (GstAacParse * aacparse,
922 const guint8 * data, const guint avail, gboolean drain,
923 guint * framesize, gint * skipsize)
925 gboolean found = FALSE;
926 guint need_data_adts = 0, need_data_loas;
929 GST_DEBUG_OBJECT (aacparse, "Parsing header data");
931 /* FIXME: No need to check for ADIF if we are not in the beginning of the
934 /* Can we even parse the header? */
935 if (avail < MAX (ADTS_MAX_SIZE, LOAS_MAX_SIZE)) {
936 GST_DEBUG_OBJECT (aacparse, "Not enough data to check");
940 for (i = 0; i < avail - 4; i++) {
941 if (((data[i] == 0xff) && ((data[i + 1] & 0xf6) == 0xf0)) ||
942 ((data[i] == 0x56) && ((data[i + 1] & 0xe0) == 0xe0)) ||
943 strncmp ((char *) data + i, "ADIF", 4) == 0) {
944 GST_DEBUG_OBJECT (aacparse, "Found signature at offset %u", i);
948 /* Trick: tell the parent class that we didn't find the frame yet,
949 but make it skip 'i' amount of bytes. Next time we arrive
950 here we have full frame in the beginning of the data. */
963 if (gst_aac_parse_check_adts_frame (aacparse, data, avail, drain,
964 framesize, &need_data_adts)) {
967 GST_INFO ("ADTS ID: %d, framesize: %d", (data[1] & 0x08) >> 3, *framesize);
969 gst_aac_parse_parse_adts_header (aacparse, data, &rate, &channels,
970 &aacparse->object_type, &aacparse->mpegversion);
972 if (!channels || !framesize) {
973 GST_DEBUG_OBJECT (aacparse, "impossible ADTS configuration");
977 aacparse->header_type = DSPAAC_HEADER_ADTS;
978 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
979 aacparse->frame_samples, 2, 2);
981 GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
982 rate, channels, aacparse->object_type, aacparse->mpegversion);
984 gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
989 if (gst_aac_parse_check_loas_frame (aacparse, data, avail, drain,
990 framesize, &need_data_loas)) {
991 gint rate = 0, channels = 0;
993 GST_INFO ("LOAS, framesize: %d", *framesize);
995 aacparse->header_type = DSPAAC_HEADER_LOAS;
997 if (!gst_aac_parse_read_loas_config (aacparse, data, avail, &rate,
998 &channels, &aacparse->mpegversion)) {
999 /* This is pretty normal when skipping data at the start of
1000 * random stream (MPEG-TS capture for example) */
1001 GST_LOG_OBJECT (aacparse, "Error reading LOAS config");
1005 if (rate && channels) {
1006 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
1007 aacparse->frame_samples, 2, 2);
1009 /* Don't store the sample rate and channels yet -
1010 * this is just format detection. */
1011 GST_DEBUG ("LOAS: samplerate %d, channels %d, objtype %d, version %d",
1012 rate, channels, aacparse->object_type, aacparse->mpegversion);
1015 gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
1020 if (need_data_adts || need_data_loas) {
1021 /* This tells the parent class not to skip any data */
1026 if (avail < ADIF_MAX_SIZE)
1029 if (memcmp (data + i, "ADIF", 4) == 0) {
1036 aacparse->header_type = DSPAAC_HEADER_ADIF;
1037 aacparse->mpegversion = 4;
1039 /* Skip the "ADIF" bytes */
1040 adif = data + i + 4;
1042 /* copyright string */
1044 skip_size += 9; /* skip 9 bytes */
1046 bitstream_type = adif[0 + skip_size] & 0x10;
1048 ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
1049 ((unsigned int) adif[1 + skip_size] << 11) |
1050 ((unsigned int) adif[2 + skip_size] << 3) |
1051 ((unsigned int) adif[3 + skip_size] & 0xe0);
1054 if (bitstream_type == 0) {
1056 /* Buffer fullness parsing. Currently not needed... */
1057 guint num_elems = 0;
1060 num_elems = (adif[3 + skip_size] & 0x1e);
1061 GST_INFO ("ADIF num_config_elems: %d", num_elems);
1063 fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) |
1064 ((unsigned int) adif[4 + skip_size] << 11) |
1065 ((unsigned int) adif[5 + skip_size] << 3) |
1066 ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5);
1068 GST_INFO ("ADIF buffer fullness: %d", fullness);
1070 aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) |
1071 ((adif[7 + skip_size] & 0x80) >> 7);
1072 sr_idx = (adif[7 + skip_size] & 0x78) >> 3;
1076 aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3;
1077 sr_idx = ((adif[4 + skip_size] & 0x07) << 1) |
1078 ((adif[5 + skip_size] & 0x80) >> 7);
1081 /* FIXME: This gives totally wrong results. Duration calculation cannot
1083 aacparse->sample_rate =
1084 gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
1086 /* baseparse is not given any fps,
1087 * so it will give up on timestamps, seeking, etc */
1089 /* FIXME: Can we assume this? */
1090 aacparse->channels = 2;
1092 GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d",
1093 aacparse->bitrate, aacparse->sample_rate, aacparse->object_type);
1095 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 512);
1097 /* arrange for metadata and get out of the way */
1098 sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (aacparse));
1099 gst_aac_parse_set_src_caps (aacparse, sinkcaps);
1101 gst_caps_unref (sinkcaps);
1103 /* not syncable, not easily seekable (unless we push data from start */
1104 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
1105 gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), TRUE);
1106 gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), 0);
1112 /* This should never happen */
1117 * gst_aac_parse_get_audio_profile_object_type
1118 * @aacparse: #GstAacParse.
1120 * Gets the MPEG-2 profile or the MPEG-4 object type value corresponding to the
1121 * mpegversion and profile of @aacparse's src pad caps, according to the
1122 * values defined by table 1.A.11 in ISO/IEC 14496-3.
1124 * Returns: the profile or object type value corresponding to @aacparse's src
1125 * pad caps, if such a value exists; otherwise G_MAXUINT8.
1128 gst_aac_parse_get_audio_profile_object_type (GstAacParse * aacparse)
1131 GstStructure *srcstruct;
1132 const gchar *profile;
1135 srccaps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse));
1136 if (G_UNLIKELY (srccaps == NULL)) {
1140 srcstruct = gst_caps_get_structure (srccaps, 0);
1141 profile = gst_structure_get_string (srcstruct, "profile");
1142 if (G_UNLIKELY (profile == NULL)) {
1143 gst_caps_unref (srccaps);
1147 if (g_strcmp0 (profile, "main") == 0) {
1149 } else if (g_strcmp0 (profile, "lc") == 0) {
1151 } else if (g_strcmp0 (profile, "ssr") == 0) {
1153 } else if (g_strcmp0 (profile, "ltp") == 0) {
1154 if (G_LIKELY (aacparse->mpegversion == 4))
1157 ret = G_MAXUINT8; /* LTP Object Type allowed only for MPEG-4 */
1162 gst_caps_unref (srccaps);
1167 * gst_aac_parse_get_audio_channel_configuration
1168 * @num_channels: number of audio channels.
1170 * Gets the Channel Configuration value, as defined by table 1.19 in ISO/IEC
1171 * 14496-3, for a given number of audio channels.
1173 * Returns: the Channel Configuration value corresponding to @num_channels, if
1174 * such a value exists; otherwise G_MAXUINT8.
1177 gst_aac_parse_get_audio_channel_configuration (gint num_channels)
1179 if (num_channels >= 1 && num_channels <= 6) /* Mono up to & including 5.1 */
1180 return (guint8) num_channels;
1181 else if (num_channels == 8) /* 7.1 */
1186 /* FIXME: Add support for configurations 11, 12 and 14 from
1187 * ISO/IEC 14496-3:2009/PDAM 4 based on the actual channel layout
1192 * gst_aac_parse_get_audio_sampling_frequency_index:
1193 * @sample_rate: audio sampling rate.
1195 * Gets the Sampling Frequency Index value, as defined by table 1.18 in ISO/IEC
1196 * 14496-3, for a given sampling rate.
1198 * Returns: the Sampling Frequency Index value corresponding to @sample_rate,
1199 * if such a value exists; otherwise G_MAXUINT8.
1202 gst_aac_parse_get_audio_sampling_frequency_index (gint sample_rate)
1204 switch (sample_rate) {
1237 * gst_aac_parse_prepend_adts_headers:
1238 * @aacparse: #GstAacParse.
1239 * @frame: raw AAC frame to which ADTS headers shall be prepended.
1241 * Prepends ADTS headers to a raw AAC audio frame.
1243 * Returns: TRUE if ADTS headers were successfully prepended; FALSE otherwise.
1246 gst_aac_parse_prepend_adts_headers (GstAacParse * aacparse,
1247 GstBaseParseFrame * frame)
1250 guint8 *adts_headers;
1253 guint8 id, profile, channel_configuration, sampling_frequency_index;
1255 id = (aacparse->mpegversion == 4) ? 0x0U : 0x1U;
1256 profile = gst_aac_parse_get_audio_profile_object_type (aacparse);
1257 if (profile == G_MAXUINT8) {
1258 GST_ERROR_OBJECT (aacparse, "Unsupported audio profile or object type");
1261 channel_configuration =
1262 gst_aac_parse_get_audio_channel_configuration (aacparse->channels);
1263 if (channel_configuration == G_MAXUINT8) {
1264 GST_ERROR_OBJECT (aacparse, "Unsupported number of channels");
1267 sampling_frequency_index =
1268 gst_aac_parse_get_audio_sampling_frequency_index (aacparse->sample_rate);
1269 if (sampling_frequency_index == G_MAXUINT8) {
1270 GST_ERROR_OBJECT (aacparse, "Unsupported sampling frequency");
1274 frame->out_buffer = gst_buffer_copy (frame->buffer);
1275 buf_size = gst_buffer_get_size (frame->out_buffer);
1276 frame_size = buf_size + ADTS_HEADERS_LENGTH;
1278 if (G_UNLIKELY (frame_size >= 0x4000)) {
1279 GST_ERROR_OBJECT (aacparse, "Frame size is too big for ADTS");
1283 adts_headers = (guint8 *) g_malloc0 (ADTS_HEADERS_LENGTH);
1285 /* Note: no error correction bits are added to the resulting ADTS frames */
1286 adts_headers[0] = 0xFFU;
1287 adts_headers[1] = 0xF0U | (id << 3) | 0x1U;
1288 adts_headers[2] = (profile << 6) | (sampling_frequency_index << 2) | 0x2U |
1289 ((channel_configuration & 0x4U) >> 2);
1290 adts_headers[3] = ((channel_configuration & 0x3U) << 6) | 0x30U |
1291 (guint8) (frame_size >> 11);
1292 adts_headers[4] = (guint8) ((frame_size >> 3) & 0x00FF);
1293 adts_headers[5] = (guint8) (((frame_size & 0x0007) << 5) + 0x1FU);
1294 adts_headers[6] = 0xFCU;
1296 mem = gst_memory_new_wrapped (0, adts_headers, ADTS_HEADERS_LENGTH, 0,
1297 ADTS_HEADERS_LENGTH, adts_headers, g_free);
1298 gst_buffer_prepend_memory (frame->out_buffer, mem);
1304 * gst_aac_parse_check_valid_frame:
1305 * @parse: #GstBaseParse.
1306 * @frame: #GstBaseParseFrame.
1307 * @skipsize: How much data parent class should skip in order to find the
1310 * Implementation of "handle_frame" vmethod in #GstBaseParse class.
1312 * Also determines frame overhead.
1313 * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
1314 * a per-frame header. LOAS has 3 bytes.
1316 * We're making a couple of simplifying assumptions:
1318 * 1. We count Program Configuration Elements rather than searching for them
1319 * in the streams to discount them - the overhead is negligible.
1321 * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16
1322 * bits, which should still not be significant enough to warrant the
1323 * additional parsing through the headers
1325 * Returns: a #GstFlowReturn.
1327 static GstFlowReturn
1328 gst_aac_parse_handle_frame (GstBaseParse * parse,
1329 GstBaseParseFrame * frame, gint * skipsize)
1332 GstAacParse *aacparse;
1333 gboolean ret = FALSE;
1337 gint rate = 0, channels = 0;
1339 aacparse = GST_AAC_PARSE (parse);
1340 buffer = frame->buffer;
1342 gst_buffer_map (buffer, &map, GST_MAP_READ);
1345 lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
1347 if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
1348 aacparse->header_type == DSPAAC_HEADER_NONE) {
1349 /* There is nothing to parse */
1350 framesize = map.size;
1353 } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
1355 ret = gst_aac_parse_detect_stream (aacparse, map.data, map.size,
1356 GST_BASE_PARSE_DRAINING (parse), &framesize, skipsize);
1358 } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
1359 guint needed_data = 1024;
1361 ret = gst_aac_parse_check_adts_frame (aacparse, map.data, map.size,
1362 GST_BASE_PARSE_DRAINING (parse), &framesize, &needed_data);
1364 if (!ret && needed_data) {
1365 GST_DEBUG ("buffer didn't contain valid frame");
1367 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
1371 } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
1372 guint needed_data = 1024;
1374 ret = gst_aac_parse_check_loas_frame (aacparse, map.data,
1375 map.size, GST_BASE_PARSE_DRAINING (parse), &framesize, &needed_data);
1377 if (!ret && needed_data) {
1378 GST_DEBUG ("buffer didn't contain valid frame");
1380 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
1385 GST_DEBUG ("buffer didn't contain valid frame");
1386 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
1390 if (G_UNLIKELY (!ret))
1393 if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
1395 frame->overhead = 7;
1397 gst_aac_parse_parse_adts_header (aacparse, map.data,
1398 &rate, &channels, NULL, NULL);
1400 GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
1402 if (G_UNLIKELY (rate != aacparse->sample_rate
1403 || channels != aacparse->channels)) {
1404 aacparse->sample_rate = rate;
1405 aacparse->channels = channels;
1407 if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
1408 /* If linking fails, we need to return appropriate error */
1409 ret = GST_FLOW_NOT_LINKED;
1412 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
1413 aacparse->sample_rate, aacparse->frame_samples, 2, 2);
1415 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1416 if (aacparse->first_frame == TRUE) {
1417 gboolean ret = FALSE;
1418 aacparse->first_frame = FALSE;
1420 ret = gst_aac_parse_estimate_duration (parse);
1422 GST_WARNING_OBJECT (aacparse, "can not estimate total duration");
1423 ret = GST_FLOW_NOT_SUPPORTED;
1427 } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
1428 gboolean setcaps = FALSE;
1431 frame->overhead = 3;
1433 if (!gst_aac_parse_read_loas_config (aacparse, map.data, map.size, &rate,
1434 &channels, NULL) || !rate || !channels) {
1435 /* This is pretty normal when skipping data at the start of
1436 * random stream (MPEG-TS capture for example) */
1437 GST_DEBUG_OBJECT (aacparse, "Error reading LOAS config. Skipping.");
1438 /* Since we don't fully parse the LOAS config, we don't know for sure
1439 * how much to skip. Just skip 1 to end up to the next marker and
1440 * resume parsing from there */
1445 if (G_UNLIKELY (rate != aacparse->sample_rate
1446 || channels != aacparse->channels)) {
1447 aacparse->sample_rate = rate;
1448 aacparse->channels = channels;
1450 GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
1454 /* We want to set caps both at start, and when rate/channels change.
1455 Since only some LOAS frames have that info, we may receive frames
1456 before knowing about rate/channels. */
1458 || !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
1459 if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
1460 /* If linking fails, we need to return appropriate error */
1461 ret = GST_FLOW_NOT_LINKED;
1464 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
1465 aacparse->sample_rate, aacparse->frame_samples, 2, 2);
1468 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1469 else if (aacparse->header_type == DSPAAC_HEADER_ADIF) {
1470 /* to get more correct duration */
1471 float estimated_duration = 0;
1472 gint64 total_file_size;
1473 gst_base_parse_get_upstream_size (parse, &total_file_size);
1474 estimated_duration =
1475 ((total_file_size * 8) / (float) (aacparse->bitrate * 1000)) *
1477 gst_base_parse_set_duration (parse, GST_FORMAT_TIME,
1478 estimated_duration * 1000, 0);
1482 if (aacparse->header_type == DSPAAC_HEADER_NONE
1483 && aacparse->output_header_type == DSPAAC_HEADER_ADTS) {
1484 if (!gst_aac_parse_prepend_adts_headers (aacparse, frame)) {
1485 GST_ERROR_OBJECT (aacparse, "Failed to prepend ADTS headers to frame");
1486 ret = GST_FLOW_ERROR;
1491 gst_buffer_unmap (buffer, &map);
1494 /* found, skip if needed */
1503 if (ret && framesize <= map.size) {
1504 return gst_base_parse_finish_frame (parse, frame, framesize);
1510 static GstFlowReturn
1511 gst_aac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1513 GstAacParse *aacparse = GST_AAC_PARSE (parse);
1515 if (!aacparse->sent_codec_tag) {
1516 GstTagList *taglist;
1520 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1522 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
1523 GST_INFO_OBJECT (parse, "Src pad is flushing");
1524 return GST_FLOW_FLUSHING;
1526 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
1527 return GST_FLOW_NOT_NEGOTIATED;
1531 taglist = gst_tag_list_new_empty ();
1532 gst_pb_utils_add_codec_description_to_tag_list (taglist,
1533 GST_TAG_AUDIO_CODEC, caps);
1534 gst_caps_unref (caps);
1536 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
1537 gst_tag_list_unref (taglist);
1539 /* also signals the end of first-frame processing */
1540 aacparse->sent_codec_tag = TRUE;
1543 /* As a special case, we can remove the ADTS framing and output raw AAC. */
1544 if (aacparse->header_type == DSPAAC_HEADER_ADTS
1545 && aacparse->output_header_type == DSPAAC_HEADER_NONE) {
1548 frame->out_buffer = gst_buffer_make_writable (frame->buffer);
1549 frame->buffer = NULL;
1550 gst_buffer_map (frame->out_buffer, &map, GST_MAP_READ);
1551 header_size = (map.data[1] & 1) ? 7 : 9; /* optional CRC */
1552 gst_buffer_unmap (frame->out_buffer, &map);
1553 gst_buffer_resize (frame->out_buffer, header_size,
1554 gst_buffer_get_size (frame->out_buffer) - header_size);
1562 * gst_aac_parse_start:
1563 * @parse: #GstBaseParse.
1565 * Implementation of "start" vmethod in #GstBaseParse class.
1567 * Returns: TRUE if startup succeeded.
1570 gst_aac_parse_start (GstBaseParse * parse)
1572 GstAacParse *aacparse;
1574 aacparse = GST_AAC_PARSE (parse);
1575 GST_DEBUG ("start");
1576 aacparse->frame_samples = 1024;
1577 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), ADTS_MAX_SIZE);
1578 aacparse->sent_codec_tag = FALSE;
1579 aacparse->last_parsed_channels = 0;
1580 aacparse->last_parsed_sample_rate = 0;
1581 aacparse->object_type = 0;
1582 aacparse->bitrate = 0;
1583 aacparse->header_type = DSPAAC_HEADER_NOT_PARSED;
1584 aacparse->output_header_type = DSPAAC_HEADER_NOT_PARSED;
1585 aacparse->channels = 0;
1586 aacparse->sample_rate = 0;
1592 * gst_aac_parse_stop:
1593 * @parse: #GstBaseParse.
1595 * Implementation of "stop" vmethod in #GstBaseParse class.
1597 * Returns: TRUE is stopping succeeded.
1600 gst_aac_parse_stop (GstBaseParse * parse)
1607 remove_fields (GstCaps * caps)
1611 n = gst_caps_get_size (caps);
1612 for (i = 0; i < n; i++) {
1613 GstStructure *s = gst_caps_get_structure (caps, i);
1615 gst_structure_remove_field (s, "framed");
1620 add_conversion_fields (GstCaps * caps)
1624 n = gst_caps_get_size (caps);
1625 for (i = 0; i < n; i++) {
1626 GstStructure *s = gst_caps_get_structure (caps, i);
1628 if (gst_structure_has_field (s, "stream-format")) {
1629 const GValue *v = gst_structure_get_value (s, "stream-format");
1631 if (G_VALUE_HOLDS_STRING (v)) {
1632 const gchar *str = g_value_get_string (v);
1634 if (strcmp (str, "adts") == 0 || strcmp (str, "raw") == 0) {
1635 GValue va = G_VALUE_INIT;
1636 GValue vs = G_VALUE_INIT;
1638 g_value_init (&va, GST_TYPE_LIST);
1639 g_value_init (&vs, G_TYPE_STRING);
1640 g_value_set_string (&vs, "adts");
1641 gst_value_list_append_value (&va, &vs);
1642 g_value_set_string (&vs, "raw");
1643 gst_value_list_append_value (&va, &vs);
1644 gst_structure_set_value (s, "stream-format", &va);
1645 g_value_unset (&va);
1646 g_value_unset (&vs);
1648 } else if (GST_VALUE_HOLDS_LIST (v)) {
1649 gboolean contains_raw = FALSE;
1650 gboolean contains_adts = FALSE;
1651 guint m = gst_value_list_get_size (v), j;
1653 for (j = 0; j < m; j++) {
1654 const GValue *ve = gst_value_list_get_value (v, j);
1657 if (G_VALUE_HOLDS_STRING (ve) && (str = g_value_get_string (ve))) {
1658 if (strcmp (str, "adts") == 0)
1659 contains_adts = TRUE;
1660 else if (strcmp (str, "raw") == 0)
1661 contains_raw = TRUE;
1665 if (contains_adts || contains_raw) {
1666 GValue va = G_VALUE_INIT;
1667 GValue vs = G_VALUE_INIT;
1669 g_value_init (&va, GST_TYPE_LIST);
1670 g_value_init (&vs, G_TYPE_STRING);
1671 g_value_copy (v, &va);
1673 if (!contains_raw) {
1674 g_value_set_string (&vs, "raw");
1675 gst_value_list_append_value (&va, &vs);
1677 if (!contains_adts) {
1678 g_value_set_string (&vs, "adts");
1679 gst_value_list_append_value (&va, &vs);
1682 gst_structure_set_value (s, "stream-format", &va);
1684 g_value_unset (&vs);
1685 g_value_unset (&va);
1693 gst_aac_parse_sink_getcaps (GstBaseParse * parse, GstCaps * filter)
1695 GstCaps *peercaps, *templ;
1698 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1701 GstCaps *fcopy = gst_caps_copy (filter);
1702 /* Remove the fields we convert */
1703 remove_fields (fcopy);
1704 add_conversion_fields (fcopy);
1705 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1706 gst_caps_unref (fcopy);
1708 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1711 peercaps = gst_caps_make_writable (peercaps);
1712 /* Remove the fields we convert */
1713 remove_fields (peercaps);
1714 add_conversion_fields (peercaps);
1716 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1717 gst_caps_unref (peercaps);
1718 gst_caps_unref (templ);
1724 GstCaps *intersection;
1727 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1728 gst_caps_unref (res);
1736 gst_aac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1738 GstAacParse *aacparse = GST_AAC_PARSE (parse);
1740 if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
1741 aacparse->last_parsed_channels = 0;
1742 aacparse->last_parsed_sample_rate = 0;
1744 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1745 GST_DEBUG ("Entering gst_aac_parse_src_event header type = %d",
1746 aacparse->header_type);
1747 if (aacparse->header_type == DSPAAC_HEADER_ADTS)
1748 return gst_aac_parse_adts_src_eventfunc (parse, event);
1750 return GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1754 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1756 * get_aac_parse_get_adts_framelength:
1757 * @data: #GstBufferData.
1758 * @offset: #GstBufferData offset
1760 * Implementation to get adts framelength by using first some frame.
1762 * Returns: frame size
1765 get_aac_parse_get_adts_frame_length (const unsigned char *data, gint64 offset)
1767 const gint adts_header_length_no_crc = 7;
1768 const gint adts_header_length_with_crc = 9;
1769 gint frame_size = 0;
1770 gint protection_absent;
1773 /* check of syncword */
1774 if ((data[offset + 0] != 0xff) || ((data[offset + 1] & 0xf6) != 0xf0)) {
1775 GST_ERROR ("check sync word is fail\n");
1779 /* check of protection absent */
1780 protection_absent = (data[offset + 1] & 0x01);
1782 /*check of frame length */
1784 (data[offset + 3] & 0x3) << 11 | data[offset + 4] << 3 | data[offset +
1787 /* check of header size */
1788 /* protectionAbsent is 0 if there is CRC */
1790 protection_absent ? adts_header_length_no_crc :
1791 adts_header_length_with_crc;
1792 if (head_size > frame_size) {
1793 GST_ERROR ("return frame length as 0 (frameSize %u < headSize %u)",
1794 frame_size, head_size);
1802 * gst_aac_parse_estimate_duration:
1803 * @parse: #GstBaseParse.
1805 * Implementation to get estimated total duration by using first some frame.
1807 * Returns: TRUE if we can get estimated total duraion
1810 gst_aac_parse_estimate_duration (GstBaseParse * parse)
1812 gboolean ret = FALSE;
1813 GstFlowReturn res = GST_FLOW_OK;
1814 gint64 pull_size = 0, file_size = 0, offset = 0, num_frames = 0, duration = 0;
1815 guint sample_rate_index = 0, sample_rate = 0, channel = 0;
1816 guint frame_size = 0, frame_duration_us = 0, estimated_bitrate = 0;
1817 guint lost_sync_count = 0;
1818 GstClockTime estimated_duration = GST_CLOCK_TIME_NONE;
1819 GstBuffer *buffer = NULL;
1822 GstPadMode pad_mode = GST_PAD_MODE_NONE;
1823 GstAacParse *aacparse;
1824 gint64 buffer_size = 0;
1827 aacparse = GST_AAC_PARSE (parse);
1828 GST_LOG_OBJECT (aacparse, "gst_aac_parse_estimate_duration enter");
1830 /* check baseparse define these fuction */
1831 gst_base_parse_get_pad_mode (parse, &pad_mode);
1832 if (pad_mode != GST_PAD_MODE_PULL) {
1833 GST_INFO_OBJECT (aacparse,
1834 "aac parser is not pull mode. can not estimate duration");
1838 gst_base_parse_get_upstream_size (parse, &file_size);
1840 if (file_size < ADIF_MAX_SIZE) {
1841 GST_ERROR_OBJECT (aacparse, "file size is too short");
1845 pull_size = MIN (file_size, AAC_MAX_ESTIMATE_DURATION_BUF);
1847 res = gst_pad_pull_range (parse->sinkpad, 0, pull_size, &buffer);
1848 if (res != GST_FLOW_OK) {
1849 GST_ERROR_OBJECT (aacparse, "gst_pad_pull_range failed!");
1853 gst_buffer_map (buffer, &map, GST_MAP_READ);
1855 buffer_size = map.size;
1856 if (buffer_size != pull_size) {
1857 GST_ERROR_OBJECT (aacparse,
1858 "We got different buffer_size(%" G_GINT64_FORMAT ") with pull_size(%"
1859 G_GINT64_FORMAT ").", buffer_size, pull_size);
1862 /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
1863 for (i = 0; i < buffer_size; i++) {
1864 if ((buf[i] == 0xff) && ((buf[i + 1] & 0xf6) == 0xf0)) { /* aac sync word */
1865 //guint profile = (buf[i+2] >> 6) & 0x3;
1866 sample_rate_index = (buf[i + 2] >> 2) & 0xf;
1868 gst_aac_parse_get_sample_rate_from_index (sample_rate_index);
1869 if (sample_rate == 0) {
1870 GST_WARNING_OBJECT (aacparse, "Invalid sample rate index (0)");
1873 channel = (buf[i + 2] & 0x1) << 2 | (buf[i + 3] >> 6);
1875 GST_INFO_OBJECT (aacparse, "found sync. aac fs=%d, ch=%d", sample_rate,
1878 /* count number of frames */
1879 /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
1880 //while (offset < pull_size) {
1881 while (offset < buffer_size) {
1882 frame_size = get_aac_parse_get_adts_frame_length (buf, i + offset);
1883 if (frame_size == 0) {
1884 GST_ERROR_OBJECT (aacparse,
1885 "framesize error at offset %" G_GINT64_FORMAT, offset);
1887 } else if (frame_size == -1) {
1889 lost_sync_count++; // lost sync count limmitation 2K Bytes
1890 if (lost_sync_count > (1024 * 2)) {
1891 GST_WARNING_OBJECT (aacparse,
1892 "lost_sync_count is larger than 2048");
1896 offset += frame_size;
1898 lost_sync_count = 0;
1902 /* if we can got full file, we can calculate the accurate duration */
1903 /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
1904 //if (pull_size == file_size) {
1905 if (buffer_size == file_size) {
1906 gfloat duration_for_one_frame = 0;
1907 GstClockTime calculated_duration = GST_CLOCK_TIME_NONE;
1909 GST_INFO_OBJECT (aacparse,
1910 "we got total file (%" G_GINT64_FORMAT
1911 " bytes). do not estimate but make Accurate total duration.",
1914 duration_for_one_frame =
1915 (gfloat) AAC_SAMPLE_PER_FRAME / (gfloat) sample_rate;
1916 calculated_duration =
1917 num_frames * duration_for_one_frame * 1000 * 1000 * 1000;
1919 GST_INFO_OBJECT (aacparse, "duration_for_one_frame %f ms",
1920 duration_for_one_frame);
1921 GST_INFO_OBJECT (aacparse, "calculated duration = %" GST_TIME_FORMAT,
1922 GST_TIME_ARGS (calculated_duration));
1923 /* 0 means disable estimate */
1924 gst_base_parse_set_duration (parse, GST_FORMAT_TIME,
1925 calculated_duration, 0);
1928 GST_INFO_OBJECT (aacparse,
1929 "we got %" G_GUINT64_FORMAT " bytes in total file (%"
1930 G_GINT64_FORMAT "). can not make accurate duration but Estimate.",
1931 pull_size, file_size);
1933 (1024 * 1000000ll + (sample_rate - 1)) / sample_rate;
1934 duration = num_frames * frame_duration_us;
1936 if (duration == 0) {
1937 GST_WARNING_OBJECT (aacparse, "Invalid duration");
1941 (gint) ((gfloat) (offset * 8) / (gfloat) (duration / 1000));
1943 if (estimated_bitrate == 0) {
1944 GST_WARNING_OBJECT (aacparse, "Invalid estimated_bitrate");
1947 estimated_duration =
1948 (GstClockTime) ((file_size * 8) / (estimated_bitrate * 1000)) *
1951 GST_INFO_OBJECT (aacparse, "number of frame = %" G_GINT64_FORMAT,
1953 GST_INFO_OBJECT (aacparse, "duration = %" G_GINT64_FORMAT,
1954 duration / 1000000);
1955 GST_INFO_OBJECT (aacparse, "byte = %" G_GINT64_FORMAT, offset);
1956 GST_INFO_OBJECT (aacparse, "estimated bitrate = %d bps",
1958 GST_INFO_OBJECT (aacparse, "estimated duration = %" GST_TIME_FORMAT,
1959 GST_TIME_ARGS (estimated_duration));
1961 gst_base_parse_set_average_bitrate (parse, estimated_bitrate * 1000);
1962 /* set update_interval as duration(sec)/2 */
1963 gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration,
1964 (gint) (duration / 2));
1973 gst_buffer_unmap (buffer, &map);
1974 gst_buffer_unref (buffer);
1979 /* perform seek in push based mode:
1980 find BYTE position to move to based on time and delegate to upstream
1983 gst_aac_audio_parse_do_push_seek (GstBaseParse * parse,
1984 GstPad * pad, GstEvent * event)
1986 GstAacParse *aacparse = GST_AAC_PARSE (parse);
1990 GstSeekType cur_type, stop_type;
1994 gint64 esimate_byte;
1996 gint64 upstream_total_bytes = 0;
1997 GstFormat fmt = GST_FORMAT_BYTES;
1999 GST_INFO_OBJECT (parse, "doing aac push-based seek");
2001 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2004 /* FIXME, always play to the end */
2007 /* only forward streaming and seeking is possible */
2009 goto unsupported_seek;
2012 /* handle rewind only */
2013 cur_type = GST_SEEK_TYPE_SET;
2015 stop_type = GST_SEEK_TYPE_NONE;
2017 flags |= GST_SEEK_FLAG_FLUSH;
2019 /* handle normal seek */
2020 cur_type = GST_SEEK_TYPE_SET;
2021 stop_type = GST_SEEK_TYPE_NONE;
2023 flags |= GST_SEEK_FLAG_FLUSH;
2025 esimate_byte = (cur / (1000 * 1000)) * aacparse->frame_byte;
2026 if (aacparse->sample_rate > 0)
2027 frame_dur = (aacparse->spf * 1000) / aacparse->sample_rate;
2029 goto unsupported_seek;
2031 byte_cur = esimate_byte / (frame_dur);
2033 goto unsupported_seek;
2035 GST_INFO_OBJECT (parse, "frame_byte(%d) spf(%d) rate (%d) ",
2036 aacparse->frame_byte, aacparse->spf, aacparse->sample_rate);
2037 GST_INFO_OBJECT (parse,
2038 "seek cur (%" G_GINT64_FORMAT ") = (%" GST_TIME_FORMAT ") ", cur,
2039 GST_TIME_ARGS (cur));
2040 GST_INFO_OBJECT (parse,
2041 "esimate_byte(%" G_GINT64_FORMAT ") esimate_byte (%d)", esimate_byte,
2045 /* obtain real upstream total bytes */
2046 if (!gst_pad_peer_query_duration (parse->sinkpad, fmt, &upstream_total_bytes))
2047 upstream_total_bytes = 0;
2048 GST_INFO_OBJECT (aacparse,
2049 "gst_pad_query_peer_duration -upstream_total_bytes (%" G_GUINT64_FORMAT
2050 ")", upstream_total_bytes);
2051 aacparse->file_size = upstream_total_bytes;
2053 if ((byte_cur == -1) || (byte_cur > aacparse->file_size)) {
2054 GST_INFO_OBJECT (parse,
2055 "[WEB-ERROR] seek cur (%" G_GINT64_FORMAT ") > file_size (%"
2056 G_GINT64_FORMAT ") ", cur, aacparse->file_size);
2060 GST_INFO_OBJECT (parse,
2061 "Pushing BYTE seek rate %g, " "start %" G_GINT64_FORMAT ", stop %"
2062 G_GINT64_FORMAT, rate, byte_cur, stop);
2064 if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
2065 GST_INFO_OBJECT (parse,
2066 "Requested seek time: %" GST_TIME_FORMAT ", calculated seek offset: %"
2067 G_GUINT64_FORMAT, GST_TIME_ARGS (cur), byte_cur);
2070 /* BYTE seek event */
2072 gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
2074 res = gst_pad_push_event (parse->sinkpad, event);
2082 GST_DEBUG_OBJECT (parse,
2083 "could not determine byte position to seek to, " "seek aborted.");
2089 GST_DEBUG_OBJECT (parse, "unsupported seek, seek aborted.");
2096 gst_aac_parse_adts_get_fast_frame_len (const guint8 * data)
2099 if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
2101 ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
2109 * gst_aac_parse_adts_src_eventfunc:
2110 * @parse: #GstBaseParse. #event
2112 * before baseparse handles seek event, make full amr index table.
2114 * Returns: TRUE on success.
2117 gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse, GstEvent * event)
2119 gboolean handled = FALSE;
2120 GstAacParse *aacparse = GST_AAC_PARSE (parse);
2122 switch (GST_EVENT_TYPE (event)) {
2123 case GST_EVENT_SEEK:
2125 GstFlowReturn res = GST_FLOW_OK;
2126 gint64 base_offset = 0, cur = 0;
2127 gint32 frame_count = 1; /* do not add first frame because it is already in index table */
2128 gint64 second_count = 0; /* initial 1 second */
2129 gint64 total_file_size = 0, start_offset = 0;
2130 GstClockTime current_ts = GST_CLOCK_TIME_NONE;
2131 GstPadMode pad_mode = GST_PAD_MODE_NONE;
2133 /* check baseparse define these fuction */
2134 gst_base_parse_get_pad_mode (parse, &pad_mode);
2135 if (pad_mode != GST_PAD_MODE_PULL) {
2136 gboolean ret = FALSE;
2137 GstPad *srcpad = parse->srcpad;
2138 GST_INFO_OBJECT (aacparse, "aac parser is PUSH MODE.");
2140 ret = gst_aac_audio_parse_do_push_seek (parse, srcpad, event);
2141 gst_object_unref (srcpad);
2144 gst_base_parse_get_upstream_size (parse, &total_file_size);
2145 gst_base_parse_get_index_last_offset (parse, &start_offset);
2146 gst_base_parse_get_index_last_ts (parse, ¤t_ts);
2148 if (total_file_size > AAC_LARGE_FILE_SIZE) {
2149 gst_base_parse_set_seek_mode (parse, 0);
2150 GST_INFO_OBJECT (aacparse, "larger than big size (2MB).");
2151 goto aac_seek_null_exit;
2154 GST_DEBUG ("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK enter");
2156 if (total_file_size == 0 || start_offset >= total_file_size) {
2157 GST_ERROR ("last index offset %" G_GINT64_FORMAT
2158 " is larger than file size %" G_GINT64_FORMAT, start_offset,
2163 gst_event_parse_seek (event, NULL, NULL, NULL, NULL, &cur, NULL, NULL);
2164 if (cur <= current_ts) {
2165 GST_INFO ("seek to %" GST_TIME_FORMAT " within index table %"
2166 GST_TIME_FORMAT ". do not make index table", GST_TIME_ARGS (cur),
2167 GST_TIME_ARGS (current_ts));
2170 GST_INFO ("seek to %" GST_TIME_FORMAT " without index table %"
2171 GST_TIME_FORMAT ". make index table", GST_TIME_ARGS (cur),
2172 GST_TIME_ARGS (current_ts));
2175 GST_INFO ("make AAC(ADTS) Index Table. file_size = %" G_GINT64_FORMAT
2176 " last idx offset=%" G_GINT64_FORMAT ", last idx ts=%"
2177 GST_TIME_FORMAT, total_file_size, start_offset,
2178 GST_TIME_ARGS (current_ts));
2180 base_offset = start_offset; /* set base by start offset */
2181 second_count = current_ts + GST_SECOND; /* 1sec */
2183 /************************************/
2184 /* STEP 0: Setting parse information */
2185 /************************************/
2186 aacparse->spf = aacparse->frame_samples;
2187 aacparse->frame_duration = (aacparse->spf * 1000 * 100) / aacparse->sample_rate; /* duration per frame (msec) */
2188 aacparse->frame_per_sec = (aacparse->sample_rate) / aacparse->spf; /* frames per second (ea) */
2190 /************************************/
2191 /* STEP 1: MAX_PULL_RANGE_BUF cycle */
2192 /************************************/
2193 while (total_file_size - base_offset >= AAC_MAX_PULL_RANGE_BUF) {
2195 GstBuffer *buffer = NULL;
2198 GST_INFO ("gst_pad_pull_range %d bytes (from %" G_GINT64_FORMAT
2199 ") use max size", AAC_MAX_PULL_RANGE_BUF, base_offset);
2201 gst_pad_pull_range (parse->sinkpad, base_offset,
2202 base_offset + AAC_MAX_PULL_RANGE_BUF, &buffer);
2203 if (res != GST_FLOW_OK) {
2204 GST_ERROR ("gst_pad_pull_range failed!");
2208 gst_buffer_map (buffer, &map, GST_MAP_READ);
2211 gst_buffer_unmap (buffer, &map);
2212 GST_WARNING ("buffer is NULL in make aac seek table's STEP1");
2213 gst_buffer_unref (buffer);
2214 goto aac_seek_null_exit;
2217 while (offset <= AAC_MAX_PULL_RANGE_BUF) {
2218 gint frame_size = 0;
2220 /* make sure the values in the frame header look sane */
2221 frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
2223 if ((frame_size > 0)
2224 && (frame_size < (AAC_MAX_PULL_RANGE_BUF - offset))) {
2225 if (current_ts > second_count) { /* 1 sec == xx frames. we make idx per sec */
2226 gst_base_parse_add_index_entry (parse, base_offset + offset, current_ts, TRUE, TRUE); /* force */
2227 GST_DEBUG ("Adding index ts=%" GST_TIME_FORMAT " offset %"
2228 G_GINT64_FORMAT, GST_TIME_ARGS (current_ts),
2229 base_offset + offset);
2230 second_count += GST_SECOND; /* 1sec */
2233 current_ts += (aacparse->frame_duration * GST_MSECOND) / 100; /* each frame is (frame_duration) ms */
2234 offset += frame_size;
2237 } else if (frame_size >= (AAC_MAX_PULL_RANGE_BUF - offset)) {
2238 GST_DEBUG ("we need refill buffer");
2241 GST_WARNING ("we lost sync");
2247 base_offset = base_offset + offset;
2249 gst_buffer_unmap (buffer, &map);
2250 gst_buffer_unref (buffer);
2251 } /* end MAX buffer cycle */
2253 /*******************************/
2254 /* STEP 2: Remain Buffer cycle */
2255 /*******************************/
2256 if (total_file_size - base_offset > 0) {
2258 GstBuffer *buffer = NULL;
2262 GST_INFO ("gst_pad_pull_range %" G_GINT64_FORMAT " bytes (from %"
2263 G_GINT64_FORMAT ") use remain_buf size",
2264 total_file_size - base_offset, base_offset);
2266 gst_pad_pull_range (parse->sinkpad, base_offset, total_file_size,
2268 if (res != GST_FLOW_OK) {
2269 GST_ERROR ("gst_pad_pull_range failed!");
2273 gst_buffer_map (buffer, &map, GST_MAP_READ);
2276 gst_buffer_unmap (buffer, &map);
2277 GST_WARNING ("buffer is NULL in make aac seek table's STEP2");
2278 gst_buffer_unref (buffer);
2279 goto aac_seek_null_exit;
2282 while (base_offset + offset < total_file_size) {
2283 gint frame_size = 0;
2285 /* make sure the values in the frame header look sane */
2286 frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
2288 if ((frame_size > 0)
2289 && (frame_size <= (total_file_size - (base_offset + offset)))) {
2290 if (current_ts > second_count) { /* 1 sec == xx frames. we make idx per sec */
2291 gst_base_parse_add_index_entry (parse, base_offset + offset, current_ts, TRUE, TRUE); /* force */
2292 GST_DEBUG ("Adding index ts=%" GST_TIME_FORMAT " offset %"
2293 G_GINT64_FORMAT, GST_TIME_ARGS (current_ts),
2294 base_offset + offset);
2295 second_count += GST_SECOND; /* 1sec */
2298 current_ts += (aacparse->frame_duration * GST_MSECOND) / 100; /* each frame is (frame_duration) ms */
2299 offset += frame_size;
2302 } else if (frame_size == 0) {
2303 GST_DEBUG ("Frame size is 0 so, Decoding end..");
2306 GST_WARNING ("we lost sync");
2312 gst_buffer_unmap (buffer, &map);
2313 gst_buffer_unref (buffer);
2315 /* end remain_buf buffer cycle */
2316 GST_DEBUG ("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK leave");
2326 /* call baseparse src_event function to handle event */
2327 handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2330 #endif /* TIZEN_FEATURE_AACPARSE_MODIFICATION */