summaryrefslogtreecommitdiff
path: root/mobile/gst/audioparsers/gstaacparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/gst/audioparsers/gstaacparse.c')
-rw-r--r--mobile/gst/audioparsers/gstaacparse.c925
1 files changed, 0 insertions, 925 deletions
diff --git a/mobile/gst/audioparsers/gstaacparse.c b/mobile/gst/audioparsers/gstaacparse.c
deleted file mode 100644
index b1dca6c..0000000
--- a/mobile/gst/audioparsers/gstaacparse.c
+++ /dev/null
@@ -1,925 +0,0 @@
-/* GStreamer AAC parser plugin
- * Copyright (C) 2008 Nokia Corporation. All rights reserved.
- *
- * Contact: Stefan Kost <stefan.kost@nokia.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-aacparse
- * @short_description: AAC parser
- * @see_also: #GstAmrParse
- *
- * This is an AAC parser which handles both ADIF and ADTS stream formats.
- *
- * As ADIF format is not framed, it is not seekable and stream duration cannot
- * be determined either. However, ADTS format AAC clips can be seeked, and parser
- * can also estimate playback position and clip duration.
- *
- * <refsect2>
- * <title>Example launch line</title>
- * |[
- * gst-launch filesrc location=abc.aac ! aacparse ! faad ! audioresample ! audioconvert ! alsasink
- * ]|
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "gstaacparse.h"
-
-
-static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/mpeg, "
- "framed = (boolean) true, " "mpegversion = (int) { 2, 4 }, "
- "stream-format = (string) { raw, adts, adif };"));
-
-static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) { 2, 4 };"));
-
-GST_DEBUG_CATEGORY_STATIC (aacparse_debug);
-#define GST_CAT_DEFAULT aacparse_debug
-
-
-#define ADIF_MAX_SIZE 40 /* Should be enough */
-#define ADTS_MAX_SIZE 10 /* Should be enough */
-
-#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more accurate duration */
-#define AAC_MAX_ESTIMATE_DURATION_BUF (1024 * 1024) /* use first 1 Mbyte */
-#define AAC_SAMPLE_PER_FRAME 1024
-#endif
-
-#define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
-
-static gboolean gst_aac_parse_start (GstBaseParse * parse);
-static gboolean gst_aac_parse_stop (GstBaseParse * parse);
-
-static gboolean gst_aac_parse_sink_setcaps (GstBaseParse * parse,
- GstCaps * caps);
-static GstCaps *gst_aac_parse_sink_getcaps (GstBaseParse * parse);
-
-static gboolean gst_aac_parse_check_valid_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame, guint * size, gint * skipsize);
-
-static GstFlowReturn gst_aac_parse_parse_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame);
-
-#define _do_init(bla) \
- GST_DEBUG_CATEGORY_INIT (aacparse_debug, "aacparse", 0, \
- "AAC audio stream parser");
-
-GST_BOILERPLATE_FULL (GstAacParse, gst_aac_parse, GstBaseParse,
- GST_TYPE_BASE_PARSE, _do_init);
-
-static inline gint
-gst_aac_parse_get_sample_rate_from_index (guint sr_idx)
-{
- static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
- 32000, 24000, 22050, 16000, 12000, 11025, 8000
- };
-
- if (sr_idx < G_N_ELEMENTS (aac_sample_rates))
- return aac_sample_rates[sr_idx];
- GST_WARNING ("Invalid sample rate index %u", sr_idx);
- return 0;
-}
-
-/**
- * gst_aac_parse_base_init:
- * @klass: #GstElementClass.
- *
- */
-static void
-gst_aac_parse_base_init (gpointer klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_add_static_pad_template (element_class,
- &sink_template);
- gst_element_class_add_static_pad_template (element_class, &src_template);
-
- gst_element_class_set_details_simple (element_class,
- "AAC audio stream parser", "Codec/Parser/Audio",
- "Advanced Audio Coding parser", "Stefan Kost <stefan.kost@nokia.com>");
-}
-
-
-/**
- * gst_aac_parse_class_init:
- * @klass: #GstAacParseClass.
- *
- */
-static void
-gst_aac_parse_class_init (GstAacParseClass * klass)
-{
- GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
-
- parse_class->start = GST_DEBUG_FUNCPTR (gst_aac_parse_start);
- parse_class->stop = GST_DEBUG_FUNCPTR (gst_aac_parse_stop);
- parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_setcaps);
- parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_getcaps);
- parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_parse_frame);
- parse_class->check_valid_frame =
- GST_DEBUG_FUNCPTR (gst_aac_parse_check_valid_frame);
-}
-
-
-/**
- * gst_aac_parse_init:
- * @aacparse: #GstAacParse.
- * @klass: #GstAacParseClass.
- *
- */
-static void
-gst_aac_parse_init (GstAacParse * aacparse, GstAacParseClass * klass)
-{
- GST_DEBUG ("initialized");
-#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
- aacparse->first_frame = TRUE;
-#endif
-}
-
-
-/**
- * gst_aac_parse_set_src_caps:
- * @aacparse: #GstAacParse.
- * @sink_caps: (proposed) caps of sink pad
- *
- * Set source pad caps according to current knowledge about the
- * audio stream.
- *
- * Returns: TRUE if caps were successfully set.
- */
-static gboolean
-gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
-{
- GstStructure *s;
- GstCaps *src_caps = NULL;
- gboolean res = FALSE;
- const gchar *stream_format;
-
- GST_DEBUG_OBJECT (aacparse, "sink caps: %" GST_PTR_FORMAT, sink_caps);
- if (sink_caps)
- src_caps = gst_caps_copy (sink_caps);
- else
- src_caps = gst_caps_new_simple ("audio/mpeg", NULL);
-
- gst_caps_set_simple (src_caps, "framed", G_TYPE_BOOLEAN, TRUE,
- "mpegversion", G_TYPE_INT, aacparse->mpegversion, NULL);
-
- switch (aacparse->header_type) {
- case DSPAAC_HEADER_NONE:
- stream_format = "raw";
- break;
- case DSPAAC_HEADER_ADTS:
- stream_format = "adts";
- break;
- case DSPAAC_HEADER_ADIF:
- stream_format = "adif";
- break;
- default:
- stream_format = NULL;
- }
-
- s = gst_caps_get_structure (src_caps, 0);
- if (aacparse->sample_rate > 0)
- gst_structure_set (s, "rate", G_TYPE_INT, aacparse->sample_rate, NULL);
- if (aacparse->channels > 0)
- gst_structure_set (s, "channels", G_TYPE_INT, aacparse->channels, NULL);
- if (stream_format)
- gst_structure_set (s, "stream-format", G_TYPE_STRING, stream_format, NULL);
-
- GST_DEBUG_OBJECT (aacparse, "setting src caps: %" GST_PTR_FORMAT, src_caps);
-
- res = gst_pad_set_caps (GST_BASE_PARSE (aacparse)->srcpad, src_caps);
- gst_caps_unref (src_caps);
- return res;
-}
-
-
-/**
- * gst_aac_parse_sink_setcaps:
- * @sinkpad: GstPad
- * @caps: GstCaps
- *
- * Implementation of "set_sink_caps" vmethod in #GstBaseParse class.
- *
- * Returns: TRUE on success.
- */
-static gboolean
-gst_aac_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
-{
- GstAacParse *aacparse;
- GstStructure *structure;
- gchar *caps_str;
- const GValue *value;
-
- aacparse = GST_AAC_PARSE (parse);
- structure = gst_caps_get_structure (caps, 0);
- caps_str = gst_caps_to_string (caps);
-
- GST_DEBUG_OBJECT (aacparse, "setcaps: %s", caps_str);
- g_free (caps_str);
-
- /* This is needed at least in case of RTP
- * Parses the codec_data information to get ObjectType,
- * number of channels and samplerate */
- value = gst_structure_get_value (structure, "codec_data");
- if (value) {
- GstBuffer *buf = gst_value_get_buffer (value);
-
- if (buf) {
- const guint8 *buffer = GST_BUFFER_DATA (buf);
- guint sr_idx;
-
- sr_idx = ((buffer[0] & 0x07) << 1) | ((buffer[1] & 0x80) >> 7);
- aacparse->object_type = (buffer[0] & 0xf8) >> 3;
- aacparse->sample_rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
- aacparse->channels = (buffer[1] & 0x78) >> 3;
- aacparse->header_type = DSPAAC_HEADER_NONE;
- aacparse->mpegversion = 4;
- aacparse->frame_samples = (buffer[1] & 4) ? 960 : 1024;
-
- GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d, "
- "samples=%d", aacparse->object_type, aacparse->sample_rate,
- aacparse->channels, aacparse->frame_samples);
-
- /* arrange for metadata and get out of the way */
- gst_aac_parse_set_src_caps (aacparse, caps);
- gst_base_parse_set_passthrough (parse, TRUE);
- } else
- return FALSE;
-
- /* caps info overrides */
- gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
- gst_structure_get_int (structure, "channels", &aacparse->channels);
- } else {
- gst_base_parse_set_passthrough (parse, FALSE);
- }
-
- return TRUE;
-}
-
-
-/**
- * gst_aac_parse_adts_get_frame_len:
- * @data: block of data containing an ADTS header.
- *
- * This function calculates ADTS frame length from the given header.
- *
- * Returns: size of the ADTS frame.
- */
-static inline guint
-gst_aac_parse_adts_get_frame_len (const guint8 * data)
-{
- return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
-}
-
-
-/**
- * gst_aac_parse_check_adts_frame:
- * @aacparse: #GstAacParse.
- * @data: Data to be checked.
- * @avail: Amount of data passed.
- * @framesize: If valid ADTS frame was found, this will be set to tell the
- * found frame size in bytes.
- * @needed_data: If frame was not found, this may be set to tell how much
- * more data is needed in the next round to detect the frame
- * reliably. This may happen when a frame header candidate
- * is found but it cannot be guaranteed to be the header without
- * peeking the following data.
- *
- * Check if the given data contains contains ADTS frame. The algorithm
- * will examine ADTS frame header and calculate the frame size. Also, another
- * consecutive ADTS frame header need to be present after the found frame.
- * Otherwise the data is not considered as a valid ADTS frame. However, this
- * "extra check" is omitted when EOS has been received. In this case it is
- * enough when data[0] contains a valid ADTS header.
- *
- * This function may set the #needed_data to indicate that a possible frame
- * candidate has been found, but more data (#needed_data bytes) is needed to
- * be absolutely sure. When this situation occurs, FALSE will be returned.
- *
- * When a valid frame is detected, this function will use
- * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
- * to set the needed bytes for next frame.This way next data chunk is already
- * of correct size.
- *
- * Returns: TRUE if the given data contains a valid ADTS header.
- */
-static gboolean
-gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
- const guint8 * data, const guint avail, gboolean drain,
- guint * framesize, guint * needed_data)
-{
- if (G_UNLIKELY (avail < 2))
- return FALSE;
-
- if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
- *framesize = gst_aac_parse_adts_get_frame_len (data);
-
- /* In EOS mode this is enough. No need to examine the data further.
- We also relax the check when we have sync, on the assumption that
- if we're not looking at random data, we have a much higher chance
- to get the correct sync, and this avoids losing two frames when
- a single bit corruption happens. */
- if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
- return TRUE;
- }
-
- if (*framesize + ADTS_MAX_SIZE > avail) {
- /* We have found a possible frame header candidate, but can't be
- sure since we don't have enough data to check the next frame */
- GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
- *framesize + ADTS_MAX_SIZE, avail);
- *needed_data = *framesize + ADTS_MAX_SIZE;
- gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
- *framesize + ADTS_MAX_SIZE);
- return FALSE;
- }
-
- if ((data[*framesize] == 0xff) && ((data[*framesize + 1] & 0xf6) == 0xf0)) {
- guint nextlen = gst_aac_parse_adts_get_frame_len (data + (*framesize));
-
- GST_LOG ("ADTS frame found, len: %d bytes", *framesize);
- gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
- nextlen + ADTS_MAX_SIZE);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/* caller ensure sufficient data */
-static inline void
-gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
- gint * rate, gint * channels, gint * object, gint * version)
-{
-
- if (rate) {
- gint sr_idx = (data[2] & 0x3c) >> 2;
-
- *rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
- }
- if (channels)
- *channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
-
- if (version)
- *version = (data[1] & 0x08) ? 2 : 4;
- if (object)
- *object = (data[2] & 0xc0) >> 6;
-}
-
-/**
- * gst_aac_parse_detect_stream:
- * @aacparse: #GstAacParse.
- * @data: A block of data that needs to be examined for stream characteristics.
- * @avail: Size of the given datablock.
- * @framesize: If valid stream was found, this will be set to tell the
- * first frame size in bytes.
- * @skipsize: If valid stream was found, this will be set to tell the first
- * audio frame position within the given data.
- *
- * Examines the given piece of data and try to detect the format of it. It
- * checks for "ADIF" header (in the beginning of the clip) and ADTS frame
- * header. If the stream is detected, TRUE will be returned and #framesize
- * is set to indicate the found frame size. Additionally, #skipsize might
- * be set to indicate the number of bytes that need to be skipped, a.k.a. the
- * position of the frame inside given data chunk.
- *
- * Returns: TRUE on success.
- */
-static gboolean
-gst_aac_parse_detect_stream (GstAacParse * aacparse,
- const guint8 * data, const guint avail, gboolean drain,
- guint * framesize, gint * skipsize)
-{
- gboolean found = FALSE;
- guint need_data = 0;
- guint i = 0;
-
- GST_DEBUG_OBJECT (aacparse, "Parsing header data");
-
- /* FIXME: No need to check for ADIF if we are not in the beginning of the
- stream */
-
- /* Can we even parse the header? */
- if (avail < ADTS_MAX_SIZE)
- return FALSE;
-
- for (i = 0; i < avail - 4; i++) {
- if (((data[i] == 0xff) && ((data[i + 1] & 0xf6) == 0xf0)) ||
- strncmp ((char *) data + i, "ADIF", 4) == 0) {
- found = TRUE;
-
- if (i) {
- /* Trick: tell the parent class that we didn't find the frame yet,
- but make it skip 'i' amount of bytes. Next time we arrive
- here we have full frame in the beginning of the data. */
- *skipsize = i;
- return FALSE;
- }
- break;
- }
- }
- if (!found) {
- if (i)
- *skipsize = i;
- return FALSE;
- }
-
- if (gst_aac_parse_check_adts_frame (aacparse, data, avail, drain,
- framesize, &need_data)) {
- gint rate, channels;
-
- GST_INFO ("ADTS ID: %d, framesize: %d", (data[1] & 0x08) >> 3, *framesize);
-
- aacparse->header_type = DSPAAC_HEADER_ADTS;
- gst_aac_parse_parse_adts_header (aacparse, data, &rate, &channels,
- &aacparse->object_type, &aacparse->mpegversion);
-
- gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
- aacparse->frame_samples, 2, 2);
-
- GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
- rate, channels, aacparse->object_type, aacparse->mpegversion);
-
- gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
-
- return TRUE;
- } else if (need_data) {
- /* This tells the parent class not to skip any data */
- *skipsize = 0;
- return FALSE;
- }
-
- if (avail < ADIF_MAX_SIZE)
- return FALSE;
-
- if (memcmp (data + i, "ADIF", 4) == 0) {
- const guint8 *adif;
- int skip_size = 0;
- int bitstream_type;
- int sr_idx;
-
- aacparse->header_type = DSPAAC_HEADER_ADIF;
- aacparse->mpegversion = 4;
-
- /* Skip the "ADIF" bytes */
- adif = data + i + 4;
-
- /* copyright string */
- if (adif[0] & 0x80)
- skip_size += 9; /* skip 9 bytes */
-
- bitstream_type = adif[0 + skip_size] & 0x10;
- aacparse->bitrate =
- ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
- ((unsigned int) adif[1 + skip_size] << 11) |
- ((unsigned int) adif[2 + skip_size] << 3) |
- ((unsigned int) adif[3 + skip_size] & 0xe0);
-
- /* CBR */
- if (bitstream_type == 0) {
-#if 0
- /* Buffer fullness parsing. Currently not needed... */
- guint num_elems = 0;
- guint fullness = 0;
-
- num_elems = (adif[3 + skip_size] & 0x1e);
- GST_INFO ("ADIF num_config_elems: %d", num_elems);
-
- fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) |
- ((unsigned int) adif[4 + skip_size] << 11) |
- ((unsigned int) adif[5 + skip_size] << 3) |
- ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5);
-
- GST_INFO ("ADIF buffer fullness: %d", fullness);
-#endif
- aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) |
- ((adif[7 + skip_size] & 0x80) >> 7);
- sr_idx = (adif[7 + skip_size] & 0x78) >> 3;
- }
- /* VBR */
- else {
- aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3;
- sr_idx = ((adif[4 + skip_size] & 0x07) << 1) |
- ((adif[5 + skip_size] & 0x80) >> 7);
- }
-
- /* FIXME: This gives totally wrong results. Duration calculation cannot
- be based on this */
- aacparse->sample_rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
-
- /* baseparse is not given any fps,
- * so it will give up on timestamps, seeking, etc */
-
- /* FIXME: Can we assume this? */
- aacparse->channels = 2;
-
- GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d",
- aacparse->bitrate, aacparse->sample_rate, aacparse->object_type);
-
- gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 512);
-
- /* arrange for metadata and get out of the way */
- gst_aac_parse_set_src_caps (aacparse,
- GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
-
- /* not syncable, not easily seekable (unless we push data from start */
- gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
- gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), TRUE);
- gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), 0);
-
- *framesize = avail;
- return TRUE;
- }
-
- /* This should never happen */
- return FALSE;
-}
-
-
-/**
- * gst_aac_parse_check_valid_frame:
- * @parse: #GstBaseParse.
- * @buffer: #GstBuffer.
- * @framesize: If the buffer contains a valid frame, its size will be put here
- * @skipsize: How much data parent class should skip in order to find the
- * frame header.
- *
- * Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
- *
- * Returns: TRUE if buffer contains a valid frame.
- */
-static gboolean
-gst_aac_parse_check_valid_frame (GstBaseParse * parse,
- GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
-{
- const guint8 *data;
- GstAacParse *aacparse;
- gboolean ret = FALSE;
- gboolean lost_sync;
- GstBuffer *buffer;
-
- aacparse = GST_AAC_PARSE (parse);
- buffer = frame->buffer;
- data = GST_BUFFER_DATA (buffer);
-
- lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
-
- if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
- aacparse->header_type == DSPAAC_HEADER_NONE) {
- /* There is nothing to parse */
- *framesize = GST_BUFFER_SIZE (buffer);
- ret = TRUE;
-
- } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
-
- ret = gst_aac_parse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
- GST_BASE_PARSE_DRAINING (parse), framesize, skipsize);
-
- } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
- guint needed_data = 1024;
-
- ret = gst_aac_parse_check_adts_frame (aacparse, data,
- GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_DRAINING (parse),
- framesize, &needed_data);
-
- if (!ret) {
- GST_DEBUG ("buffer didn't contain valid frame");
- gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
- needed_data);
- }
-
- } else {
- GST_DEBUG ("buffer didn't contain valid frame");
- gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
- ADTS_MAX_SIZE);
- }
-
- return ret;
-}
-
-
-#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
-/**
- * get_aac_parse_get_adts_framelength:
- * @data: #GstBufferData.
- * @offset: #GstBufferData offset
- *
- * Implementation to get adts framelength by using first some frame.
- *
- * Returns: frame size
- */
-int get_aac_parse_get_adts_frame_length (const unsigned char* data, gint64 offset)
-{
- const gint adts_header_length_no_crc = 7;
- const gint adts_header_length_with_crc = 9;
- gint frame_size = 0;
- gint protection_absent;
- gint head_size;
-
- /* check of syncword */
- if ((data[offset+0] != 0xff) || ((data[offset+1] & 0xf6) != 0xf0)) {
- return 0;
- }
-
- /* check of protection absent */
- protection_absent = (data[offset+1] & 0x01);
-
- /*check of frame length */
- frame_size = (data[offset+3] & 0x3) << 11 | data[offset+4] << 3 | data[offset+5] >> 5;
-
- /* check of header size */
- /* protectionAbsent is 0 if there is CRC */
- head_size = protection_absent ? adts_header_length_no_crc : adts_header_length_with_crc;
- if (head_size > frame_size) {
- GST_ERROR("return frame length as 0 (frameSize %u < headSize %u)", frame_size, head_size);
- return 0;
- }
-
- return frame_size;
-}
-
-/**
- * gst_aac_parse_estimate_duration:
- * @parse: #GstBaseParse.
- *
- * Implementation to get estimated total duration by using first some frame.
- *
- * Returns: TRUE if we can get estimated total duraion
- */
-static gboolean
-gst_aac_parse_estimate_duration (GstBaseParse * parse)
-{
- GstFlowReturn res = GST_FLOW_OK;
- gint64 pull_size = 0, file_size = 0, offset = 0, num_frames=0, duration=0;
- guint profile = 0, sample_rate_index = 0, sample_rate = 0, channel = 0;
- guint frame_size = 0, frame_duration_us = 0, estimated_bitrate = 0;
- GstClockTime estimated_duration = GST_CLOCK_TIME_NONE;
- GstBuffer *buffer = NULL;
- guint8 *buf = NULL;
- gint i = 0;
- GstActivateMode pad_mode = GST_ACTIVATE_NONE;
- GstAacParse *aacparse;
-
- aacparse = GST_AAC_PARSE (parse);
- GST_LOG_OBJECT (aacparse, "gst_aac_parse_estimate_duration enter");
-
-#ifdef GST_EXT_BASEPARSER_MODIFICATION /* check baseparse define these fuction */
- gst_base_parse_get_pad_mode(parse, &pad_mode);
- if (pad_mode != GST_ACTIVATE_PULL) {
- GST_INFO_OBJECT (aacparse, "aac parser is not pull mode. can not estimate duration");
- return FALSE;
- }
-
- gst_base_parse_get_upstream_size (parse, &file_size);
-#else
- GST_WARNING_OBJECT (aacparse, "baseparser does not define get private param functions");
- return FALSE;
-#endif
-
- if (file_size < ADIF_MAX_SIZE) {
- GST_ERROR_OBJECT (aacparse, "file size is too short");
- return FALSE;
- }
-
- pull_size = MIN(file_size, AAC_MAX_ESTIMATE_DURATION_BUF);
-
- res = gst_pad_pull_range (parse->sinkpad, 0, pull_size, &buffer);
- if (res != GST_FLOW_OK) {
- GST_ERROR_OBJECT (aacparse, "gst_pad_pull_range failed!");
- return FALSE;
- }
-
- buf = GST_BUFFER_DATA(buffer);
-
- for (i = 0; i < pull_size; i ++) {
- if ((buf[i] == 0xff) && ((buf[i+1] & 0xf6) == 0xf0)) { /* aac sync word */
- profile = (buf[i+2] >> 6) & 0x3;
- sample_rate_index = (buf[i+2] >> 2) & 0xf;
- sample_rate = gst_aac_parse_get_sample_rate_from_index(sample_rate_index);
- channel = (buf[i+2] & 0x1) << 2 | (buf[i+3] >> 6);
-
- GST_INFO_OBJECT (aacparse, "found sync. aac sample_rate=%d, channel=%d", sample_rate, channel);
-
- /* count number of frames */
- while (offset < pull_size) {
- if ((frame_size = get_aac_parse_get_adts_frame_length(buf, i + offset)) == 0) {
- GST_ERROR_OBJECT (aacparse, "framesize error at offset %"G_GINT64_FORMAT, offset);
- break;
- }
- offset += frame_size;
- num_frames++;
- } /* while */
-
- /* if we can got full file, we can calculate the accurate duration */
- if (pull_size == file_size) {
- gfloat duration_for_one_frame = 0;
- GstClockTime calculated_duration = GST_CLOCK_TIME_NONE;
-
- GST_INFO_OBJECT (aacparse, "we got total file (%d bytes). do not estimate but make Accurate total duration.", pull_size);
-
- duration_for_one_frame = (gfloat)AAC_SAMPLE_PER_FRAME / (gfloat)sample_rate;
- calculated_duration = num_frames * duration_for_one_frame * 1000 * 1000 * 1000;
-
- GST_INFO_OBJECT (aacparse, "duration_for_one_frame %f ms", duration_for_one_frame);
- GST_INFO_OBJECT (aacparse, "calculated duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(calculated_duration));
- gst_base_parse_set_duration (parse, GST_FORMAT_TIME, calculated_duration, 0); /* 0 means disable estimate */
-
- } else {
- GST_INFO_OBJECT (aacparse, "we got %d bytes in total file (%"G_GINT64_FORMAT
- "). can not make accurate duration but Estimate.", pull_size, file_size);
- frame_duration_us = (1024 * 1000000ll + (sample_rate - 1)) / sample_rate;
- duration = num_frames * frame_duration_us;
-
- estimated_bitrate = (gint)((gfloat)(offset * 8) / (gfloat)(duration / 1000));
- estimated_duration = (GstClockTime)((file_size * 8) / (estimated_bitrate * 1000)) * GST_SECOND;
-
- GST_INFO_OBJECT (aacparse, "number of frame = %"G_GINT64_FORMAT, num_frames);
- GST_INFO_OBJECT (aacparse, "duration = %"G_GINT64_FORMAT, duration / 1000000);
- GST_INFO_OBJECT (aacparse, "byte = %"G_GINT64_FORMAT, offset);
- GST_INFO_OBJECT (aacparse, "estimated bitrate = %d bps", estimated_bitrate);
- GST_INFO_OBJECT (aacparse, "estimated duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(estimated_duration));
-
- gst_base_parse_set_average_bitrate (parse, estimated_bitrate * 1000);
- /* set update_interval as duration(sec)/2 */
- gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration, (gint)(duration/2));
- }
-
- break;
- }
- }
-
- gst_buffer_unref (buffer);
- return TRUE;
-}
-#endif
-
-
-/**
- * gst_aac_parse_parse_frame:
- * @parse: #GstBaseParse.
- * @buffer: #GstBuffer.
- *
- * Implementation of "parse_frame" vmethod in #GstBaseParse class.
- *
- * Also determines frame overhead.
- * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
- * a per-frame header.
- *
- * We're making a couple of simplifying assumptions:
- *
- * 1. We count Program Configuration Elements rather than searching for them
- * in the streams to discount them - the overhead is negligible.
- *
- * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16
- * bits, which should still not be significant enough to warrant the
- * additional parsing through the headers
- *
- * Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed
- * forward. Otherwise appropriate error is returned.
- */
-static GstFlowReturn
-gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
-{
- GstAacParse *aacparse;
- GstBuffer *buffer;
- GstFlowReturn ret = GST_FLOW_OK;
- gint rate, channels;
-
- aacparse = GST_AAC_PARSE (parse);
- buffer = frame->buffer;
-
- if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
- return ret;
-
- /* see above */
- frame->overhead = 7;
-
- gst_aac_parse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
- &rate, &channels, NULL, NULL);
- GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
-
- if (G_UNLIKELY (rate != aacparse->sample_rate
- || channels != aacparse->channels)) {
- aacparse->sample_rate = rate;
- aacparse->channels = channels;
-
- if (!gst_aac_parse_set_src_caps (aacparse,
- GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
- /* If linking fails, we need to return appropriate error */
- ret = GST_FLOW_NOT_LINKED;
- }
-
- gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
- aacparse->sample_rate, aacparse->frame_samples, 2, 2);
- }
-
-#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
- if (aacparse->first_frame == TRUE) {
- gboolean ret = FALSE;
- aacparse->first_frame = FALSE;
-
- ret = gst_aac_parse_estimate_duration(parse);
- if (!ret) {
- GST_WARNING_OBJECT (aacparse, "can not estimate total duration");
- }
- }
-#endif
-
- return ret;
-}
-
-
-/**
- * gst_aac_parse_start:
- * @parse: #GstBaseParse.
- *
- * Implementation of "start" vmethod in #GstBaseParse class.
- *
- * Returns: TRUE if startup succeeded.
- */
-static gboolean
-gst_aac_parse_start (GstBaseParse * parse)
-{
- GstAacParse *aacparse;
-
- aacparse = GST_AAC_PARSE (parse);
- GST_DEBUG ("start");
- aacparse->frame_samples = 1024;
- gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), ADTS_MAX_SIZE);
- return TRUE;
-}
-
-
-/**
- * gst_aac_parse_stop:
- * @parse: #GstBaseParse.
- *
- * Implementation of "stop" vmethod in #GstBaseParse class.
- *
- * Returns: TRUE is stopping succeeded.
- */
-static gboolean
-gst_aac_parse_stop (GstBaseParse * parse)
-{
- GST_DEBUG ("stop");
- return TRUE;
-}
-
-static GstCaps *
-gst_aac_parse_sink_getcaps (GstBaseParse * parse)
-{
- GstCaps *peercaps;
- GstCaps *res;
-
- peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
- if (peercaps) {
- guint i, n;
-
- /* Remove the framed field */
- peercaps = gst_caps_make_writable (peercaps);
- n = gst_caps_get_size (peercaps);
- for (i = 0; i < n; i++) {
- GstStructure *s = gst_caps_get_structure (peercaps, i);
-
- gst_structure_remove_field (s, "framed");
- }
-
- res =
- gst_caps_intersect_full (peercaps,
- gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
- GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (peercaps);
- } else {
- res =
- gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD
- (parse)));
- }
-
- return res;
-}