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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, 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 filesrc location=abc.aac ! aacparse ! faad ! audioresample ! audioconvert ! alsasink
47 #include "gstaacparse.h"
50 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
53 GST_STATIC_CAPS ("audio/mpeg, "
54 "framed = (boolean) true, " "mpegversion = (int) { 2, 4 }, "
55 "stream-format = (string) { raw, adts, adif };"));
57 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
60 GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) { 2, 4 };"));
62 GST_DEBUG_CATEGORY_STATIC (aacparse_debug);
63 #define GST_CAT_DEFAULT aacparse_debug
66 #define ADIF_MAX_SIZE 40 /* Should be enough */
67 #define ADTS_MAX_SIZE 10 /* Should be enough */
69 #ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more accurate duration */
70 #define AAC_MAX_ESTIMATE_DURATION_BUF (1024 * 1024) /* use first 1 Mbyte */
71 #define AAC_SAMPLE_PER_FRAME 1024
74 #define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
76 static gboolean gst_aac_parse_start (GstBaseParse * parse);
77 static gboolean gst_aac_parse_stop (GstBaseParse * parse);
79 static gboolean gst_aac_parse_sink_setcaps (GstBaseParse * parse,
81 static GstCaps *gst_aac_parse_sink_getcaps (GstBaseParse * parse);
83 static gboolean gst_aac_parse_check_valid_frame (GstBaseParse * parse,
84 GstBaseParseFrame * frame, guint * size, gint * skipsize);
86 static GstFlowReturn gst_aac_parse_parse_frame (GstBaseParse * parse,
87 GstBaseParseFrame * frame);
89 #define _do_init(bla) \
90 GST_DEBUG_CATEGORY_INIT (aacparse_debug, "aacparse", 0, \
91 "AAC audio stream parser");
93 GST_BOILERPLATE_FULL (GstAacParse, gst_aac_parse, GstBaseParse,
94 GST_TYPE_BASE_PARSE, _do_init);
97 gst_aac_parse_get_sample_rate_from_index (guint sr_idx)
99 static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
100 32000, 24000, 22050, 16000, 12000, 11025, 8000
103 if (sr_idx < G_N_ELEMENTS (aac_sample_rates))
104 return aac_sample_rates[sr_idx];
105 GST_WARNING ("Invalid sample rate index %u", sr_idx);
110 * gst_aac_parse_base_init:
111 * @klass: #GstElementClass.
115 gst_aac_parse_base_init (gpointer klass)
117 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
119 gst_element_class_add_static_pad_template (element_class,
121 gst_element_class_add_static_pad_template (element_class, &src_template);
123 gst_element_class_set_details_simple (element_class,
124 "AAC audio stream parser", "Codec/Parser/Audio",
125 "Advanced Audio Coding parser", "Stefan Kost <stefan.kost@nokia.com>");
130 * gst_aac_parse_class_init:
131 * @klass: #GstAacParseClass.
135 gst_aac_parse_class_init (GstAacParseClass * klass)
137 GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
139 parse_class->start = GST_DEBUG_FUNCPTR (gst_aac_parse_start);
140 parse_class->stop = GST_DEBUG_FUNCPTR (gst_aac_parse_stop);
141 parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_setcaps);
142 parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_getcaps);
143 parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_parse_frame);
144 parse_class->check_valid_frame =
145 GST_DEBUG_FUNCPTR (gst_aac_parse_check_valid_frame);
150 * gst_aac_parse_init:
151 * @aacparse: #GstAacParse.
152 * @klass: #GstAacParseClass.
156 gst_aac_parse_init (GstAacParse * aacparse, GstAacParseClass * klass)
158 GST_DEBUG ("initialized");
159 #ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
160 aacparse->first_frame = TRUE;
166 * gst_aac_parse_set_src_caps:
167 * @aacparse: #GstAacParse.
168 * @sink_caps: (proposed) caps of sink pad
170 * Set source pad caps according to current knowledge about the
173 * Returns: TRUE if caps were successfully set.
176 gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
179 GstCaps *src_caps = NULL;
180 gboolean res = FALSE;
181 const gchar *stream_format;
183 GST_DEBUG_OBJECT (aacparse, "sink caps: %" GST_PTR_FORMAT, sink_caps);
185 src_caps = gst_caps_copy (sink_caps);
187 src_caps = gst_caps_new_simple ("audio/mpeg", NULL);
189 gst_caps_set_simple (src_caps, "framed", G_TYPE_BOOLEAN, TRUE,
190 "mpegversion", G_TYPE_INT, aacparse->mpegversion, NULL);
192 switch (aacparse->header_type) {
193 case DSPAAC_HEADER_NONE:
194 stream_format = "raw";
196 case DSPAAC_HEADER_ADTS:
197 stream_format = "adts";
199 case DSPAAC_HEADER_ADIF:
200 stream_format = "adif";
203 stream_format = NULL;
206 s = gst_caps_get_structure (src_caps, 0);
207 if (aacparse->sample_rate > 0)
208 gst_structure_set (s, "rate", G_TYPE_INT, aacparse->sample_rate, NULL);
209 if (aacparse->channels > 0)
210 gst_structure_set (s, "channels", G_TYPE_INT, aacparse->channels, NULL);
212 gst_structure_set (s, "stream-format", G_TYPE_STRING, stream_format, NULL);
214 GST_DEBUG_OBJECT (aacparse, "setting src caps: %" GST_PTR_FORMAT, src_caps);
216 res = gst_pad_set_caps (GST_BASE_PARSE (aacparse)->srcpad, src_caps);
217 gst_caps_unref (src_caps);
223 * gst_aac_parse_sink_setcaps:
227 * Implementation of "set_sink_caps" vmethod in #GstBaseParse class.
229 * Returns: TRUE on success.
232 gst_aac_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
234 GstAacParse *aacparse;
235 GstStructure *structure;
239 aacparse = GST_AAC_PARSE (parse);
240 structure = gst_caps_get_structure (caps, 0);
241 caps_str = gst_caps_to_string (caps);
243 GST_DEBUG_OBJECT (aacparse, "setcaps: %s", caps_str);
246 /* This is needed at least in case of RTP
247 * Parses the codec_data information to get ObjectType,
248 * number of channels and samplerate */
249 value = gst_structure_get_value (structure, "codec_data");
251 GstBuffer *buf = gst_value_get_buffer (value);
254 const guint8 *buffer = GST_BUFFER_DATA (buf);
257 sr_idx = ((buffer[0] & 0x07) << 1) | ((buffer[1] & 0x80) >> 7);
258 aacparse->object_type = (buffer[0] & 0xf8) >> 3;
259 aacparse->sample_rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
260 aacparse->channels = (buffer[1] & 0x78) >> 3;
261 aacparse->header_type = DSPAAC_HEADER_NONE;
262 aacparse->mpegversion = 4;
263 aacparse->frame_samples = (buffer[1] & 4) ? 960 : 1024;
265 GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d, "
266 "samples=%d", aacparse->object_type, aacparse->sample_rate,
267 aacparse->channels, aacparse->frame_samples);
269 /* arrange for metadata and get out of the way */
270 gst_aac_parse_set_src_caps (aacparse, caps);
271 gst_base_parse_set_passthrough (parse, TRUE);
275 /* caps info overrides */
276 gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
277 gst_structure_get_int (structure, "channels", &aacparse->channels);
279 gst_base_parse_set_passthrough (parse, FALSE);
287 * gst_aac_parse_adts_get_frame_len:
288 * @data: block of data containing an ADTS header.
290 * This function calculates ADTS frame length from the given header.
292 * Returns: size of the ADTS frame.
295 gst_aac_parse_adts_get_frame_len (const guint8 * data)
297 return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
302 * gst_aac_parse_check_adts_frame:
303 * @aacparse: #GstAacParse.
304 * @data: Data to be checked.
305 * @avail: Amount of data passed.
306 * @framesize: If valid ADTS frame was found, this will be set to tell the
307 * found frame size in bytes.
308 * @needed_data: If frame was not found, this may be set to tell how much
309 * more data is needed in the next round to detect the frame
310 * reliably. This may happen when a frame header candidate
311 * is found but it cannot be guaranteed to be the header without
312 * peeking the following data.
314 * Check if the given data contains contains ADTS frame. The algorithm
315 * will examine ADTS frame header and calculate the frame size. Also, another
316 * consecutive ADTS frame header need to be present after the found frame.
317 * Otherwise the data is not considered as a valid ADTS frame. However, this
318 * "extra check" is omitted when EOS has been received. In this case it is
319 * enough when data[0] contains a valid ADTS header.
321 * This function may set the #needed_data to indicate that a possible frame
322 * candidate has been found, but more data (#needed_data bytes) is needed to
323 * be absolutely sure. When this situation occurs, FALSE will be returned.
325 * When a valid frame is detected, this function will use
326 * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
327 * to set the needed bytes for next frame.This way next data chunk is already
330 * Returns: TRUE if the given data contains a valid ADTS header.
333 gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
334 const guint8 * data, const guint avail, gboolean drain,
335 guint * framesize, guint * needed_data)
337 if (G_UNLIKELY (avail < 2))
340 if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
341 *framesize = gst_aac_parse_adts_get_frame_len (data);
343 /* In EOS mode this is enough. No need to examine the data further.
344 We also relax the check when we have sync, on the assumption that
345 if we're not looking at random data, we have a much higher chance
346 to get the correct sync, and this avoids losing two frames when
347 a single bit corruption happens. */
348 if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
352 if (*framesize + ADTS_MAX_SIZE > avail) {
353 /* We have found a possible frame header candidate, but can't be
354 sure since we don't have enough data to check the next frame */
355 GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
356 *framesize + ADTS_MAX_SIZE, avail);
357 *needed_data = *framesize + ADTS_MAX_SIZE;
358 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
359 *framesize + ADTS_MAX_SIZE);
363 if ((data[*framesize] == 0xff) && ((data[*framesize + 1] & 0xf6) == 0xf0)) {
364 guint nextlen = gst_aac_parse_adts_get_frame_len (data + (*framesize));
366 GST_LOG ("ADTS frame found, len: %d bytes", *framesize);
367 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
368 nextlen + ADTS_MAX_SIZE);
375 /* caller ensure sufficient data */
377 gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
378 gint * rate, gint * channels, gint * object, gint * version)
382 gint sr_idx = (data[2] & 0x3c) >> 2;
384 *rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
387 *channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
390 *version = (data[1] & 0x08) ? 2 : 4;
392 *object = (data[2] & 0xc0) >> 6;
396 * gst_aac_parse_detect_stream:
397 * @aacparse: #GstAacParse.
398 * @data: A block of data that needs to be examined for stream characteristics.
399 * @avail: Size of the given datablock.
400 * @framesize: If valid stream was found, this will be set to tell the
401 * first frame size in bytes.
402 * @skipsize: If valid stream was found, this will be set to tell the first
403 * audio frame position within the given data.
405 * Examines the given piece of data and try to detect the format of it. It
406 * checks for "ADIF" header (in the beginning of the clip) and ADTS frame
407 * header. If the stream is detected, TRUE will be returned and #framesize
408 * is set to indicate the found frame size. Additionally, #skipsize might
409 * be set to indicate the number of bytes that need to be skipped, a.k.a. the
410 * position of the frame inside given data chunk.
412 * Returns: TRUE on success.
415 gst_aac_parse_detect_stream (GstAacParse * aacparse,
416 const guint8 * data, const guint avail, gboolean drain,
417 guint * framesize, gint * skipsize)
419 gboolean found = FALSE;
423 GST_DEBUG_OBJECT (aacparse, "Parsing header data");
425 /* FIXME: No need to check for ADIF if we are not in the beginning of the
428 /* Can we even parse the header? */
429 if (avail < ADTS_MAX_SIZE)
432 for (i = 0; i < avail - 4; i++) {
433 if (((data[i] == 0xff) && ((data[i + 1] & 0xf6) == 0xf0)) ||
434 strncmp ((char *) data + i, "ADIF", 4) == 0) {
438 /* Trick: tell the parent class that we didn't find the frame yet,
439 but make it skip 'i' amount of bytes. Next time we arrive
440 here we have full frame in the beginning of the data. */
453 if (gst_aac_parse_check_adts_frame (aacparse, data, avail, drain,
454 framesize, &need_data)) {
457 GST_INFO ("ADTS ID: %d, framesize: %d", (data[1] & 0x08) >> 3, *framesize);
459 aacparse->header_type = DSPAAC_HEADER_ADTS;
460 gst_aac_parse_parse_adts_header (aacparse, data, &rate, &channels,
461 &aacparse->object_type, &aacparse->mpegversion);
463 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
464 aacparse->frame_samples, 2, 2);
466 GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
467 rate, channels, aacparse->object_type, aacparse->mpegversion);
469 gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
472 } else if (need_data) {
473 /* This tells the parent class not to skip any data */
478 if (avail < ADIF_MAX_SIZE)
481 if (memcmp (data + i, "ADIF", 4) == 0) {
487 aacparse->header_type = DSPAAC_HEADER_ADIF;
488 aacparse->mpegversion = 4;
490 /* Skip the "ADIF" bytes */
493 /* copyright string */
495 skip_size += 9; /* skip 9 bytes */
497 bitstream_type = adif[0 + skip_size] & 0x10;
499 ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
500 ((unsigned int) adif[1 + skip_size] << 11) |
501 ((unsigned int) adif[2 + skip_size] << 3) |
502 ((unsigned int) adif[3 + skip_size] & 0xe0);
505 if (bitstream_type == 0) {
507 /* Buffer fullness parsing. Currently not needed... */
511 num_elems = (adif[3 + skip_size] & 0x1e);
512 GST_INFO ("ADIF num_config_elems: %d", num_elems);
514 fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) |
515 ((unsigned int) adif[4 + skip_size] << 11) |
516 ((unsigned int) adif[5 + skip_size] << 3) |
517 ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5);
519 GST_INFO ("ADIF buffer fullness: %d", fullness);
521 aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) |
522 ((adif[7 + skip_size] & 0x80) >> 7);
523 sr_idx = (adif[7 + skip_size] & 0x78) >> 3;
527 aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3;
528 sr_idx = ((adif[4 + skip_size] & 0x07) << 1) |
529 ((adif[5 + skip_size] & 0x80) >> 7);
532 /* FIXME: This gives totally wrong results. Duration calculation cannot
534 aacparse->sample_rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
536 /* baseparse is not given any fps,
537 * so it will give up on timestamps, seeking, etc */
539 /* FIXME: Can we assume this? */
540 aacparse->channels = 2;
542 GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d",
543 aacparse->bitrate, aacparse->sample_rate, aacparse->object_type);
545 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 512);
547 /* arrange for metadata and get out of the way */
548 gst_aac_parse_set_src_caps (aacparse,
549 GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
551 /* not syncable, not easily seekable (unless we push data from start */
552 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
553 gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), TRUE);
554 gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), 0);
560 /* This should never happen */
566 * gst_aac_parse_check_valid_frame:
567 * @parse: #GstBaseParse.
568 * @buffer: #GstBuffer.
569 * @framesize: If the buffer contains a valid frame, its size will be put here
570 * @skipsize: How much data parent class should skip in order to find the
573 * Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
575 * Returns: TRUE if buffer contains a valid frame.
578 gst_aac_parse_check_valid_frame (GstBaseParse * parse,
579 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
582 GstAacParse *aacparse;
583 gboolean ret = FALSE;
587 aacparse = GST_AAC_PARSE (parse);
588 buffer = frame->buffer;
589 data = GST_BUFFER_DATA (buffer);
591 lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
593 if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
594 aacparse->header_type == DSPAAC_HEADER_NONE) {
595 /* There is nothing to parse */
596 *framesize = GST_BUFFER_SIZE (buffer);
599 } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
601 ret = gst_aac_parse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
602 GST_BASE_PARSE_DRAINING (parse), framesize, skipsize);
604 } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
605 guint needed_data = 1024;
607 ret = gst_aac_parse_check_adts_frame (aacparse, data,
608 GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_DRAINING (parse),
609 framesize, &needed_data);
612 GST_DEBUG ("buffer didn't contain valid frame");
613 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
618 GST_DEBUG ("buffer didn't contain valid frame");
619 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
627 #ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
629 * get_aac_parse_get_adts_framelength:
630 * @data: #GstBufferData.
631 * @offset: #GstBufferData offset
633 * Implementation to get adts framelength by using first some frame.
635 * Returns: frame size
637 int get_aac_parse_get_adts_frame_length (const unsigned char* data, gint64 offset)
639 const gint adts_header_length_no_crc = 7;
640 const gint adts_header_length_with_crc = 9;
642 gint protection_absent;
645 /* check of syncword */
646 if ((data[offset+0] != 0xff) || ((data[offset+1] & 0xf6) != 0xf0)) {
650 /* check of protection absent */
651 protection_absent = (data[offset+1] & 0x01);
653 /*check of frame length */
654 frame_size = (data[offset+3] & 0x3) << 11 | data[offset+4] << 3 | data[offset+5] >> 5;
656 /* check of header size */
657 /* protectionAbsent is 0 if there is CRC */
658 head_size = protection_absent ? adts_header_length_no_crc : adts_header_length_with_crc;
659 if (head_size > frame_size) {
660 GST_ERROR("return frame length as 0 (frameSize %u < headSize %u)", frame_size, head_size);
668 * gst_aac_parse_estimate_duration:
669 * @parse: #GstBaseParse.
671 * Implementation to get estimated total duration by using first some frame.
673 * Returns: TRUE if we can get estimated total duraion
676 gst_aac_parse_estimate_duration (GstBaseParse * parse)
678 GstFlowReturn res = GST_FLOW_OK;
679 gint64 pull_size = 0, file_size = 0, offset = 0, num_frames=0, duration=0;
680 guint profile = 0, sample_rate_index = 0, sample_rate = 0, channel = 0;
681 guint frame_size = 0, frame_duration_us = 0, estimated_bitrate = 0;
682 GstClockTime estimated_duration = GST_CLOCK_TIME_NONE;
683 GstBuffer *buffer = NULL;
686 GstActivateMode pad_mode = GST_ACTIVATE_NONE;
687 GstAacParse *aacparse;
689 aacparse = GST_AAC_PARSE (parse);
690 GST_LOG_OBJECT (aacparse, "gst_aac_parse_estimate_duration enter");
692 #ifdef GST_EXT_BASEPARSER_MODIFICATION /* check baseparse define these fuction */
693 gst_base_parse_get_pad_mode(parse, &pad_mode);
694 if (pad_mode != GST_ACTIVATE_PULL) {
695 GST_INFO_OBJECT (aacparse, "aac parser is not pull mode. can not estimate duration");
699 gst_base_parse_get_upstream_size (parse, &file_size);
701 GST_WARNING_OBJECT (aacparse, "baseparser does not define get private param functions");
705 if (file_size < ADIF_MAX_SIZE) {
706 GST_ERROR_OBJECT (aacparse, "file size is too short");
710 pull_size = MIN(file_size, AAC_MAX_ESTIMATE_DURATION_BUF);
712 res = gst_pad_pull_range (parse->sinkpad, 0, pull_size, &buffer);
713 if (res != GST_FLOW_OK) {
714 GST_ERROR_OBJECT (aacparse, "gst_pad_pull_range failed!");
718 buf = GST_BUFFER_DATA(buffer);
720 for (i = 0; i < pull_size; i ++) {
721 if ((buf[i] == 0xff) && ((buf[i+1] & 0xf6) == 0xf0)) { /* aac sync word */
722 profile = (buf[i+2] >> 6) & 0x3;
723 sample_rate_index = (buf[i+2] >> 2) & 0xf;
724 sample_rate = gst_aac_parse_get_sample_rate_from_index(sample_rate_index);
725 channel = (buf[i+2] & 0x1) << 2 | (buf[i+3] >> 6);
727 GST_INFO_OBJECT (aacparse, "found sync. aac sample_rate=%d, channel=%d", sample_rate, channel);
729 /* count number of frames */
730 while (offset < pull_size) {
731 if ((frame_size = get_aac_parse_get_adts_frame_length(buf, i + offset)) == 0) {
732 GST_ERROR_OBJECT (aacparse, "framesize error at offset %"G_GINT64_FORMAT, offset);
735 offset += frame_size;
739 /* if we can got full file, we can calculate the accurate duration */
740 if (pull_size == file_size) {
741 gfloat duration_for_one_frame = 0;
742 GstClockTime calculated_duration = GST_CLOCK_TIME_NONE;
744 GST_INFO_OBJECT (aacparse, "we got total file (%d bytes). do not estimate but make Accurate total duration.", pull_size);
746 duration_for_one_frame = (gfloat)AAC_SAMPLE_PER_FRAME / (gfloat)sample_rate;
747 calculated_duration = num_frames * duration_for_one_frame * 1000 * 1000 * 1000;
749 GST_INFO_OBJECT (aacparse, "duration_for_one_frame %f ms", duration_for_one_frame);
750 GST_INFO_OBJECT (aacparse, "calculated duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(calculated_duration));
751 gst_base_parse_set_duration (parse, GST_FORMAT_TIME, calculated_duration, 0); /* 0 means disable estimate */
754 GST_INFO_OBJECT (aacparse, "we got %d bytes in total file (%"G_GINT64_FORMAT
755 "). can not make accurate duration but Estimate.", pull_size, file_size);
756 frame_duration_us = (1024 * 1000000ll + (sample_rate - 1)) / sample_rate;
757 duration = num_frames * frame_duration_us;
759 estimated_bitrate = (gint)((gfloat)(offset * 8) / (gfloat)(duration / 1000));
760 estimated_duration = (GstClockTime)((file_size * 8) / (estimated_bitrate * 1000)) * GST_SECOND;
762 GST_INFO_OBJECT (aacparse, "number of frame = %"G_GINT64_FORMAT, num_frames);
763 GST_INFO_OBJECT (aacparse, "duration = %"G_GINT64_FORMAT, duration / 1000000);
764 GST_INFO_OBJECT (aacparse, "byte = %"G_GINT64_FORMAT, offset);
765 GST_INFO_OBJECT (aacparse, "estimated bitrate = %d bps", estimated_bitrate);
766 GST_INFO_OBJECT (aacparse, "estimated duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(estimated_duration));
768 gst_base_parse_set_average_bitrate (parse, estimated_bitrate * 1000);
769 /* set update_interval as duration(sec)/2 */
770 gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration, (gint)(duration/2));
777 gst_buffer_unref (buffer);
784 * gst_aac_parse_parse_frame:
785 * @parse: #GstBaseParse.
786 * @buffer: #GstBuffer.
788 * Implementation of "parse_frame" vmethod in #GstBaseParse class.
790 * Also determines frame overhead.
791 * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
792 * a per-frame header.
794 * We're making a couple of simplifying assumptions:
796 * 1. We count Program Configuration Elements rather than searching for them
797 * in the streams to discount them - the overhead is negligible.
799 * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16
800 * bits, which should still not be significant enough to warrant the
801 * additional parsing through the headers
803 * Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed
804 * forward. Otherwise appropriate error is returned.
807 gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
809 GstAacParse *aacparse;
811 GstFlowReturn ret = GST_FLOW_OK;
814 aacparse = GST_AAC_PARSE (parse);
815 buffer = frame->buffer;
817 if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
823 gst_aac_parse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
824 &rate, &channels, NULL, NULL);
825 GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
827 if (G_UNLIKELY (rate != aacparse->sample_rate
828 || channels != aacparse->channels)) {
829 aacparse->sample_rate = rate;
830 aacparse->channels = channels;
832 if (!gst_aac_parse_set_src_caps (aacparse,
833 GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
834 /* If linking fails, we need to return appropriate error */
835 ret = GST_FLOW_NOT_LINKED;
838 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
839 aacparse->sample_rate, aacparse->frame_samples, 2, 2);
842 #ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
843 if (aacparse->first_frame == TRUE) {
844 gboolean ret = FALSE;
845 aacparse->first_frame = FALSE;
847 ret = gst_aac_parse_estimate_duration(parse);
849 GST_WARNING_OBJECT (aacparse, "can not estimate total duration");
859 * gst_aac_parse_start:
860 * @parse: #GstBaseParse.
862 * Implementation of "start" vmethod in #GstBaseParse class.
864 * Returns: TRUE if startup succeeded.
867 gst_aac_parse_start (GstBaseParse * parse)
869 GstAacParse *aacparse;
871 aacparse = GST_AAC_PARSE (parse);
873 aacparse->frame_samples = 1024;
874 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), ADTS_MAX_SIZE);
880 * gst_aac_parse_stop:
881 * @parse: #GstBaseParse.
883 * Implementation of "stop" vmethod in #GstBaseParse class.
885 * Returns: TRUE is stopping succeeded.
888 gst_aac_parse_stop (GstBaseParse * parse)
895 gst_aac_parse_sink_getcaps (GstBaseParse * parse)
900 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
904 /* Remove the framed field */
905 peercaps = gst_caps_make_writable (peercaps);
906 n = gst_caps_get_size (peercaps);
907 for (i = 0; i < n; i++) {
908 GstStructure *s = gst_caps_get_structure (peercaps, i);
910 gst_structure_remove_field (s, "framed");
914 gst_caps_intersect_full (peercaps,
915 gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
916 GST_CAPS_INTERSECT_FIRST);
917 gst_caps_unref (peercaps);
920 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD