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 allowed = gst_pad_get_allowed_caps (GST_BASE_PARSE (aacparse)->srcpad);
266 if (allowed && !gst_caps_can_intersect (src_caps, allowed)) {
267 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
268 "Caps can not intersect");
269 if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
270 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
271 "Input is ADTS, trying raw");
272 gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "raw",
274 if (gst_caps_can_intersect (src_caps, allowed)) {
275 GstBuffer *codec_data_buffer;
277 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
278 "Caps can intersect, we will drop the ADTS layer");
279 aacparse->output_header_type = DSPAAC_HEADER_NONE;
281 /* The codec_data data is according to AudioSpecificConfig,
282 ISO/IEC 14496-3, 1.6.2.1 */
283 codec_data_buffer = gst_buffer_new_and_alloc (2);
284 gst_buffer_fill (codec_data_buffer, 0, codec_data, 2);
285 gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER,
286 codec_data_buffer, NULL);
287 gst_buffer_unref (codec_data_buffer);
289 } else if (aacparse->header_type == DSPAAC_HEADER_NONE) {
290 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
291 "Input is raw, trying ADTS");
292 gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adts",
294 if (gst_caps_can_intersect (src_caps, allowed)) {
295 GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
296 "Caps can intersect, we will prepend ADTS headers");
297 aacparse->output_header_type = DSPAAC_HEADER_ADTS;
302 gst_caps_unref (allowed);
304 aacparse->last_parsed_channels = 0;
305 aacparse->last_parsed_sample_rate = 0;
307 GST_DEBUG_OBJECT (aacparse, "setting src caps: %" GST_PTR_FORMAT, src_caps);
309 res = gst_pad_set_caps (GST_BASE_PARSE (aacparse)->srcpad, src_caps);
310 gst_caps_unref (src_caps);
314 GST_ERROR_OBJECT (aacparse, "Not a known sample rate: %d",
315 aacparse->sample_rate);
316 gst_caps_unref (src_caps);
322 * gst_aac_parse_sink_setcaps:
326 * Implementation of "set_sink_caps" vmethod in #GstBaseParse class.
328 * Returns: TRUE on success.
331 gst_aac_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
333 GstAacParse *aacparse;
334 GstStructure *structure;
338 aacparse = GST_AAC_PARSE (parse);
339 structure = gst_caps_get_structure (caps, 0);
340 caps_str = gst_caps_to_string (caps);
342 GST_DEBUG_OBJECT (aacparse, "setcaps: %s", caps_str);
345 /* This is needed at least in case of RTP
346 * Parses the codec_data information to get ObjectType,
347 * number of channels and samplerate */
348 value = gst_structure_get_value (structure, "codec_data");
350 GstBuffer *buf = gst_value_get_buffer (value);
352 if (buf && gst_buffer_get_size (buf) >= 2) {
356 if (!gst_buffer_map (buf, &map, GST_MAP_READ))
358 gst_bit_reader_init (&br, map.data, map.size);
359 gst_aac_parse_read_audio_specific_config (aacparse, &br,
360 &aacparse->object_type, &aacparse->sample_rate, &aacparse->channels,
361 &aacparse->frame_samples);
363 aacparse->header_type = DSPAAC_HEADER_NONE;
364 aacparse->mpegversion = 4;
365 gst_buffer_unmap (buf, &map);
367 GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d, "
368 "samples=%d", aacparse->object_type, aacparse->sample_rate,
369 aacparse->channels, aacparse->frame_samples);
371 /* arrange for metadata and get out of the way */
372 gst_aac_parse_set_src_caps (aacparse, caps);
373 if (aacparse->header_type == aacparse->output_header_type)
374 gst_base_parse_set_passthrough (parse, TRUE);
376 /* input is already correctly framed */
377 gst_base_parse_set_min_frame_size (parse, RAW_MAX_SIZE);
382 /* caps info overrides */
383 gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
384 gst_structure_get_int (structure, "channels", &aacparse->channels);
386 const gchar *stream_format =
387 gst_structure_get_string (structure, "stream-format");
389 if (g_strcmp0 (stream_format, "raw") == 0) {
390 GST_ERROR_OBJECT (parse, "Need codec_data for raw AAC");
393 aacparse->sample_rate = 0;
394 aacparse->channels = 0;
395 aacparse->header_type = DSPAAC_HEADER_NOT_PARSED;
396 gst_base_parse_set_passthrough (parse, FALSE);
404 * gst_aac_parse_adts_get_frame_len:
405 * @data: block of data containing an ADTS header.
407 * This function calculates ADTS frame length from the given header.
409 * Returns: size of the ADTS frame.
412 gst_aac_parse_adts_get_frame_len (const guint8 * data)
414 return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
419 * gst_aac_parse_check_adts_frame:
420 * @aacparse: #GstAacParse.
421 * @data: Data to be checked.
422 * @avail: Amount of data passed.
423 * @framesize: If valid ADTS frame was found, this will be set to tell the
424 * found frame size in bytes.
425 * @needed_data: If frame was not found, this may be set to tell how much
426 * more data is needed in the next round to detect the frame
427 * reliably. This may happen when a frame header candidate
428 * is found but it cannot be guaranteed to be the header without
429 * peeking the following data.
431 * Check if the given data contains contains ADTS frame. The algorithm
432 * will examine ADTS frame header and calculate the frame size. Also, another
433 * consecutive ADTS frame header need to be present after the found frame.
434 * Otherwise the data is not considered as a valid ADTS frame. However, this
435 * "extra check" is omitted when EOS has been received. In this case it is
436 * enough when data[0] contains a valid ADTS header.
438 * This function may set the #needed_data to indicate that a possible frame
439 * candidate has been found, but more data (#needed_data bytes) is needed to
440 * be absolutely sure. When this situation occurs, FALSE will be returned.
442 * When a valid frame is detected, this function will use
443 * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
444 * to set the needed bytes for next frame.This way next data chunk is already
447 * Returns: TRUE if the given data contains a valid ADTS header.
450 gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
451 const guint8 * data, const guint avail, gboolean drain,
452 guint * framesize, guint * needed_data)
458 /* Absolute minimum to perform the ADTS syncword,
459 layer and sampling frequency tests */
460 if (G_UNLIKELY (avail < 3)) {
465 /* Syncword and layer tests */
466 if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
468 /* Sampling frequency test */
469 if (G_UNLIKELY ((data[2] & 0x3C) >> 2 == 15))
472 /* This looks like an ADTS frame header but
473 we need at least 6 bytes to proceed */
474 if (G_UNLIKELY (avail < 6)) {
479 *framesize = gst_aac_parse_adts_get_frame_len (data);
481 /* If frame has CRC, it needs 2 bytes
482 for it at the end of the header */
483 crc_size = (data[1] & 0x01) ? 0 : 2;
486 if (*framesize < 7 + crc_size) {
487 *needed_data = 7 + crc_size;
491 /* In EOS mode this is enough. No need to examine the data further.
492 We also relax the check when we have sync, on the assumption that
493 if we're not looking at random data, we have a much higher chance
494 to get the correct sync, and this avoids losing two frames when
495 a single bit corruption happens. */
496 if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
500 if (*framesize + ADTS_MAX_SIZE > avail) {
501 /* We have found a possible frame header candidate, but can't be
502 sure since we don't have enough data to check the next frame */
503 GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
504 *framesize + ADTS_MAX_SIZE, avail);
505 *needed_data = *framesize + ADTS_MAX_SIZE;
506 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
507 *framesize + ADTS_MAX_SIZE);
511 if ((data[*framesize] == 0xff) && ((data[*framesize + 1] & 0xf6) == 0xf0)) {
512 guint nextlen = gst_aac_parse_adts_get_frame_len (data + (*framesize));
514 GST_LOG ("ADTS frame found, len: %d bytes", *framesize);
515 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
516 nextlen + ADTS_MAX_SIZE);
524 gst_aac_parse_latm_get_value (GstAacParse * aacparse, GstBitReader * br,
527 guint8 bytes, i, byte;
530 if (!gst_bit_reader_get_bits_uint8 (br, &bytes, 2))
532 for (i = 0; i <= bytes; ++i) {
534 if (!gst_bit_reader_get_bits_uint8 (br, &byte, 8))
542 gst_aac_parse_get_audio_object_type (GstAacParse * aacparse, GstBitReader * br,
543 guint8 * audio_object_type)
545 if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 5))
547 if (*audio_object_type == 31) {
548 if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 6))
550 *audio_object_type += 32;
552 GST_LOG_OBJECT (aacparse, "audio object type %u", *audio_object_type);
557 gst_aac_parse_get_audio_sample_rate (GstAacParse * aacparse, GstBitReader * br,
560 guint8 sampling_frequency_index;
561 if (!gst_bit_reader_get_bits_uint8 (br, &sampling_frequency_index, 4))
563 GST_LOG_OBJECT (aacparse, "sampling_frequency_index: %u",
564 sampling_frequency_index);
565 if (sampling_frequency_index == 0xf) {
566 guint32 sampling_rate;
567 if (!gst_bit_reader_get_bits_uint32 (br, &sampling_rate, 24))
569 *sample_rate = sampling_rate;
571 *sample_rate = loas_sample_rate_table[sampling_frequency_index];
575 aacparse->last_parsed_sample_rate = *sample_rate;
579 /* See table 1.13 in ISO/IEC 14496-3 */
581 gst_aac_parse_read_audio_specific_config (GstAacParse * aacparse,
582 GstBitReader * br, gint * object_type, gint * sample_rate, gint * channels,
583 gint * frame_samples)
585 guint8 audio_object_type;
586 guint8 G_GNUC_UNUSED extension_audio_object_type;
587 guint8 channel_configuration, extension_channel_configuration;
588 gboolean G_GNUC_UNUSED sbr = FALSE, ps = FALSE;
590 if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type))
593 *object_type = audio_object_type;
595 if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
598 if (!gst_bit_reader_get_bits_uint8 (br, &channel_configuration, 4))
600 *channels = loas_channels_table[channel_configuration];
601 GST_LOG_OBJECT (aacparse, "channel_configuration: %d", channel_configuration);
605 if (audio_object_type == 5 || audio_object_type == 29) {
606 extension_audio_object_type = 5;
608 if (audio_object_type == 29) {
610 /* Parametric stereo. If we have a one-channel configuration, we can
611 * override it to stereo */
616 GST_LOG_OBJECT (aacparse,
617 "Audio object type 5 or 29, so rereading sampling rate (was %d)...",
619 if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
622 if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type))
625 if (audio_object_type == 22) {
626 /* extension channel configuration */
627 if (!gst_bit_reader_get_bits_uint8 (br, &extension_channel_configuration,
630 GST_LOG_OBJECT (aacparse, "extension channel_configuration: %d",
631 extension_channel_configuration);
632 *channels = loas_channels_table[extension_channel_configuration];
637 extension_audio_object_type = 0;
640 GST_INFO_OBJECT (aacparse, "Parsed AudioSpecificConfig: %d Hz, %d channels",
641 *sample_rate, *channels);
643 if (frame_samples && audio_object_type == 23) {
645 /* Read the Decoder Configuration (GASpecificConfig) if present */
646 /* We only care about the first bit to know what the number of samples
648 if (!gst_bit_reader_get_bits_uint8 (br, &frame_flag, 1))
650 *frame_samples = frame_flag ? 960 : 1024;
653 /* There's LOTS of stuff next, but we ignore it for now as we have
654 what we want (sample rate and number of channels */
655 GST_DEBUG_OBJECT (aacparse,
656 "Need more code to parse humongous LOAS data, currently ignored");
657 aacparse->last_parsed_channels = *channels;
663 gst_aac_parse_read_loas_config (GstAacParse * aacparse, const guint8 * data,
664 guint avail, gint * sample_rate, gint * channels, gint * version)
669 /* No version in the bitstream, but the spec has LOAS in the MPEG-4 section */
673 gst_bit_reader_init (&br, data, avail);
675 /* skip sync word (11 bits) and size (13 bits) */
676 if (!gst_bit_reader_skip (&br, 11 + 13))
679 /* First bit is "use last config" */
680 if (!gst_bit_reader_get_bits_uint8 (&br, &u8, 1))
683 GST_LOG_OBJECT (aacparse, "Frame uses previous config");
684 if (!aacparse->last_parsed_sample_rate || !aacparse->last_parsed_channels) {
685 GST_DEBUG_OBJECT (aacparse,
686 "No previous config to use. We'll look for more data.");
689 *sample_rate = aacparse->last_parsed_sample_rate;
690 *channels = aacparse->last_parsed_channels;
694 GST_DEBUG_OBJECT (aacparse, "Frame contains new config");
696 /* audioMuxVersion */
697 if (!gst_bit_reader_get_bits_uint8 (&br, &v, 1))
700 /* audioMuxVersionA */
701 if (!gst_bit_reader_get_bits_uint8 (&br, &vA, 1))
706 GST_LOG_OBJECT (aacparse, "v %d, vA %d", v, vA);
708 guint8 same_time, subframes, num_program, prog;
711 /* taraBufferFullness */
712 if (!gst_aac_parse_latm_get_value (aacparse, &br, &value))
715 if (!gst_bit_reader_get_bits_uint8 (&br, &same_time, 1))
717 if (!gst_bit_reader_get_bits_uint8 (&br, &subframes, 6))
719 if (!gst_bit_reader_get_bits_uint8 (&br, &num_program, 4))
721 GST_LOG_OBJECT (aacparse, "same_time %d, subframes %d, num_program %d",
722 same_time, subframes, num_program);
724 for (prog = 0; prog <= num_program; ++prog) {
725 guint8 num_layer, layer;
726 if (!gst_bit_reader_get_bits_uint8 (&br, &num_layer, 3))
728 GST_LOG_OBJECT (aacparse, "Program %d: %d layers", prog, num_layer);
730 for (layer = 0; layer <= num_layer; ++layer) {
731 guint8 use_same_config;
732 if (prog == 0 && layer == 0) {
735 if (!gst_bit_reader_get_bits_uint8 (&br, &use_same_config, 1))
738 if (!use_same_config) {
740 if (!gst_aac_parse_read_audio_specific_config (aacparse, &br, NULL,
741 sample_rate, channels, NULL))
745 if (!gst_aac_parse_latm_get_value (aacparse, &br, &asc_len))
747 if (!gst_aac_parse_read_audio_specific_config (aacparse, &br, NULL,
748 sample_rate, channels, NULL))
750 if (!gst_bit_reader_skip (&br, asc_len))
756 GST_LOG_OBJECT (aacparse, "More data ignored");
758 GST_WARNING_OBJECT (aacparse, "Spec says \"TBD\"...");
765 * gst_aac_parse_loas_get_frame_len:
766 * @data: block of data containing a LOAS header.
768 * This function calculates LOAS frame length from the given header.
770 * Returns: size of the LOAS frame.
773 gst_aac_parse_loas_get_frame_len (const guint8 * data)
775 return (((data[1] & 0x1f) << 8) | data[2]) + 3;
780 * gst_aac_parse_check_loas_frame:
781 * @aacparse: #GstAacParse.
782 * @data: Data to be checked.
783 * @avail: Amount of data passed.
784 * @framesize: If valid LOAS frame was found, this will be set to tell the
785 * found frame size in bytes.
786 * @needed_data: If frame was not found, this may be set to tell how much
787 * more data is needed in the next round to detect the frame
788 * reliably. This may happen when a frame header candidate
789 * is found but it cannot be guaranteed to be the header without
790 * peeking the following data.
792 * Check if the given data contains contains LOAS frame. The algorithm
793 * will examine LOAS frame header and calculate the frame size. Also, another
794 * consecutive LOAS frame header need to be present after the found frame.
795 * Otherwise the data is not considered as a valid LOAS frame. However, this
796 * "extra check" is omitted when EOS has been received. In this case it is
797 * enough when data[0] contains a valid LOAS header.
799 * This function may set the #needed_data to indicate that a possible frame
800 * candidate has been found, but more data (#needed_data bytes) is needed to
801 * be absolutely sure. When this situation occurs, FALSE will be returned.
803 * When a valid frame is detected, this function will use
804 * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
805 * to set the needed bytes for next frame.This way next data chunk is already
808 * LOAS can have three different formats, if I read the spec correctly. Only
809 * one of them is supported here, as the two samples I have use this one.
811 * Returns: TRUE if the given data contains a valid LOAS header.
814 gst_aac_parse_check_loas_frame (GstAacParse * aacparse,
815 const guint8 * data, const guint avail, gboolean drain,
816 guint * framesize, guint * needed_data)
821 if (G_UNLIKELY (avail < 3)) {
826 if ((data[0] == 0x56) && ((data[1] & 0xe0) == 0xe0)) {
827 *framesize = gst_aac_parse_loas_get_frame_len (data);
828 GST_DEBUG_OBJECT (aacparse, "Found possible %u byte LOAS frame",
831 /* In EOS mode this is enough. No need to examine the data further.
832 We also relax the check when we have sync, on the assumption that
833 if we're not looking at random data, we have a much higher chance
834 to get the correct sync, and this avoids losing two frames when
835 a single bit corruption happens. */
836 if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
840 if (*framesize + LOAS_MAX_SIZE > avail) {
841 /* We have found a possible frame header candidate, but can't be
842 sure since we don't have enough data to check the next frame */
843 GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
844 *framesize + LOAS_MAX_SIZE, avail);
845 *needed_data = *framesize + LOAS_MAX_SIZE;
846 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
847 *framesize + LOAS_MAX_SIZE);
851 if ((data[*framesize] == 0x56) && ((data[*framesize + 1] & 0xe0) == 0xe0)) {
852 guint nextlen = gst_aac_parse_loas_get_frame_len (data + (*framesize));
854 GST_LOG ("LOAS frame found, len: %d bytes", *framesize);
855 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
856 nextlen + LOAS_MAX_SIZE);
859 GST_DEBUG_OBJECT (aacparse, "That was a false positive");
865 /* caller ensure sufficient data */
867 gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
868 gint * rate, gint * channels, gint * object, gint * version)
872 gint sr_idx = (data[2] & 0x3c) >> 2;
874 *rate = gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
877 *channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
883 *version = (data[1] & 0x08) ? 2 : 4;
885 *object = ((data[2] & 0xc0) >> 6) + 1;
889 * gst_aac_parse_detect_stream:
890 * @aacparse: #GstAacParse.
891 * @data: A block of data that needs to be examined for stream characteristics.
892 * @avail: Size of the given datablock.
893 * @framesize: If valid stream was found, this will be set to tell the
894 * first frame size in bytes.
895 * @skipsize: If valid stream was found, this will be set to tell the first
896 * audio frame position within the given data.
898 * Examines the given piece of data and try to detect the format of it. It
899 * checks for "ADIF" header (in the beginning of the clip) and ADTS frame
900 * header. If the stream is detected, TRUE will be returned and #framesize
901 * is set to indicate the found frame size. Additionally, #skipsize might
902 * be set to indicate the number of bytes that need to be skipped, a.k.a. the
903 * position of the frame inside given data chunk.
905 * Returns: TRUE on success.
908 gst_aac_parse_detect_stream (GstAacParse * aacparse,
909 const guint8 * data, const guint avail, gboolean drain,
910 guint * framesize, gint * skipsize)
912 gboolean found = FALSE;
913 guint need_data_adts = 0, need_data_loas;
916 GST_DEBUG_OBJECT (aacparse, "Parsing header data");
918 /* FIXME: No need to check for ADIF if we are not in the beginning of the
921 /* Can we even parse the header? */
922 if (avail < MAX (ADTS_MAX_SIZE, LOAS_MAX_SIZE)) {
923 GST_DEBUG_OBJECT (aacparse, "Not enough data to check");
927 for (i = 0; i < avail - 4; i++) {
928 if (((data[i] == 0xff) && ((data[i + 1] & 0xf6) == 0xf0)) ||
929 ((data[i] == 0x56) && ((data[i + 1] & 0xe0) == 0xe0)) ||
930 strncmp ((char *) data + i, "ADIF", 4) == 0) {
931 GST_DEBUG_OBJECT (aacparse, "Found signature at offset %u", i);
935 /* Trick: tell the parent class that we didn't find the frame yet,
936 but make it skip 'i' amount of bytes. Next time we arrive
937 here we have full frame in the beginning of the data. */
950 if (gst_aac_parse_check_adts_frame (aacparse, data, avail, drain,
951 framesize, &need_data_adts)) {
954 GST_INFO ("ADTS ID: %d, framesize: %d", (data[1] & 0x08) >> 3, *framesize);
956 gst_aac_parse_parse_adts_header (aacparse, data, &rate, &channels,
957 &aacparse->object_type, &aacparse->mpegversion);
959 if (!channels || !framesize) {
960 GST_DEBUG_OBJECT (aacparse, "impossible ADTS configuration");
964 aacparse->header_type = DSPAAC_HEADER_ADTS;
965 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
966 aacparse->frame_samples, 2, 2);
968 GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
969 rate, channels, aacparse->object_type, aacparse->mpegversion);
971 gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
976 if (gst_aac_parse_check_loas_frame (aacparse, data, avail, drain,
977 framesize, &need_data_loas)) {
978 gint rate = 0, channels = 0;
980 GST_INFO ("LOAS, framesize: %d", *framesize);
982 aacparse->header_type = DSPAAC_HEADER_LOAS;
984 if (!gst_aac_parse_read_loas_config (aacparse, data, avail, &rate,
985 &channels, &aacparse->mpegversion)) {
986 /* This is pretty normal when skipping data at the start of
987 * random stream (MPEG-TS capture for example) */
988 GST_LOG_OBJECT (aacparse, "Error reading LOAS config");
992 if (rate && channels) {
993 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
994 aacparse->frame_samples, 2, 2);
996 /* Don't store the sample rate and channels yet -
997 * this is just format detection. */
998 GST_DEBUG ("LOAS: samplerate %d, channels %d, objtype %d, version %d",
999 rate, channels, aacparse->object_type, aacparse->mpegversion);
1002 gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
1007 if (need_data_adts || need_data_loas) {
1008 /* This tells the parent class not to skip any data */
1013 if (avail < ADIF_MAX_SIZE)
1016 if (memcmp (data + i, "ADIF", 4) == 0) {
1023 aacparse->header_type = DSPAAC_HEADER_ADIF;
1024 aacparse->mpegversion = 4;
1026 /* Skip the "ADIF" bytes */
1027 adif = data + i + 4;
1029 /* copyright string */
1031 skip_size += 9; /* skip 9 bytes */
1033 bitstream_type = adif[0 + skip_size] & 0x10;
1035 ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
1036 ((unsigned int) adif[1 + skip_size] << 11) |
1037 ((unsigned int) adif[2 + skip_size] << 3) |
1038 ((unsigned int) adif[3 + skip_size] & 0xe0);
1041 if (bitstream_type == 0) {
1043 /* Buffer fullness parsing. Currently not needed... */
1044 guint num_elems = 0;
1047 num_elems = (adif[3 + skip_size] & 0x1e);
1048 GST_INFO ("ADIF num_config_elems: %d", num_elems);
1050 fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) |
1051 ((unsigned int) adif[4 + skip_size] << 11) |
1052 ((unsigned int) adif[5 + skip_size] << 3) |
1053 ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5);
1055 GST_INFO ("ADIF buffer fullness: %d", fullness);
1057 aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) |
1058 ((adif[7 + skip_size] & 0x80) >> 7);
1059 sr_idx = (adif[7 + skip_size] & 0x78) >> 3;
1063 aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3;
1064 sr_idx = ((adif[4 + skip_size] & 0x07) << 1) |
1065 ((adif[5 + skip_size] & 0x80) >> 7);
1068 /* FIXME: This gives totally wrong results. Duration calculation cannot
1070 aacparse->sample_rate =
1071 gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
1073 /* baseparse is not given any fps,
1074 * so it will give up on timestamps, seeking, etc */
1076 /* FIXME: Can we assume this? */
1077 aacparse->channels = 2;
1079 GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d",
1080 aacparse->bitrate, aacparse->sample_rate, aacparse->object_type);
1082 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 512);
1084 /* arrange for metadata and get out of the way */
1085 sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (aacparse));
1086 gst_aac_parse_set_src_caps (aacparse, sinkcaps);
1088 gst_caps_unref (sinkcaps);
1090 /* not syncable, not easily seekable (unless we push data from start */
1091 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
1092 gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), TRUE);
1093 gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), 0);
1099 /* This should never happen */
1104 * gst_aac_parse_get_audio_profile_object_type
1105 * @aacparse: #GstAacParse.
1107 * Gets the MPEG-2 profile or the MPEG-4 object type value corresponding to the
1108 * mpegversion and profile of @aacparse's src pad caps, according to the
1109 * values defined by table 1.A.11 in ISO/IEC 14496-3.
1111 * Returns: the profile or object type value corresponding to @aacparse's src
1112 * pad caps, if such a value exists; otherwise G_MAXUINT8.
1115 gst_aac_parse_get_audio_profile_object_type (GstAacParse * aacparse)
1118 GstStructure *srcstruct;
1119 const gchar *profile;
1122 srccaps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse));
1123 if (G_UNLIKELY (srccaps == NULL)) {
1127 srcstruct = gst_caps_get_structure (srccaps, 0);
1128 profile = gst_structure_get_string (srcstruct, "profile");
1129 if (G_UNLIKELY (profile == NULL)) {
1130 gst_caps_unref (srccaps);
1134 if (g_strcmp0 (profile, "main") == 0) {
1136 } else if (g_strcmp0 (profile, "lc") == 0) {
1138 } else if (g_strcmp0 (profile, "ssr") == 0) {
1140 } else if (g_strcmp0 (profile, "ltp") == 0) {
1141 if (G_LIKELY (aacparse->mpegversion == 4))
1144 ret = G_MAXUINT8; /* LTP Object Type allowed only for MPEG-4 */
1149 gst_caps_unref (srccaps);
1154 * gst_aac_parse_get_audio_channel_configuration
1155 * @num_channels: number of audio channels.
1157 * Gets the Channel Configuration value, as defined by table 1.19 in ISO/IEC
1158 * 14496-3, for a given number of audio channels.
1160 * Returns: the Channel Configuration value corresponding to @num_channels, if
1161 * such a value exists; otherwise G_MAXUINT8.
1164 gst_aac_parse_get_audio_channel_configuration (gint num_channels)
1166 if (num_channels >= 1 && num_channels <= 6) /* Mono up to & including 5.1 */
1167 return (guint8) num_channels;
1168 else if (num_channels == 8) /* 7.1 */
1173 /* FIXME: Add support for configurations 11, 12 and 14 from
1174 * ISO/IEC 14496-3:2009/PDAM 4 based on the actual channel layout
1179 * gst_aac_parse_get_audio_sampling_frequency_index:
1180 * @sample_rate: audio sampling rate.
1182 * Gets the Sampling Frequency Index value, as defined by table 1.18 in ISO/IEC
1183 * 14496-3, for a given sampling rate.
1185 * Returns: the Sampling Frequency Index value corresponding to @sample_rate,
1186 * if such a value exists; otherwise G_MAXUINT8.
1189 gst_aac_parse_get_audio_sampling_frequency_index (gint sample_rate)
1191 switch (sample_rate) {
1224 * gst_aac_parse_prepend_adts_headers:
1225 * @aacparse: #GstAacParse.
1226 * @frame: raw AAC frame to which ADTS headers shall be prepended.
1228 * Prepends ADTS headers to a raw AAC audio frame.
1230 * Returns: TRUE if ADTS headers were successfully prepended; FALSE otherwise.
1233 gst_aac_parse_prepend_adts_headers (GstAacParse * aacparse,
1234 GstBaseParseFrame * frame)
1237 guint8 *adts_headers;
1240 guint8 id, profile, channel_configuration, sampling_frequency_index;
1242 id = (aacparse->mpegversion == 4) ? 0x0U : 0x1U;
1243 profile = gst_aac_parse_get_audio_profile_object_type (aacparse);
1244 if (profile == G_MAXUINT8) {
1245 GST_ERROR_OBJECT (aacparse, "Unsupported audio profile or object type");
1248 channel_configuration =
1249 gst_aac_parse_get_audio_channel_configuration (aacparse->channels);
1250 if (channel_configuration == G_MAXUINT8) {
1251 GST_ERROR_OBJECT (aacparse, "Unsupported number of channels");
1254 sampling_frequency_index =
1255 gst_aac_parse_get_audio_sampling_frequency_index (aacparse->sample_rate);
1256 if (sampling_frequency_index == G_MAXUINT8) {
1257 GST_ERROR_OBJECT (aacparse, "Unsupported sampling frequency");
1261 frame->out_buffer = gst_buffer_copy (frame->buffer);
1262 buf_size = gst_buffer_get_size (frame->out_buffer);
1263 frame_size = buf_size + ADTS_HEADERS_LENGTH;
1265 if (G_UNLIKELY (frame_size >= 0x4000)) {
1266 GST_ERROR_OBJECT (aacparse, "Frame size is too big for ADTS");
1270 adts_headers = (guint8 *) g_malloc0 (ADTS_HEADERS_LENGTH);
1272 /* Note: no error correction bits are added to the resulting ADTS frames */
1273 adts_headers[0] = 0xFFU;
1274 adts_headers[1] = 0xF0U | (id << 3) | 0x1U;
1275 adts_headers[2] = (profile << 6) | (sampling_frequency_index << 2) | 0x2U |
1276 ((channel_configuration & 0x4U) >> 2);
1277 adts_headers[3] = ((channel_configuration & 0x3U) << 6) | 0x30U |
1278 (guint8) (frame_size >> 11);
1279 adts_headers[4] = (guint8) ((frame_size >> 3) & 0x00FF);
1280 adts_headers[5] = (guint8) (((frame_size & 0x0007) << 5) + 0x1FU);
1281 adts_headers[6] = 0xFCU;
1283 mem = gst_memory_new_wrapped (0, adts_headers, ADTS_HEADERS_LENGTH, 0,
1284 ADTS_HEADERS_LENGTH, adts_headers, g_free);
1285 gst_buffer_prepend_memory (frame->out_buffer, mem);
1291 * gst_aac_parse_check_valid_frame:
1292 * @parse: #GstBaseParse.
1293 * @frame: #GstBaseParseFrame.
1294 * @skipsize: How much data parent class should skip in order to find the
1297 * Implementation of "handle_frame" vmethod in #GstBaseParse class.
1299 * Also determines frame overhead.
1300 * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
1301 * a per-frame header. LOAS has 3 bytes.
1303 * We're making a couple of simplifying assumptions:
1305 * 1. We count Program Configuration Elements rather than searching for them
1306 * in the streams to discount them - the overhead is negligible.
1308 * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16
1309 * bits, which should still not be significant enough to warrant the
1310 * additional parsing through the headers
1312 * Returns: a #GstFlowReturn.
1314 static GstFlowReturn
1315 gst_aac_parse_handle_frame (GstBaseParse * parse,
1316 GstBaseParseFrame * frame, gint * skipsize)
1319 GstAacParse *aacparse;
1320 gboolean ret = FALSE;
1324 gint rate = 0, channels = 0;
1326 aacparse = GST_AAC_PARSE (parse);
1327 buffer = frame->buffer;
1329 gst_buffer_map (buffer, &map, GST_MAP_READ);
1332 lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
1334 if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
1335 aacparse->header_type == DSPAAC_HEADER_NONE) {
1336 /* There is nothing to parse */
1337 framesize = map.size;
1340 } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
1342 ret = gst_aac_parse_detect_stream (aacparse, map.data, map.size,
1343 GST_BASE_PARSE_DRAINING (parse), &framesize, skipsize);
1345 } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
1346 guint needed_data = 1024;
1348 ret = gst_aac_parse_check_adts_frame (aacparse, map.data, map.size,
1349 GST_BASE_PARSE_DRAINING (parse), &framesize, &needed_data);
1351 if (!ret && needed_data) {
1352 GST_DEBUG ("buffer didn't contain valid frame");
1354 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
1358 } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
1359 guint needed_data = 1024;
1361 ret = gst_aac_parse_check_loas_frame (aacparse, map.data,
1362 map.size, 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),
1372 GST_DEBUG ("buffer didn't contain valid frame");
1373 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
1377 if (G_UNLIKELY (!ret))
1380 if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
1382 frame->overhead = 7;
1384 gst_aac_parse_parse_adts_header (aacparse, map.data,
1385 &rate, &channels, NULL, NULL);
1387 GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
1389 if (G_UNLIKELY (rate != aacparse->sample_rate
1390 || channels != aacparse->channels)) {
1391 aacparse->sample_rate = rate;
1392 aacparse->channels = channels;
1394 if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
1395 /* If linking fails, we need to return appropriate error */
1396 ret = GST_FLOW_NOT_LINKED;
1399 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
1400 aacparse->sample_rate, aacparse->frame_samples, 2, 2);
1402 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1403 if (aacparse->first_frame == TRUE) {
1404 gboolean ret = FALSE;
1405 aacparse->first_frame = FALSE;
1407 ret = gst_aac_parse_estimate_duration (parse);
1409 GST_WARNING_OBJECT (aacparse, "can not estimate total duration");
1410 ret = GST_FLOW_NOT_SUPPORTED;
1414 } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
1415 gboolean setcaps = FALSE;
1418 frame->overhead = 3;
1420 if (!gst_aac_parse_read_loas_config (aacparse, map.data, map.size, &rate,
1421 &channels, NULL) || !rate || !channels) {
1422 /* This is pretty normal when skipping data at the start of
1423 * random stream (MPEG-TS capture for example) */
1424 GST_DEBUG_OBJECT (aacparse, "Error reading LOAS config. Skipping.");
1425 /* Since we don't fully parse the LOAS config, we don't know for sure
1426 * how much to skip. Just skip 1 to end up to the next marker and
1427 * resume parsing from there */
1432 if (G_UNLIKELY (rate != aacparse->sample_rate
1433 || channels != aacparse->channels)) {
1434 aacparse->sample_rate = rate;
1435 aacparse->channels = channels;
1437 GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
1441 /* We want to set caps both at start, and when rate/channels change.
1442 Since only some LOAS frames have that info, we may receive frames
1443 before knowing about rate/channels. */
1445 || !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
1446 if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
1447 /* If linking fails, we need to return appropriate error */
1448 ret = GST_FLOW_NOT_LINKED;
1451 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
1452 aacparse->sample_rate, aacparse->frame_samples, 2, 2);
1455 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1456 else if (aacparse->header_type == DSPAAC_HEADER_ADIF) {
1457 /* to get more correct duration */
1458 float estimated_duration = 0;
1459 gint64 total_file_size;
1460 gst_base_parse_get_upstream_size (parse, &total_file_size);
1461 estimated_duration =
1462 ((total_file_size * 8) / (float) (aacparse->bitrate * 1000)) *
1464 gst_base_parse_set_duration (parse, GST_FORMAT_TIME,
1465 estimated_duration * 1000, 0);
1469 if (aacparse->header_type == DSPAAC_HEADER_NONE
1470 && aacparse->output_header_type == DSPAAC_HEADER_ADTS) {
1471 if (!gst_aac_parse_prepend_adts_headers (aacparse, frame)) {
1472 GST_ERROR_OBJECT (aacparse, "Failed to prepend ADTS headers to frame");
1473 ret = GST_FLOW_ERROR;
1478 gst_buffer_unmap (buffer, &map);
1481 /* found, skip if needed */
1490 if (ret && framesize <= map.size) {
1491 return gst_base_parse_finish_frame (parse, frame, framesize);
1497 static GstFlowReturn
1498 gst_aac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1500 GstAacParse *aacparse = GST_AAC_PARSE (parse);
1502 if (!aacparse->sent_codec_tag) {
1503 GstTagList *taglist;
1507 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1509 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
1510 GST_INFO_OBJECT (parse, "Src pad is flushing");
1511 return GST_FLOW_FLUSHING;
1513 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
1514 return GST_FLOW_NOT_NEGOTIATED;
1518 taglist = gst_tag_list_new_empty ();
1519 gst_pb_utils_add_codec_description_to_tag_list (taglist,
1520 GST_TAG_AUDIO_CODEC, caps);
1521 gst_caps_unref (caps);
1523 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
1524 gst_tag_list_unref (taglist);
1526 /* also signals the end of first-frame processing */
1527 aacparse->sent_codec_tag = TRUE;
1530 /* As a special case, we can remove the ADTS framing and output raw AAC. */
1531 if (aacparse->header_type == DSPAAC_HEADER_ADTS
1532 && aacparse->output_header_type == DSPAAC_HEADER_NONE) {
1535 frame->out_buffer = gst_buffer_make_writable (frame->buffer);
1536 frame->buffer = NULL;
1537 gst_buffer_map (frame->out_buffer, &map, GST_MAP_READ);
1538 header_size = (map.data[1] & 1) ? 7 : 9; /* optional CRC */
1539 gst_buffer_unmap (frame->out_buffer, &map);
1540 gst_buffer_resize (frame->out_buffer, header_size,
1541 gst_buffer_get_size (frame->out_buffer) - header_size);
1549 * gst_aac_parse_start:
1550 * @parse: #GstBaseParse.
1552 * Implementation of "start" vmethod in #GstBaseParse class.
1554 * Returns: TRUE if startup succeeded.
1557 gst_aac_parse_start (GstBaseParse * parse)
1559 GstAacParse *aacparse;
1561 aacparse = GST_AAC_PARSE (parse);
1562 GST_DEBUG ("start");
1563 aacparse->frame_samples = 1024;
1564 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), ADTS_MAX_SIZE);
1565 aacparse->sent_codec_tag = FALSE;
1566 aacparse->last_parsed_channels = 0;
1567 aacparse->last_parsed_sample_rate = 0;
1568 aacparse->object_type = 0;
1569 aacparse->bitrate = 0;
1570 aacparse->header_type = DSPAAC_HEADER_NOT_PARSED;
1571 aacparse->output_header_type = DSPAAC_HEADER_NOT_PARSED;
1572 aacparse->channels = 0;
1573 aacparse->sample_rate = 0;
1579 * gst_aac_parse_stop:
1580 * @parse: #GstBaseParse.
1582 * Implementation of "stop" vmethod in #GstBaseParse class.
1584 * Returns: TRUE is stopping succeeded.
1587 gst_aac_parse_stop (GstBaseParse * parse)
1594 remove_fields (GstCaps * caps)
1598 n = gst_caps_get_size (caps);
1599 for (i = 0; i < n; i++) {
1600 GstStructure *s = gst_caps_get_structure (caps, i);
1602 gst_structure_remove_field (s, "framed");
1607 add_conversion_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 if (gst_structure_has_field (s, "stream-format")) {
1616 const GValue *v = gst_structure_get_value (s, "stream-format");
1618 if (G_VALUE_HOLDS_STRING (v)) {
1619 const gchar *str = g_value_get_string (v);
1621 if (strcmp (str, "adts") == 0 || strcmp (str, "raw") == 0) {
1622 GValue va = G_VALUE_INIT;
1623 GValue vs = G_VALUE_INIT;
1625 g_value_init (&va, GST_TYPE_LIST);
1626 g_value_init (&vs, G_TYPE_STRING);
1627 g_value_set_string (&vs, "adts");
1628 gst_value_list_append_value (&va, &vs);
1629 g_value_set_string (&vs, "raw");
1630 gst_value_list_append_value (&va, &vs);
1631 gst_structure_set_value (s, "stream-format", &va);
1632 g_value_unset (&va);
1633 g_value_unset (&vs);
1635 } else if (GST_VALUE_HOLDS_LIST (v)) {
1636 gboolean contains_raw = FALSE;
1637 gboolean contains_adts = FALSE;
1638 guint m = gst_value_list_get_size (v), j;
1640 for (j = 0; j < m; j++) {
1641 const GValue *ve = gst_value_list_get_value (v, j);
1644 if (G_VALUE_HOLDS_STRING (ve) && (str = g_value_get_string (ve))) {
1645 if (strcmp (str, "adts") == 0)
1646 contains_adts = TRUE;
1647 else if (strcmp (str, "raw") == 0)
1648 contains_raw = TRUE;
1652 if (contains_adts || contains_raw) {
1653 GValue va = G_VALUE_INIT;
1654 GValue vs = G_VALUE_INIT;
1656 g_value_init (&va, GST_TYPE_LIST);
1657 g_value_init (&vs, G_TYPE_STRING);
1658 g_value_copy (v, &va);
1660 if (!contains_raw) {
1661 g_value_set_string (&vs, "raw");
1662 gst_value_list_append_value (&va, &vs);
1664 if (!contains_adts) {
1665 g_value_set_string (&vs, "adts");
1666 gst_value_list_append_value (&va, &vs);
1669 gst_structure_set_value (s, "stream-format", &va);
1671 g_value_unset (&vs);
1672 g_value_unset (&va);
1680 gst_aac_parse_sink_getcaps (GstBaseParse * parse, GstCaps * filter)
1682 GstCaps *peercaps, *templ;
1685 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1688 GstCaps *fcopy = gst_caps_copy (filter);
1689 /* Remove the fields we convert */
1690 remove_fields (fcopy);
1691 add_conversion_fields (fcopy);
1692 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1693 gst_caps_unref (fcopy);
1695 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1698 peercaps = gst_caps_make_writable (peercaps);
1699 /* Remove the fields we convert */
1700 remove_fields (peercaps);
1701 add_conversion_fields (peercaps);
1703 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1704 gst_caps_unref (peercaps);
1705 gst_caps_unref (templ);
1711 GstCaps *intersection;
1714 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1715 gst_caps_unref (res);
1723 gst_aac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1725 GstAacParse *aacparse = GST_AAC_PARSE (parse);
1727 if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
1728 aacparse->last_parsed_channels = 0;
1729 aacparse->last_parsed_sample_rate = 0;
1731 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1732 GST_DEBUG ("Entering gst_aac_parse_src_event header type = %d",
1733 aacparse->header_type);
1734 if (aacparse->header_type == DSPAAC_HEADER_ADTS)
1735 return gst_aac_parse_adts_src_eventfunc (parse, event);
1737 return GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1741 #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
1743 * get_aac_parse_get_adts_framelength:
1744 * @data: #GstBufferData.
1745 * @offset: #GstBufferData offset
1747 * Implementation to get adts framelength by using first some frame.
1749 * Returns: frame size
1752 get_aac_parse_get_adts_frame_length (const unsigned char *data, gint64 offset)
1754 const gint adts_header_length_no_crc = 7;
1755 const gint adts_header_length_with_crc = 9;
1756 gint frame_size = 0;
1757 gint protection_absent;
1760 /* check of syncword */
1761 if ((data[offset + 0] != 0xff) || ((data[offset + 1] & 0xf6) != 0xf0)) {
1762 GST_ERROR ("check sync word is fail\n");
1766 /* check of protection absent */
1767 protection_absent = (data[offset + 1] & 0x01);
1769 /*check of frame length */
1771 (data[offset + 3] & 0x3) << 11 | data[offset + 4] << 3 | data[offset +
1774 /* check of header size */
1775 /* protectionAbsent is 0 if there is CRC */
1777 protection_absent ? adts_header_length_no_crc :
1778 adts_header_length_with_crc;
1779 if (head_size > frame_size) {
1780 GST_ERROR ("return frame length as 0 (frameSize %u < headSize %u)",
1781 frame_size, head_size);
1789 * gst_aac_parse_estimate_duration:
1790 * @parse: #GstBaseParse.
1792 * Implementation to get estimated total duration by using first some frame.
1794 * Returns: TRUE if we can get estimated total duraion
1797 gst_aac_parse_estimate_duration (GstBaseParse * parse)
1799 gboolean ret = FALSE;
1800 GstFlowReturn res = GST_FLOW_OK;
1801 gint64 pull_size = 0, file_size = 0, offset = 0, num_frames = 0, duration = 0;
1802 guint sample_rate_index = 0, sample_rate = 0, channel = 0;
1803 guint frame_size = 0, frame_duration_us = 0, estimated_bitrate = 0;
1804 guint lost_sync_count = 0;
1805 GstClockTime estimated_duration = GST_CLOCK_TIME_NONE;
1806 GstBuffer *buffer = NULL;
1809 GstPadMode pad_mode = GST_PAD_MODE_NONE;
1810 GstAacParse *aacparse;
1811 gint64 buffer_size = 0;
1814 aacparse = GST_AAC_PARSE (parse);
1815 GST_LOG_OBJECT (aacparse, "gst_aac_parse_estimate_duration enter");
1817 /* check baseparse define these fuction */
1818 gst_base_parse_get_pad_mode (parse, &pad_mode);
1819 if (pad_mode != GST_PAD_MODE_PULL) {
1820 GST_INFO_OBJECT (aacparse,
1821 "aac parser is not pull mode. can not estimate duration");
1825 gst_base_parse_get_upstream_size (parse, &file_size);
1827 if (file_size < ADIF_MAX_SIZE) {
1828 GST_ERROR_OBJECT (aacparse, "file size is too short");
1832 pull_size = MIN (file_size, AAC_MAX_ESTIMATE_DURATION_BUF);
1834 res = gst_pad_pull_range (parse->sinkpad, 0, pull_size, &buffer);
1835 if (res != GST_FLOW_OK) {
1836 GST_ERROR_OBJECT (aacparse, "gst_pad_pull_range failed!");
1840 gst_buffer_map (buffer, &map, GST_MAP_READ);
1842 buffer_size = map.size;
1843 if (buffer_size != pull_size) {
1844 GST_ERROR_OBJECT (aacparse,
1845 "We got different buffer_size(%" G_GINT64_FORMAT ") with pull_size(%"
1846 G_GINT64_FORMAT ").", buffer_size, pull_size);
1849 /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
1850 for (i = 0; i < buffer_size; i++) {
1851 if ((buf[i] == 0xff) && ((buf[i + 1] & 0xf6) == 0xf0)) { /* aac sync word */
1852 //guint profile = (buf[i+2] >> 6) & 0x3;
1853 sample_rate_index = (buf[i + 2] >> 2) & 0xf;
1855 gst_aac_parse_get_sample_rate_from_index (sample_rate_index);
1856 if (sample_rate == 0) {
1857 GST_WARNING_OBJECT (aacparse, "Invalid sample rate index (0)");
1860 channel = (buf[i + 2] & 0x1) << 2 | (buf[i + 3] >> 6);
1862 GST_INFO_OBJECT (aacparse, "found sync. aac fs=%d, ch=%d", sample_rate,
1865 /* count number of frames */
1866 /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
1867 //while (offset < pull_size) {
1868 while (offset < buffer_size) {
1869 frame_size = get_aac_parse_get_adts_frame_length (buf, i + offset);
1870 if (frame_size == 0) {
1871 GST_ERROR_OBJECT (aacparse,
1872 "framesize error at offset %" G_GINT64_FORMAT, offset);
1874 } else if (frame_size == -1) {
1876 lost_sync_count++; // lost sync count limmitation 2K Bytes
1877 if (lost_sync_count > (1024 * 2)) {
1878 GST_WARNING_OBJECT (aacparse,
1879 "lost_sync_count is larger than 2048");
1883 offset += frame_size;
1885 lost_sync_count = 0;
1889 /* if we can got full file, we can calculate the accurate duration */
1890 /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
1891 //if (pull_size == file_size) {
1892 if (buffer_size == file_size) {
1893 gfloat duration_for_one_frame = 0;
1894 GstClockTime calculated_duration = GST_CLOCK_TIME_NONE;
1896 GST_INFO_OBJECT (aacparse,
1897 "we got total file (%" G_GINT64_FORMAT
1898 " bytes). do not estimate but make Accurate total duration.",
1901 duration_for_one_frame =
1902 (gfloat) AAC_SAMPLE_PER_FRAME / (gfloat) sample_rate;
1903 calculated_duration =
1904 num_frames * duration_for_one_frame * 1000 * 1000 * 1000;
1906 GST_INFO_OBJECT (aacparse, "duration_for_one_frame %f ms",
1907 duration_for_one_frame);
1908 GST_INFO_OBJECT (aacparse, "calculated duration = %" GST_TIME_FORMAT,
1909 GST_TIME_ARGS (calculated_duration));
1910 /* 0 means disable estimate */
1911 gst_base_parse_set_duration (parse, GST_FORMAT_TIME,
1912 calculated_duration, 0);
1915 GST_INFO_OBJECT (aacparse,
1916 "we got %" G_GUINT64_FORMAT " bytes in total file (%"
1917 G_GINT64_FORMAT "). can not make accurate duration but Estimate.",
1918 pull_size, file_size);
1920 (1024 * 1000000ll + (sample_rate - 1)) / sample_rate;
1921 duration = num_frames * frame_duration_us;
1923 if (duration == 0) {
1924 GST_WARNING_OBJECT (aacparse, "Invalid duration");
1928 (gint) ((gfloat) (offset * 8) / (gfloat) (duration / 1000));
1930 if (estimated_bitrate == 0) {
1931 GST_WARNING_OBJECT (aacparse, "Invalid estimated_bitrate");
1934 estimated_duration =
1935 (GstClockTime) ((file_size * 8) / (estimated_bitrate * 1000)) *
1938 GST_INFO_OBJECT (aacparse, "number of frame = %" G_GINT64_FORMAT,
1940 GST_INFO_OBJECT (aacparse, "duration = %" G_GINT64_FORMAT,
1941 duration / 1000000);
1942 GST_INFO_OBJECT (aacparse, "byte = %" G_GINT64_FORMAT, offset);
1943 GST_INFO_OBJECT (aacparse, "estimated bitrate = %d bps",
1945 GST_INFO_OBJECT (aacparse, "estimated duration = %" GST_TIME_FORMAT,
1946 GST_TIME_ARGS (estimated_duration));
1948 gst_base_parse_set_average_bitrate (parse, estimated_bitrate * 1000);
1949 /* set update_interval as duration(sec)/2 */
1950 gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration,
1951 (gint) (duration / 2));
1960 gst_buffer_unmap (buffer, &map);
1961 gst_buffer_unref (buffer);
1966 /* perform seek in push based mode:
1967 find BYTE position to move to based on time and delegate to upstream
1970 gst_aac_audio_parse_do_push_seek (GstBaseParse * parse,
1971 GstPad * pad, GstEvent * event)
1973 GstAacParse *aacparse = GST_AAC_PARSE (parse);
1977 GstSeekType cur_type, stop_type;
1981 gint64 esimate_byte;
1983 gint64 upstream_total_bytes = 0;
1984 GstFormat fmt = GST_FORMAT_BYTES;
1986 GST_INFO_OBJECT (parse, "doing aac push-based seek");
1988 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1991 /* FIXME, always play to the end */
1994 /* only forward streaming and seeking is possible */
1996 goto unsupported_seek;
1999 /* handle rewind only */
2000 cur_type = GST_SEEK_TYPE_SET;
2002 stop_type = GST_SEEK_TYPE_NONE;
2004 flags |= GST_SEEK_FLAG_FLUSH;
2006 /* handle normal seek */
2007 cur_type = GST_SEEK_TYPE_SET;
2008 stop_type = GST_SEEK_TYPE_NONE;
2010 flags |= GST_SEEK_FLAG_FLUSH;
2012 esimate_byte = (cur / (1000 * 1000)) * aacparse->frame_byte;
2013 if (aacparse->sample_rate > 0)
2014 frame_dur = (aacparse->spf * 1000) / aacparse->sample_rate;
2016 goto unsupported_seek;
2018 byte_cur = esimate_byte / (frame_dur);
2020 goto unsupported_seek;
2022 GST_INFO_OBJECT (parse, "frame_byte(%d) spf(%d) rate (%d) ",
2023 aacparse->frame_byte, aacparse->spf, aacparse->sample_rate);
2024 GST_INFO_OBJECT (parse,
2025 "seek cur (%" G_GINT64_FORMAT ") = (%" GST_TIME_FORMAT ") ", cur,
2026 GST_TIME_ARGS (cur));
2027 GST_INFO_OBJECT (parse,
2028 "esimate_byte(%" G_GINT64_FORMAT ") esimate_byte (%d)", esimate_byte,
2032 /* obtain real upstream total bytes */
2033 if (!gst_pad_peer_query_duration (parse->sinkpad, fmt, &upstream_total_bytes))
2034 upstream_total_bytes = 0;
2035 GST_INFO_OBJECT (aacparse,
2036 "gst_pad_query_peer_duration -upstream_total_bytes (%" G_GUINT64_FORMAT
2037 ")", upstream_total_bytes);
2038 aacparse->file_size = upstream_total_bytes;
2040 if ((byte_cur == -1) || (byte_cur > aacparse->file_size)) {
2041 GST_INFO_OBJECT (parse,
2042 "[WEB-ERROR] seek cur (%" G_GINT64_FORMAT ") > file_size (%"
2043 G_GINT64_FORMAT ") ", cur, aacparse->file_size);
2047 GST_INFO_OBJECT (parse,
2048 "Pushing BYTE seek rate %g, " "start %" G_GINT64_FORMAT ", stop %"
2049 G_GINT64_FORMAT, rate, byte_cur, stop);
2051 if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
2052 GST_INFO_OBJECT (parse,
2053 "Requested seek time: %" GST_TIME_FORMAT ", calculated seek offset: %"
2054 G_GUINT64_FORMAT, GST_TIME_ARGS (cur), byte_cur);
2057 /* BYTE seek event */
2059 gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
2061 res = gst_pad_push_event (parse->sinkpad, event);
2069 GST_DEBUG_OBJECT (parse,
2070 "could not determine byte position to seek to, " "seek aborted.");
2076 GST_DEBUG_OBJECT (parse, "unsupported seek, seek aborted.");
2083 gst_aac_parse_adts_get_fast_frame_len (const guint8 * data)
2086 if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
2088 ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
2096 * gst_aac_parse_adts_src_eventfunc:
2097 * @parse: #GstBaseParse. #event
2099 * before baseparse handles seek event, make full amr index table.
2101 * Returns: TRUE on success.
2104 gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse, GstEvent * event)
2106 gboolean handled = FALSE;
2107 GstAacParse *aacparse = GST_AAC_PARSE (parse);
2109 switch (GST_EVENT_TYPE (event)) {
2110 case GST_EVENT_SEEK:
2112 GstFlowReturn res = GST_FLOW_OK;
2113 gint64 base_offset = 0, cur = 0;
2114 gint32 frame_count = 1; /* do not add first frame because it is already in index table */
2115 gint64 second_count = 0; /* initial 1 second */
2116 gint64 total_file_size = 0, start_offset = 0;
2117 GstClockTime current_ts = GST_CLOCK_TIME_NONE;
2118 GstPadMode pad_mode = GST_PAD_MODE_NONE;
2120 /* check baseparse define these fuction */
2121 gst_base_parse_get_pad_mode (parse, &pad_mode);
2122 if (pad_mode != GST_PAD_MODE_PULL) {
2123 gboolean ret = FALSE;
2124 GstPad *srcpad = parse->srcpad;
2125 GST_INFO_OBJECT (aacparse, "aac parser is PUSH MODE.");
2127 ret = gst_aac_audio_parse_do_push_seek (parse, srcpad, event);
2128 gst_object_unref (srcpad);
2131 gst_base_parse_get_upstream_size (parse, &total_file_size);
2132 gst_base_parse_get_index_last_offset (parse, &start_offset);
2133 gst_base_parse_get_index_last_ts (parse, ¤t_ts);
2135 if (total_file_size > AAC_LARGE_FILE_SIZE) {
2136 gst_base_parse_set_seek_mode (parse, 0);
2137 GST_INFO_OBJECT (aacparse, "larger than big size (2MB).");
2138 goto aac_seek_null_exit;
2141 GST_DEBUG ("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK enter");
2143 if (total_file_size == 0 || start_offset >= total_file_size) {
2144 GST_ERROR ("last index offset %" G_GINT64_FORMAT
2145 " is larger than file size %" G_GINT64_FORMAT, start_offset,
2150 gst_event_parse_seek (event, NULL, NULL, NULL, NULL, &cur, NULL, NULL);
2151 if (cur <= current_ts) {
2152 GST_INFO ("seek to %" GST_TIME_FORMAT " within index table %"
2153 GST_TIME_FORMAT ". do not make index table", GST_TIME_ARGS (cur),
2154 GST_TIME_ARGS (current_ts));
2157 GST_INFO ("seek to %" GST_TIME_FORMAT " without index table %"
2158 GST_TIME_FORMAT ". make index table", GST_TIME_ARGS (cur),
2159 GST_TIME_ARGS (current_ts));
2162 GST_INFO ("make AAC(ADTS) Index Table. file_size = %" G_GINT64_FORMAT
2163 " last idx offset=%" G_GINT64_FORMAT ", last idx ts=%"
2164 GST_TIME_FORMAT, total_file_size, start_offset,
2165 GST_TIME_ARGS (current_ts));
2167 base_offset = start_offset; /* set base by start offset */
2168 second_count = current_ts + GST_SECOND; /* 1sec */
2170 /************************************/
2171 /* STEP 0: Setting parse information */
2172 /************************************/
2173 aacparse->spf = aacparse->frame_samples;
2174 aacparse->frame_duration = (aacparse->spf * 1000 * 100) / aacparse->sample_rate; /* duration per frame (msec) */
2175 aacparse->frame_per_sec = (aacparse->sample_rate) / aacparse->spf; /* frames per second (ea) */
2177 /************************************/
2178 /* STEP 1: MAX_PULL_RANGE_BUF cycle */
2179 /************************************/
2180 while (total_file_size - base_offset >= AAC_MAX_PULL_RANGE_BUF) {
2182 GstBuffer *buffer = NULL;
2185 GST_INFO ("gst_pad_pull_range %d bytes (from %" G_GINT64_FORMAT
2186 ") use max size", AAC_MAX_PULL_RANGE_BUF, base_offset);
2188 gst_pad_pull_range (parse->sinkpad, base_offset,
2189 base_offset + AAC_MAX_PULL_RANGE_BUF, &buffer);
2190 if (res != GST_FLOW_OK) {
2191 GST_ERROR ("gst_pad_pull_range failed!");
2195 gst_buffer_map (buffer, &map, GST_MAP_READ);
2198 gst_buffer_unmap (buffer, &map);
2199 GST_WARNING ("buffer is NULL in make aac seek table's STEP1");
2200 gst_buffer_unref (buffer);
2201 goto aac_seek_null_exit;
2204 while (offset <= AAC_MAX_PULL_RANGE_BUF) {
2205 gint frame_size = 0;
2207 /* make sure the values in the frame header look sane */
2208 frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
2210 if ((frame_size > 0)
2211 && (frame_size < (AAC_MAX_PULL_RANGE_BUF - offset))) {
2212 if (current_ts > second_count) { /* 1 sec == xx frames. we make idx per sec */
2213 gst_base_parse_add_index_entry (parse, base_offset + offset, current_ts, TRUE, TRUE); /* force */
2214 GST_DEBUG ("Adding index ts=%" GST_TIME_FORMAT " offset %"
2215 G_GINT64_FORMAT, GST_TIME_ARGS (current_ts),
2216 base_offset + offset);
2217 second_count += GST_SECOND; /* 1sec */
2220 current_ts += (aacparse->frame_duration * GST_MSECOND) / 100; /* each frame is (frame_duration) ms */
2221 offset += frame_size;
2224 } else if (frame_size >= (AAC_MAX_PULL_RANGE_BUF - offset)) {
2225 GST_DEBUG ("we need refill buffer");
2228 GST_WARNING ("we lost sync");
2234 base_offset = base_offset + offset;
2236 gst_buffer_unmap (buffer, &map);
2237 gst_buffer_unref (buffer);
2238 } /* end MAX buffer cycle */
2240 /*******************************/
2241 /* STEP 2: Remain Buffer cycle */
2242 /*******************************/
2243 if (total_file_size - base_offset > 0) {
2245 GstBuffer *buffer = NULL;
2249 GST_INFO ("gst_pad_pull_range %" G_GINT64_FORMAT " bytes (from %"
2250 G_GINT64_FORMAT ") use remain_buf size",
2251 total_file_size - base_offset, base_offset);
2253 gst_pad_pull_range (parse->sinkpad, base_offset, total_file_size,
2255 if (res != GST_FLOW_OK) {
2256 GST_ERROR ("gst_pad_pull_range failed!");
2260 gst_buffer_map (buffer, &map, GST_MAP_READ);
2263 gst_buffer_unmap (buffer, &map);
2264 GST_WARNING ("buffer is NULL in make aac seek table's STEP2");
2265 gst_buffer_unref (buffer);
2266 goto aac_seek_null_exit;
2269 while (base_offset + offset < total_file_size) {
2270 gint frame_size = 0;
2272 /* make sure the values in the frame header look sane */
2273 frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
2275 if ((frame_size > 0)
2276 && (frame_size <= (total_file_size - (base_offset + offset)))) {
2277 if (current_ts > second_count) { /* 1 sec == xx frames. we make idx per sec */
2278 gst_base_parse_add_index_entry (parse, base_offset + offset, current_ts, TRUE, TRUE); /* force */
2279 GST_DEBUG ("Adding index ts=%" GST_TIME_FORMAT " offset %"
2280 G_GINT64_FORMAT, GST_TIME_ARGS (current_ts),
2281 base_offset + offset);
2282 second_count += GST_SECOND; /* 1sec */
2285 current_ts += (aacparse->frame_duration * GST_MSECOND) / 100; /* each frame is (frame_duration) ms */
2286 offset += frame_size;
2289 } else if (frame_size == 0) {
2290 GST_DEBUG ("Frame size is 0 so, Decoding end..");
2293 GST_WARNING ("we lost sync");
2299 gst_buffer_unmap (buffer, &map);
2300 gst_buffer_unref (buffer);
2302 /* end remain_buf buffer cycle */
2303 GST_DEBUG ("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK leave");
2313 /* call baseparse src_event function to handle event */
2314 handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2317 #endif /* TIZEN_FEATURE_AACPARSE_MODIFICATION */