mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 17:18:15 +00:00
Remove audioparsers plugin, it has been moved to -good
This commit is contained in:
parent
a7cbd201b1
commit
9bfac61f97
29 changed files with 3 additions and 6841 deletions
|
@ -49,6 +49,7 @@ CRUFT_FILES = \
|
|||
$(top_builddir)/ext/jack/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/gst/aacparse/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/gst/amrparse/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/gst/audioparsers/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/gst/flacparse/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/gst/imagefreeze/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/gst/selector/.libs/*.{so,dll,DLL,dylib} \
|
||||
|
@ -56,6 +57,7 @@ CRUFT_FILES = \
|
|||
$(top_builddir)/gst/valve/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/gst/videoparsers/.libs/libgsth263parse* \
|
||||
$(top_builddir)/sys/oss4/.libs/*.{so,dll,DLL,dylib} \
|
||||
$(top_builddir)/tests/check/elements/{aac,ac3,amr,flac,mpegaudio,dca}parse \
|
||||
$(top_builddir)/tests/check/elements/autocolorspace \
|
||||
$(top_builddir)/tests/check/elements/capssetter \
|
||||
$(top_builddir)/tests/check/elements/imagefreeze \
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
||||
aacparse_LOCAL_SRC_FILES:= \
|
||||
gst/aacparse/gstaacparse.c \
|
||||
gst/aacparse/gstbaseparse.c
|
||||
|
||||
LOCAL_SRC_FILES:= $(addprefix ../,$(aacparse_LOCAL_SRC_FILES))
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libgstreamer-0.10 \
|
||||
libgstbase-0.10 \
|
||||
libglib-2.0 \
|
||||
libgthread-2.0 \
|
||||
libgmodule-2.0 \
|
||||
libgobject-2.0 \
|
||||
libgstinterfaces-0.10
|
||||
|
||||
LOCAL_MODULE:= libgstaacparse
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/.. \
|
||||
$(LOCAL_PATH)/../gst-libs \
|
||||
$(LOCAL_PATH) \
|
||||
$(TARGET_OUT_HEADERS)/gstreamer-0.10 \
|
||||
$(TARGET_OUT_HEADERS)/glib-2.0 \
|
||||
$(TARGET_OUT_HEADERS)/glib-2.0/glib \
|
||||
external/libxml2/include
|
||||
|
||||
ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
|
||||
LOCAL_SHARED_LIBRARIES += libicuuc
|
||||
LOCAL_C_INCLUDES += external/icu4c/common
|
||||
endif
|
||||
|
||||
|
||||
LOCAL_CFLAGS := -DHAVE_CONFIG_H
|
||||
#
|
||||
# define LOCAL_PRELINK_MODULE to false to not use pre-link map
|
||||
#
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.10
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -1,48 +0,0 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
||||
amrparse_LOCAL_SRC_FILES:= \
|
||||
gst/amrparse/gstamrparse.c \
|
||||
gst/amrparse/gstbaseparse.c
|
||||
|
||||
LOCAL_SRC_FILES:= $(addprefix ../,$(amrparse_LOCAL_SRC_FILES))
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libgstreamer-0.10 \
|
||||
libgstbase-0.10 \
|
||||
libglib-2.0 \
|
||||
libgthread-2.0 \
|
||||
libgmodule-2.0 \
|
||||
libgobject-2.0
|
||||
|
||||
LOCAL_MODULE:= libgstamrparse
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/../ext/amrwbenc \
|
||||
$(LOCAL_PATH)/.. \
|
||||
$(LOCAL_PATH)/../gst-libs \
|
||||
$(LOCAL_PATH) \
|
||||
$(TARGET_OUT_HEADERS)/gstreamer-0.10 \
|
||||
$(TARGET_OUT_HEADERS)/glib-2.0 \
|
||||
$(TARGET_OUT_HEADERS)/glib-2.0/glib \
|
||||
external/libxml2/include
|
||||
|
||||
ifeq ($(STECONF_ANDROID_VERSION),"FROYO")
|
||||
LOCAL_SHARED_LIBRARIES += libicuuc
|
||||
LOCAL_C_INCLUDES += external/icu4c/common
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS := -DHAVE_CONFIG_H
|
||||
#
|
||||
# define LOCAL_PRELINK_MODULE to false to not use pre-link map
|
||||
#
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
#It's a gstreamer plugins, and it must be installed on ..../lib/gstreamer-0.10
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
|
@ -291,7 +291,6 @@ AG_GST_CHECK_PLUGIN(adpcmdec)
|
|||
AG_GST_CHECK_PLUGIN(adpcmenc)
|
||||
AG_GST_CHECK_PLUGIN(aiff)
|
||||
AG_GST_CHECK_PLUGIN(asfmux)
|
||||
AG_GST_CHECK_PLUGIN(audioparsers)
|
||||
AG_GST_CHECK_PLUGIN(autoconvert)
|
||||
AG_GST_CHECK_PLUGIN(bayer)
|
||||
AG_GST_CHECK_PLUGIN(camerabin)
|
||||
|
@ -1742,7 +1741,6 @@ gst/adpcmdec/Makefile
|
|||
gst/adpcmenc/Makefile
|
||||
gst/aiff/Makefile
|
||||
gst/asfmux/Makefile
|
||||
gst/audioparsers/Makefile
|
||||
gst/autoconvert/Makefile
|
||||
gst/bayer/Makefile
|
||||
gst/camerabin/Makefile
|
||||
|
|
|
@ -136,12 +136,6 @@ EXTRA_HFILES = \
|
|||
$(top_srcdir)/ext/zbar/gstzbar.h \
|
||||
$(top_srcdir)/gst/aiff/aiffparse.h \
|
||||
$(top_srcdir)/gst/aiff/aiffmux.h \
|
||||
$(top_srcdir)/gst/audioparsers/gstaacparse.h \
|
||||
$(top_srcdir)/gst/audioparsers/gstac3parse.h \
|
||||
$(top_srcdir)/gst/audioparsers/gstamrparse.h \
|
||||
$(top_srcdir)/gst/audioparsers/gstflacparse.h \
|
||||
$(top_srcdir)/gst/audioparsers/gstdcaparse.h \
|
||||
$(top_srcdir)/gst/audioparsers/gstmpegaudioparse.h \
|
||||
$(top_srcdir)/gst/autoconvert/gstautoconvert.h \
|
||||
$(top_srcdir)/gst/camerabin/gstcamerabin.h \
|
||||
$(top_srcdir)/gst/coloreffects/gstcoloreffects.h \
|
||||
|
|
|
@ -17,11 +17,8 @@
|
|||
|
||||
<chapter>
|
||||
<title>gst-plugins-bad Elements</title>
|
||||
<xi:include href="xml/element-aacparse.xml" />
|
||||
<xi:include href="xml/element-ac3parse.xml" />
|
||||
<xi:include href="xml/element-aiffparse.xml" />
|
||||
<xi:include href="xml/element-aiffmux.xml" />
|
||||
<xi:include href="xml/element-amrparse.xml" />
|
||||
<xi:include href="xml/element-amrwbenc.xml" />
|
||||
<xi:include href="xml/element-assrender.xml" />
|
||||
<xi:include href="xml/element-autoconvert.xml" />
|
||||
|
@ -42,7 +39,6 @@
|
|||
<xi:include href="xml/element-cvsobel.xml" />
|
||||
<xi:include href="xml/element-dataurisrc.xml" />
|
||||
<!--xi:include href="xml/element-dc1394.xml" /-->
|
||||
<xi:include href="xml/element-dcaparse.xml" />
|
||||
<xi:include href="xml/element-dccpclientsink.xml" />
|
||||
<xi:include href="xml/element-dccpclientsrc.xml" />
|
||||
<xi:include href="xml/element-dccpserversink.xml" />
|
||||
|
@ -65,7 +61,6 @@
|
|||
<xi:include href="xml/element-facedetect.xml" />
|
||||
<xi:include href="xml/element-festival.xml" />
|
||||
<xi:include href="xml/element-fisheye.xml" />
|
||||
<xi:include href="xml/element-flacparse.xml" />
|
||||
<xi:include href="xml/element-fpsdisplaysink.xml" />
|
||||
<xi:include href="xml/element-freeze.xml" />
|
||||
<xi:include href="xml/element-gaussianblur.xml" />
|
||||
|
@ -84,7 +79,6 @@
|
|||
<xi:include href="xml/element-mimdec.xml" />
|
||||
<xi:include href="xml/element-mirror.xml" />
|
||||
<xi:include href="xml/element-modplug.xml" />
|
||||
<xi:include href="xml/element-mpegaudioparse.xml" />
|
||||
<xi:include href="xml/element-mpeg2enc.xml" />
|
||||
<xi:include href="xml/element-mplex.xml" />
|
||||
<xi:include href="xml/element-mythtvsrc.xml" />
|
||||
|
@ -135,7 +129,6 @@
|
|||
<chapter>
|
||||
<title>gst-plugins-bad Plugins</title>
|
||||
<xi:include href="xml/plugin-aiff.xml" />
|
||||
<xi:include href="xml/plugin-audioparsersbad.xml" />
|
||||
<xi:include href="xml/plugin-autoconvert.xml" />
|
||||
<xi:include href="xml/plugin-legacyresample.xml" />
|
||||
<xi:include href="xml/plugin-amrwbenc.xml" />
|
||||
|
|
|
@ -1,31 +1,3 @@
|
|||
<SECTION>
|
||||
<FILE>element-aacparse</FILE>
|
||||
<TITLE>aacparse</TITLE>
|
||||
GstAacParse
|
||||
<SUBSECTION Standard>
|
||||
GstAacParseClass
|
||||
GST_AACPARSE
|
||||
GST_AACPARSE_CLASS
|
||||
GST_IS_AACPARSE
|
||||
GST_IS_AACPARSE_CLASS
|
||||
GST_TYPE_AACPARSE
|
||||
gst_aacparse_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-ac3parse</FILE>
|
||||
<TITLE>ac3parse</TITLE>
|
||||
GstAc3Parse
|
||||
<SUBSECTION Standard>
|
||||
GstAc3ParseClass
|
||||
GST_AC3_PARSE
|
||||
GST_AC3_PARSE_CLASS
|
||||
GST_IS_AC3_PARSE
|
||||
GST_IS_AC3_PARSE_CLASS
|
||||
GST_TYPE_AC3_PARSE
|
||||
gst_ac3_parse_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-aiffmux</FILE>
|
||||
<TITLE>aiffmux</TITLE>
|
||||
|
@ -55,20 +27,6 @@ GstAiffParseState
|
|||
gst_aiff_parse_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-amrparse</FILE>
|
||||
<TITLE>amrparse</TITLE>
|
||||
GstAmrParse
|
||||
<SUBSECTION Standard>
|
||||
GstAmrParseClass
|
||||
GST_AMRPARSE
|
||||
GST_AMRPARSE_CLASS
|
||||
GST_IS_AMRPARSE
|
||||
GST_IS_AMRPARSE_CLASS
|
||||
GST_TYPE_AMRPARSE
|
||||
gst_amrparse_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-amrwbenc</FILE>
|
||||
<TITLE>amrwbenc</TITLE>
|
||||
|
@ -377,20 +335,6 @@ GST_TYPE_DC1394
|
|||
gst_dc1394_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-dcaparse</FILE>
|
||||
<TITLE>dcaparse</TITLE>
|
||||
GstDCAParse
|
||||
<SUBSECTION Standard>
|
||||
GstDCAParseClass
|
||||
GST_DCA_PARSE
|
||||
GST_DCA_PARSE_CLASS
|
||||
GST_IS_DCA_PARSE
|
||||
GST_IS_DCA_PARSE_CLASS
|
||||
GST_TYPE_DCA_PARSE
|
||||
gst_dca_parse_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-dccpclientsink</FILE>
|
||||
<TITLE>dccpclientsink</TITLE>
|
||||
|
@ -751,20 +695,6 @@ gst_fisheye_get_type
|
|||
gst_fisheye_plugin_init
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-flacparse</FILE>
|
||||
<TITLE>flacparse</TITLE>
|
||||
GstFlacParse
|
||||
<SUBSECTION Standard>
|
||||
GstFlacParseClass
|
||||
GST_FLAC_PARSE
|
||||
GST_FLAC_PARSE_CLASS
|
||||
GST_IS_FLAC_PARSE
|
||||
GST_IS_FLAC_PARSE_CLASS
|
||||
GST_TYPE_FLAC_PARSE
|
||||
gst_flac_parse_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-fpsdisplaysink</FILE>
|
||||
<TITLE>fpsdisplaysink</TITLE>
|
||||
|
@ -1034,20 +964,6 @@ GST_TYPE_MODPLUG
|
|||
gst_modplug_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-mpegaudioparse</FILE>
|
||||
<TITLE>mpegaudioparse</TITLE>
|
||||
GstMpegAudioParse
|
||||
<SUBSECTION Standard>
|
||||
GstMpegAudioParseClass
|
||||
GST_MPEG_AUDIO_PARSE
|
||||
GST_MPEG_AUDIO_PARSE_CLASS
|
||||
GST_IS_MPEG_AUDIO_PARSE
|
||||
GST_IS_MPEG_AUDIO_PARSE_CLASS
|
||||
GST_TYPE_MPEG_AUDIO_PARSE
|
||||
gst_mpeg_audio_parse_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-mpeg2enc</FILE>
|
||||
<TITLE>mpeg2enc</TITLE>
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
<plugin>
|
||||
<name>audioparsersbad</name>
|
||||
<description>audioparsers</description>
|
||||
<filename>../../gst/audioparsers/.libs/libgstaudioparsersbad.so</filename>
|
||||
<basename>libgstaudioparsersbad.so</basename>
|
||||
<version>0.10.21.1</version>
|
||||
<license>LGPL</license>
|
||||
<source>gst-plugins-bad</source>
|
||||
<package>GStreamer Bad Plug-ins git</package>
|
||||
<origin>Unknown package origin</origin>
|
||||
<elements>
|
||||
<element>
|
||||
<name>aacparse</name>
|
||||
<longname>AAC audio stream parser</longname>
|
||||
<class>Codec/Parser/Audio</class>
|
||||
<description>Advanced Audio Coding parser</description>
|
||||
<author>Stefan Kost <stefan.kost@nokia.com></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink</name>
|
||||
<direction>sink</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/mpeg, framed=(boolean)false, mpegversion=(int){ 2, 4 }</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/mpeg, framed=(boolean)true, mpegversion=(int){ 2, 4 }, stream-format=(string){ raw, adts, adif }</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>ac3parse</name>
|
||||
<longname>AC3 audio stream parser</longname>
|
||||
<class>Codec/Parser/Audio</class>
|
||||
<description>AC3 parser</description>
|
||||
<author>Tim-Philipp Müller <tim centricular net></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink</name>
|
||||
<direction>sink</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/x-ac3, framed=(boolean)false; audio/x-eac3, framed=(boolean)false; audio/ac3, framed=(boolean)false</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/x-ac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]; audio/x-eac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>amrparse</name>
|
||||
<longname>AMR audio stream parser</longname>
|
||||
<class>Codec/Parser/Audio</class>
|
||||
<description>Adaptive Multi-Rate audio parser</description>
|
||||
<author>Ronald Bultje <rbultje@ronald.bitfreak.net></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink</name>
|
||||
<direction>sink</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/x-amr-nb-sh; audio/x-amr-wb-sh</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/AMR, rate=(int)8000, channels=(int)1; audio/AMR-WB, rate=(int)16000, channels=(int)1</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>dcaparse</name>
|
||||
<longname>DTS Coherent Acoustics audio stream parser</longname>
|
||||
<class>Codec/Parser/Audio</class>
|
||||
<description>DCA parser</description>
|
||||
<author>Tim-Philipp Müller <tim centricular net></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink</name>
|
||||
<direction>sink</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/x-dts, framed=(boolean)false</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/x-dts, framed=(boolean)true, channels=(int)[ 1, 8 ], rate=(int)[ 8000, 192000 ]</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>flacparse</name>
|
||||
<longname>FLAC audio parser</longname>
|
||||
<class>Codec/Parser/Audio</class>
|
||||
<description>Parses audio with the FLAC lossless audio codec</description>
|
||||
<author>Sebastian Dröge <sebastian.droege@collabora.co.uk></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink</name>
|
||||
<direction>sink</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/x-flac, framed=(boolean)false</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/x-flac, framed=(boolean)true, channels=(int)[ 1, 8 ], rate=(int)[ 1, 655350 ]</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>mpegaudioparse</name>
|
||||
<longname>MPEG1 Audio Parser</longname>
|
||||
<class>Codec/Parser/Audio</class>
|
||||
<description>Parses and frames mpeg1 audio streams (levels 1-3), provides seek</description>
|
||||
<author>Jan Schmidt <thaytan@mad.scientist.com>,Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink</name>
|
||||
<direction>sink</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/mpeg, mpegversion=(int)1, parsed=(boolean)false</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>audio/mpeg, mpegversion=(int)1, layer=(int)[ 1, 3 ], rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ], parsed=(boolean)true</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
</elements>
|
||||
</plugin>
|
|
@ -1,20 +0,0 @@
|
|||
plugin_LTLIBRARIES = libgstaudioparsersbad.la
|
||||
|
||||
libgstaudioparsersbad_la_SOURCES = \
|
||||
gstaacparse.c gstamrparse.c gstac3parse.c \
|
||||
gstdcaparse.c gstflacparse.c gstmpegaudioparse.c \
|
||||
plugin.c
|
||||
|
||||
libgstaudioparsersbad_la_CFLAGS = \
|
||||
-I$(top_srcdir)/gst-libs \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
|
||||
libgstaudioparsersbad_la_LIBADD = \
|
||||
$(top_builddir)/gst-libs/gst/baseparse/libgstbaseparse-$(GST_MAJORMINOR).la \
|
||||
$(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) \
|
||||
-lgstaudio-$(GST_MAJORMINOR) \
|
||||
$(GST_BASE_LIBS) $(GST_LIBS)
|
||||
libgstaudioparsersbad_la_LDFLAGS = $(PACKAGE_LIBS) $(GST_PLUGIN_LDFLAGS)
|
||||
libgstaudioparsersbad_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = gstaacparse.h gstamrparse.h gstac3parse.h \
|
||||
gstdcaparse.h gstflacparse.h gstmpegaudioparse.h
|
|
@ -1,715 +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, "
|
||||
"framed = (boolean) false, " "mpegversion = (int) { 2, 4 };"));
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_aacparse_debug);
|
||||
#define GST_CAT_DEFAULT gst_aacparse_debug
|
||||
|
||||
|
||||
#define ADIF_MAX_SIZE 40 /* Should be enough */
|
||||
#define ADTS_MAX_SIZE 10 /* Should be enough */
|
||||
|
||||
|
||||
#define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
|
||||
|
||||
gboolean gst_aacparse_start (GstBaseParse * parse);
|
||||
gboolean gst_aacparse_stop (GstBaseParse * parse);
|
||||
|
||||
static gboolean gst_aacparse_sink_setcaps (GstBaseParse * parse,
|
||||
GstCaps * caps);
|
||||
|
||||
gboolean gst_aacparse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
||||
|
||||
GstFlowReturn gst_aacparse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
|
||||
gboolean gst_aacparse_convert (GstBaseParse * parse,
|
||||
GstFormat src_format,
|
||||
gint64 src_value, GstFormat dest_format, gint64 * dest_value);
|
||||
|
||||
gint gst_aacparse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer);
|
||||
|
||||
gboolean gst_aacparse_event (GstBaseParse * parse, GstEvent * event);
|
||||
|
||||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_aacparse_debug, "aacparse", 0, \
|
||||
"AAC audio stream parser");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstAacParse, gst_aacparse, GstBaseParse,
|
||||
GST_TYPE_BASE_PARSE, _do_init);
|
||||
|
||||
static inline gint
|
||||
gst_aacparse_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_aacparse_base_init:
|
||||
* @klass: #GstElementClass.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
gst_aacparse_base_init (gpointer klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&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_aacparse_class_init:
|
||||
* @klass: #GstAacParseClass.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
gst_aacparse_class_init (GstAacParseClass * klass)
|
||||
{
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_aacparse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_aacparse_stop);
|
||||
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aacparse_sink_setcaps);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aacparse_parse_frame);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_aacparse_check_valid_frame);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_init:
|
||||
* @aacparse: #GstAacParse.
|
||||
* @klass: #GstAacParseClass.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
gst_aacparse_init (GstAacParse * aacparse, GstAacParseClass * klass)
|
||||
{
|
||||
GST_DEBUG ("initialized");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_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_aacparse_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_aacparse_sink_setcaps:
|
||||
* @sinkpad: GstPad
|
||||
* @caps: GstCaps
|
||||
*
|
||||
* Implementation of "set_sink_caps" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: TRUE on success.
|
||||
*/
|
||||
static gboolean
|
||||
gst_aacparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
|
||||
{
|
||||
GstAacParse *aacparse;
|
||||
GstStructure *structure;
|
||||
gchar *caps_str;
|
||||
const GValue *value;
|
||||
|
||||
aacparse = GST_AACPARSE (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_aacparse_get_sample_rate_from_index (sr_idx);
|
||||
aacparse->channels = (buffer[1] & 0x78) >> 3;
|
||||
aacparse->header_type = DSPAAC_HEADER_NONE;
|
||||
aacparse->mpegversion = 4;
|
||||
|
||||
GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d",
|
||||
aacparse->object_type, aacparse->sample_rate, aacparse->channels);
|
||||
|
||||
/* arrange for metadata and get out of the way */
|
||||
gst_aacparse_set_src_caps (aacparse, caps);
|
||||
gst_base_parse_set_format (parse,
|
||||
GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE);
|
||||
} else
|
||||
return FALSE;
|
||||
|
||||
/* caps info overrides */
|
||||
gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
|
||||
gst_structure_get_int (structure, "channels", &aacparse->channels);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_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_aacparse_adts_get_frame_len (const guint8 * data)
|
||||
{
|
||||
return ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_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_aacparse_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_aacparse_adts_get_frame_len (data);
|
||||
|
||||
/* In EOS mode this is enough. No need to examine the data further */
|
||||
if (drain) {
|
||||
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_aacparse_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_aacparse_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_aacparse_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_aacparse_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_aacparse_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_aacparse_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_aacparse_parse_adts_header (aacparse, data, &rate, &channels,
|
||||
&aacparse->object_type, &aacparse->mpegversion);
|
||||
|
||||
gst_base_parse_set_frame_props (GST_BASE_PARSE (aacparse),
|
||||
rate, 1024, 2, 2);
|
||||
|
||||
GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
|
||||
rate, channels, aacparse->object_type, aacparse->mpegversion);
|
||||
|
||||
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;
|
||||
|
||||
/* no way to seek this */
|
||||
gst_base_parse_set_seek (GST_BASE_PARSE (aacparse),
|
||||
GST_BASE_PARSE_SEEK_NONE, 0);
|
||||
|
||||
/* 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_aacparse_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_aacparse_set_src_caps (aacparse,
|
||||
GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
|
||||
gst_base_parse_set_format (GST_BASE_PARSE (aacparse),
|
||||
GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE);
|
||||
|
||||
*framesize = avail;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This should never happen */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_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.
|
||||
*/
|
||||
gboolean
|
||||
gst_aacparse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
{
|
||||
const guint8 *data;
|
||||
GstAacParse *aacparse;
|
||||
gboolean ret = FALSE;
|
||||
gboolean sync;
|
||||
GstBuffer *buffer;
|
||||
|
||||
aacparse = GST_AACPARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
data = GST_BUFFER_DATA (buffer);
|
||||
|
||||
sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
||||
|
||||
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 || sync == FALSE) {
|
||||
|
||||
ret = gst_aacparse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
|
||||
GST_BASE_PARSE_FRAME_DRAIN (frame), framesize, skipsize);
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||
guint needed_data = 1024;
|
||||
|
||||
ret = gst_aacparse_check_adts_frame (aacparse, data,
|
||||
GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_FRAME_DRAIN (frame),
|
||||
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), 1024);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_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.
|
||||
*/
|
||||
GstFlowReturn
|
||||
gst_aacparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
{
|
||||
GstAacParse *aacparse;
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gint rate, channels;
|
||||
|
||||
aacparse = GST_AACPARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
|
||||
if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
|
||||
return ret;
|
||||
|
||||
/* see above */
|
||||
frame->overhead = 7;
|
||||
|
||||
gst_aacparse_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_aacparse_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_props (GST_BASE_PARSE (aacparse),
|
||||
aacparse->sample_rate, 1024, 2, 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_start:
|
||||
* @parse: #GstBaseParse.
|
||||
*
|
||||
* Implementation of "start" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: TRUE if startup succeeded.
|
||||
*/
|
||||
gboolean
|
||||
gst_aacparse_start (GstBaseParse * parse)
|
||||
{
|
||||
GstAacParse *aacparse;
|
||||
|
||||
aacparse = GST_AACPARSE (parse);
|
||||
GST_DEBUG ("start");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 1024);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aacparse_stop:
|
||||
* @parse: #GstBaseParse.
|
||||
*
|
||||
* Implementation of "stop" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: TRUE is stopping succeeded.
|
||||
*/
|
||||
gboolean
|
||||
gst_aacparse_stop (GstBaseParse * parse)
|
||||
{
|
||||
GST_DEBUG ("stop");
|
||||
return TRUE;
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/* GStreamer AAC parser
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __GST_AACPARSE_H__
|
||||
#define __GST_AACPARSE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/baseparse/gstbaseparse.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_AACPARSE \
|
||||
(gst_aacparse_get_type())
|
||||
#define GST_AACPARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AACPARSE, GstAacParse))
|
||||
#define GST_AACPARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AACPARSE, GstAacParseClass))
|
||||
#define GST_IS_AACPARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AACPARSE))
|
||||
#define GST_IS_AACPARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AACPARSE))
|
||||
|
||||
|
||||
/**
|
||||
* GstAacHeaderType:
|
||||
* @DSPAAC_HEADER_NOT_PARSED: Header not parsed yet.
|
||||
* @DSPAAC_HEADER_UNKNOWN: Unknown (not recognized) header.
|
||||
* @DSPAAC_HEADER_ADIF: ADIF header found.
|
||||
* @DSPAAC_HEADER_ADTS: ADTS header found.
|
||||
* @DSPAAC_HEADER_NONE: Raw stream, no header.
|
||||
*
|
||||
* Type header enumeration set in #header_type.
|
||||
*/
|
||||
typedef enum {
|
||||
DSPAAC_HEADER_NOT_PARSED,
|
||||
DSPAAC_HEADER_UNKNOWN,
|
||||
DSPAAC_HEADER_ADIF,
|
||||
DSPAAC_HEADER_ADTS,
|
||||
DSPAAC_HEADER_NONE
|
||||
} GstAacHeaderType;
|
||||
|
||||
|
||||
typedef struct _GstAacParse GstAacParse;
|
||||
typedef struct _GstAacParseClass GstAacParseClass;
|
||||
|
||||
/**
|
||||
* GstAacParse:
|
||||
* @element: the parent element.
|
||||
* @object_type: AAC object type of the stream.
|
||||
* @bitrate: Current media bitrate.
|
||||
* @sample_rate: Current media samplerate.
|
||||
* @channels: Current media channel count.
|
||||
* @frames_per_sec: FPS value of the current stream.
|
||||
* @header_type: #GstAacHeaderType indicating the current stream type.
|
||||
* @framecount: The amount of frames that has been processed this far.
|
||||
* @bytecount: The amount of bytes that has been processed this far.
|
||||
* @sync: Tells whether the parser is in sync (a.k.a. not searching for header)
|
||||
* @eos: End-of-Stream indicator. Set when EOS event arrives.
|
||||
* @duration: Duration of the current stream.
|
||||
* @ts: Current stream timestamp.
|
||||
*
|
||||
* The opaque GstAacParse data structure.
|
||||
*/
|
||||
struct _GstAacParse {
|
||||
GstBaseParse element;
|
||||
|
||||
/* Stream type -related info */
|
||||
gint object_type;
|
||||
gint bitrate;
|
||||
gint sample_rate;
|
||||
gint channels;
|
||||
gint mpegversion;
|
||||
|
||||
GstAacHeaderType header_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstAacParseClass:
|
||||
* @parent_class: Element parent class.
|
||||
*
|
||||
* The opaque GstAacParseClass data structure.
|
||||
*/
|
||||
struct _GstAacParseClass {
|
||||
GstBaseParseClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_aacparse_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_AACPARSE_H__ */
|
|
@ -1,507 +0,0 @@
|
|||
/* GStreamer AC3 parser
|
||||
* Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
|
||||
* Copyright (C) 2009 Mark Nauwelaerts <mnauw users sf net>
|
||||
* Copyright (C) 2009 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-ac3parse
|
||||
* @short_description: AC3 parser
|
||||
* @see_also: #GstAmrParse, #GstAACParse
|
||||
*
|
||||
* This is an AC3 parser.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch filesrc location=abc.ac3 ! ac3parse ! a52dec ! audioresample ! audioconvert ! autoaudiosink
|
||||
* ]|
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* - add support for audio/x-private1-ac3 as well
|
||||
* - should accept framed and unframed input (needs decodebin fixes first)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gstac3parse.h"
|
||||
#include <gst/base/gstbytereader.h>
|
||||
#include <gst/base/gstbitreader.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (ac3_parse_debug);
|
||||
#define GST_CAT_DEFAULT ac3_parse_debug
|
||||
|
||||
static const struct
|
||||
{
|
||||
const guint bit_rate; /* nominal bit rate */
|
||||
const guint frame_size[3]; /* frame size for 32kHz, 44kHz, and 48kHz */
|
||||
} frmsizcod_table[38] = {
|
||||
{
|
||||
32, {
|
||||
64, 69, 96}}, {
|
||||
32, {
|
||||
64, 70, 96}}, {
|
||||
40, {
|
||||
80, 87, 120}}, {
|
||||
40, {
|
||||
80, 88, 120}}, {
|
||||
48, {
|
||||
96, 104, 144}}, {
|
||||
48, {
|
||||
96, 105, 144}}, {
|
||||
56, {
|
||||
112, 121, 168}}, {
|
||||
56, {
|
||||
112, 122, 168}}, {
|
||||
64, {
|
||||
128, 139, 192}}, {
|
||||
64, {
|
||||
128, 140, 192}}, {
|
||||
80, {
|
||||
160, 174, 240}}, {
|
||||
80, {
|
||||
160, 175, 240}}, {
|
||||
96, {
|
||||
192, 208, 288}}, {
|
||||
96, {
|
||||
192, 209, 288}}, {
|
||||
112, {
|
||||
224, 243, 336}}, {
|
||||
112, {
|
||||
224, 244, 336}}, {
|
||||
128, {
|
||||
256, 278, 384}}, {
|
||||
128, {
|
||||
256, 279, 384}}, {
|
||||
160, {
|
||||
320, 348, 480}}, {
|
||||
160, {
|
||||
320, 349, 480}}, {
|
||||
192, {
|
||||
384, 417, 576}}, {
|
||||
192, {
|
||||
384, 418, 576}}, {
|
||||
224, {
|
||||
448, 487, 672}}, {
|
||||
224, {
|
||||
448, 488, 672}}, {
|
||||
256, {
|
||||
512, 557, 768}}, {
|
||||
256, {
|
||||
512, 558, 768}}, {
|
||||
320, {
|
||||
640, 696, 960}}, {
|
||||
320, {
|
||||
640, 697, 960}}, {
|
||||
384, {
|
||||
768, 835, 1152}}, {
|
||||
384, {
|
||||
768, 836, 1152}}, {
|
||||
448, {
|
||||
896, 975, 1344}}, {
|
||||
448, {
|
||||
896, 976, 1344}}, {
|
||||
512, {
|
||||
1024, 1114, 1536}}, {
|
||||
512, {
|
||||
1024, 1115, 1536}}, {
|
||||
576, {
|
||||
1152, 1253, 1728}}, {
|
||||
576, {
|
||||
1152, 1254, 1728}}, {
|
||||
640, {
|
||||
1280, 1393, 1920}}, {
|
||||
640, {
|
||||
1280, 1394, 1920}}
|
||||
};
|
||||
|
||||
static const guint fscod_rates[4] = { 48000, 44100, 32000, 0 };
|
||||
static const guint acmod_chans[8] = { 2, 1, 2, 3, 3, 4, 4, 5 };
|
||||
static const guint numblks[4] = { 1, 2, 3, 6 };
|
||||
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-ac3, framed = (boolean) true, "
|
||||
" channels = (int) [ 1, 6 ], rate = (int) [ 32000, 48000 ]; "
|
||||
"audio/x-eac3, framed = (boolean) true, "
|
||||
" channels = (int) [ 1, 6 ], rate = (int) [ 32000, 48000 ] "));
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-ac3, framed = (boolean) false; "
|
||||
"audio/x-eac3, framed = (boolean) false; "
|
||||
"audio/ac3, framed = (boolean) false "));
|
||||
|
||||
static void gst_ac3_parse_finalize (GObject * object);
|
||||
|
||||
static gboolean gst_ac3_parse_start (GstBaseParse * parse);
|
||||
static gboolean gst_ac3_parse_stop (GstBaseParse * parse);
|
||||
static gboolean gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
||||
static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
|
||||
GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
static void
|
||||
gst_ac3_parse_base_init (gpointer klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
|
||||
gst_element_class_set_details_simple (element_class,
|
||||
"AC3 audio stream parser", "Codec/Parser/Audio",
|
||||
"AC3 parser", "Tim-Philipp Müller <tim centricular net>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ac3_parse_class_init (GstAc3ParseClass * klass)
|
||||
{
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (ac3_parse_debug, "ac3parse", 0,
|
||||
"AC3 audio stream parser");
|
||||
|
||||
object_class->finalize = gst_ac3_parse_finalize;
|
||||
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_ac3_parse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_ac3_parse_stop);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_ac3_parse_check_valid_frame);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_parse_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ac3_parse_reset (GstAc3Parse * ac3parse)
|
||||
{
|
||||
ac3parse->channels = -1;
|
||||
ac3parse->sample_rate = -1;
|
||||
ac3parse->eac = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ac3_parse_init (GstAc3Parse * ac3parse, GstAc3ParseClass * klass)
|
||||
{
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (ac3parse), 64 * 2);
|
||||
gst_ac3_parse_reset (ac3parse);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ac3_parse_finalize (GObject * object)
|
||||
{
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ac3_parse_start (GstBaseParse * parse)
|
||||
{
|
||||
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
||||
|
||||
GST_DEBUG_OBJECT (parse, "starting");
|
||||
|
||||
gst_ac3_parse_reset (ac3parse);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ac3_parse_stop (GstBaseParse * parse)
|
||||
{
|
||||
GST_DEBUG_OBJECT (parse, "stopping");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
|
||||
guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
|
||||
{
|
||||
GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
|
||||
guint8 fscod, frmsizcod, bsid, bsmod, acmod, lfe_on;
|
||||
|
||||
GST_LOG_OBJECT (ac3parse, "parsing ac3");
|
||||
|
||||
gst_bit_reader_skip_unchecked (&bits, 16 + 16);
|
||||
fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);
|
||||
frmsizcod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 6);
|
||||
|
||||
if (G_UNLIKELY (fscod == 3 || frmsizcod >= G_N_ELEMENTS (frmsizcod_table))) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "bad fscod=%d frmsizcod=%d", fscod, frmsizcod);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bsid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 5);
|
||||
bsmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);
|
||||
acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);
|
||||
|
||||
/* spec not quite clear here: decoder should decode if less than 8,
|
||||
* but seemingly only defines 6 and 8 cases */
|
||||
if (bsid > 8) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid);
|
||||
return FALSE;
|
||||
} else if (bsid != 8 && bsid != 6) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "undefined bsid=%d", bsid);
|
||||
}
|
||||
|
||||
if ((acmod & 0x1) && (acmod != 0x1)) /* 3 front channels */
|
||||
gst_bit_reader_skip_unchecked (&bits, 2);
|
||||
if ((acmod & 0x4)) /* if a surround channel exists */
|
||||
gst_bit_reader_skip_unchecked (&bits, 2);
|
||||
if (acmod == 0x2) /* if in 2/0 mode */
|
||||
gst_bit_reader_skip_unchecked (&bits, 2);
|
||||
|
||||
lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1);
|
||||
|
||||
if (frame_size)
|
||||
*frame_size = frmsizcod_table[frmsizcod].frame_size[fscod] * 2;
|
||||
if (rate)
|
||||
*rate = fscod_rates[fscod];
|
||||
if (chans)
|
||||
*chans = acmod_chans[acmod] + lfe_on;
|
||||
if (blks)
|
||||
*blks = 6;
|
||||
if (sid)
|
||||
*sid = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
|
||||
guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
|
||||
{
|
||||
GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
|
||||
guint16 frmsiz, sample_rate, blocks;
|
||||
guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod;
|
||||
|
||||
GST_LOG_OBJECT (ac3parse, "parsing e-ac3");
|
||||
|
||||
gst_bit_reader_skip_unchecked (&bits, 16);
|
||||
strmtyp = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* strmtyp */
|
||||
if (G_UNLIKELY (strmtyp == 3)) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "bad strmtyp %d", strmtyp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strmid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); /* substreamid */
|
||||
frmsiz = gst_bit_reader_get_bits_uint16_unchecked (&bits, 11); /* frmsiz */
|
||||
fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* fscod */
|
||||
if (fscod == 3) {
|
||||
fscod2 = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* fscod2 */
|
||||
if (G_UNLIKELY (fscod2 == 3)) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "invalid fscod2");
|
||||
return FALSE;
|
||||
}
|
||||
sample_rate = fscod_rates[fscod2] / 2;
|
||||
blocks = 6;
|
||||
} else {
|
||||
numblkscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* numblkscod */
|
||||
sample_rate = fscod_rates[fscod];
|
||||
blocks = numblks[numblkscod];
|
||||
}
|
||||
|
||||
acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); /* acmod */
|
||||
lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1); /* lfeon */
|
||||
|
||||
gst_bit_reader_skip_unchecked (&bits, 5); /* bsid */
|
||||
|
||||
if (frame_size)
|
||||
*frame_size = (frmsiz + 1) * 2;
|
||||
if (rate)
|
||||
*rate = sample_rate;
|
||||
if (chans)
|
||||
*chans = acmod_chans[acmod] + lfe_on;
|
||||
if (blks)
|
||||
*blks = blocks;
|
||||
if (sid)
|
||||
*sid = (strmtyp & 0x1) << 3 | strmid;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf,
|
||||
guint * framesize, guint * rate, guint * chans, guint * blocks,
|
||||
guint * sid, gboolean * eac)
|
||||
{
|
||||
GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
|
||||
guint16 sync;
|
||||
guint8 bsid;
|
||||
|
||||
GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", GST_BUFFER_DATA (buf), 16);
|
||||
|
||||
sync = gst_bit_reader_get_bits_uint16_unchecked (&bits, 16);
|
||||
gst_bit_reader_skip_unchecked (&bits, 16 + 8);
|
||||
bsid = gst_bit_reader_peek_bits_uint8_unchecked (&bits, 5);
|
||||
|
||||
if (G_UNLIKELY (sync != 0x0b77))
|
||||
return FALSE;
|
||||
|
||||
GST_LOG_OBJECT (parse, "bsid = %d", bsid);
|
||||
|
||||
if (bsid <= 10) {
|
||||
if (eac)
|
||||
*eac = FALSE;
|
||||
return gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans,
|
||||
blocks, sid);
|
||||
} else if (bsid <= 16) {
|
||||
if (eac)
|
||||
*eac = TRUE;
|
||||
return gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans,
|
||||
blocks, sid);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
{
|
||||
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||
gint off;
|
||||
gboolean sync, drain;
|
||||
|
||||
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
|
||||
return FALSE;
|
||||
|
||||
off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
|
||||
0, GST_BUFFER_SIZE (buf));
|
||||
|
||||
GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
|
||||
|
||||
/* didn't find anything that looks like a sync word, skip */
|
||||
if (off < 0) {
|
||||
*skipsize = GST_BUFFER_SIZE (buf) - 3;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* possible frame header, but not at offset 0? skip bytes before sync */
|
||||
if (off > 0) {
|
||||
*skipsize = off;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* make sure the values in the frame header look sane */
|
||||
if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, NULL, NULL,
|
||||
NULL, NULL, NULL)) {
|
||||
*skipsize = off + 2;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (parse, "got frame");
|
||||
|
||||
sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
||||
drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
|
||||
|
||||
if (!sync && !drain) {
|
||||
guint16 word = 0;
|
||||
|
||||
GST_DEBUG_OBJECT (ac3parse, "resyncing; checking next frame syncword");
|
||||
|
||||
if (!gst_byte_reader_skip (&reader, *framesize) ||
|
||||
!gst_byte_reader_get_uint16_be (&reader, &word)) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
|
||||
gst_base_parse_set_min_frame_size (parse, *framesize + 6);
|
||||
*skipsize = 0;
|
||||
return FALSE;
|
||||
} else {
|
||||
if (word != 0x0b77) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "0x%x not OK", word);
|
||||
*skipsize = off + 2;
|
||||
return FALSE;
|
||||
} else {
|
||||
/* ok, got sync now, let's assume constant frame size */
|
||||
gst_base_parse_set_min_frame_size (parse, *framesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
{
|
||||
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
guint fsize, rate, chans, blocks, sid;
|
||||
gboolean eac;
|
||||
|
||||
if (!gst_ac3_parse_frame_header (ac3parse, buf, &fsize, &rate, &chans,
|
||||
&blocks, &sid, &eac))
|
||||
goto broken_header;
|
||||
|
||||
GST_LOG_OBJECT (parse, "size: %u, rate: %u, chans: %u", fsize, rate, chans);
|
||||
|
||||
if (G_UNLIKELY (sid)) {
|
||||
/* dependent frame, no need to (ac)count for or consider further */
|
||||
GST_LOG_OBJECT (parse, "sid: %d", sid);
|
||||
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
|
||||
/* TODO maybe also mark as DELTA_UNIT,
|
||||
* if that does not surprise baseparse elsewhere */
|
||||
/* occupies same time space as previous base frame */
|
||||
if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
|
||||
GST_BUFFER_TIMESTAMP (buf) -= GST_BUFFER_DURATION (buf);
|
||||
/* only return if we already arranged for caps */
|
||||
if (G_LIKELY (ac3parse->sample_rate > 0))
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
|
||||
|| ac3parse->eac != ac3parse->eac)) {
|
||||
GstCaps *caps = gst_caps_new_simple (eac ? "audio/x-eac3" : "audio/x-ac3",
|
||||
"framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
|
||||
"channels", G_TYPE_INT, chans, NULL);
|
||||
gst_buffer_set_caps (buf, caps);
|
||||
gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
ac3parse->sample_rate = rate;
|
||||
ac3parse->channels = chans;
|
||||
ac3parse->eac = eac;
|
||||
|
||||
gst_base_parse_set_frame_props (parse, rate, 256 * blocks, 2, 2);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
broken_header:
|
||||
{
|
||||
/* this really shouldn't ever happen */
|
||||
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/* GStreamer AC3 parser
|
||||
* Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
|
||||
* Copyright (C) 2009 Mark Nauwelaerts <mnauw users sf net>
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
#ifndef __GST_AC3_PARSE_H__
|
||||
#define __GST_AC3_PARSE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/baseparse/gstbaseparse.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_AC3_PARSE \
|
||||
(gst_ac3_parse_get_type())
|
||||
#define GST_AC3_PARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AC3_PARSE, GstAc3Parse))
|
||||
#define GST_AC3_PARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AC3_PARSE, GstAc3ParseClass))
|
||||
#define GST_IS_AC3_PARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AC3_PARSE))
|
||||
#define GST_IS_AC3_PARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AC3_PARSE))
|
||||
|
||||
typedef struct _GstAc3Parse GstAc3Parse;
|
||||
typedef struct _GstAc3ParseClass GstAc3ParseClass;
|
||||
|
||||
/**
|
||||
* GstAc3Parse:
|
||||
*
|
||||
* The opaque GstAc3Parse object
|
||||
*/
|
||||
struct _GstAc3Parse {
|
||||
GstBaseParse baseparse;
|
||||
|
||||
/*< private >*/
|
||||
gint sample_rate;
|
||||
gint channels;
|
||||
gboolean eac;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstAc3ParseClass:
|
||||
* @parent_class: Element parent class.
|
||||
*
|
||||
* The opaque GstAc3ParseClass data structure.
|
||||
*/
|
||||
struct _GstAc3ParseClass {
|
||||
GstBaseParseClass baseparse_class;
|
||||
};
|
||||
|
||||
GType gst_ac3_parse_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_AC3_PARSE_H__ */
|
|
@ -1,378 +0,0 @@
|
|||
/* GStreamer Adaptive Multi-Rate parser plugin
|
||||
* Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
|
||||
* 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-amrparse
|
||||
* @short_description: AMR parser
|
||||
* @see_also: #GstAmrnbDec, #GstAmrnbEnc
|
||||
*
|
||||
* This is an AMR parser capable of handling both narrow-band and wideband
|
||||
* formats.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch filesrc location=abc.amr ! amrparse ! amrdec ! audioresample ! audioconvert ! alsasink
|
||||
* ]|
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gstamrparse.h"
|
||||
|
||||
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/AMR, " "rate = (int) 8000, " "channels = (int) 1;"
|
||||
"audio/AMR-WB, " "rate = (int) 16000, " "channels = (int) 1;")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-amr-nb-sh; audio/x-amr-wb-sh"));
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_amrparse_debug);
|
||||
#define GST_CAT_DEFAULT gst_amrparse_debug
|
||||
|
||||
static const gint block_size_nb[16] =
|
||||
{ 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
static const gint block_size_wb[16] =
|
||||
{ 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, -1, -1, -1, -1, 0, 0 };
|
||||
|
||||
/* AMR has a "hardcoded" framerate of 50fps */
|
||||
#define AMR_FRAMES_PER_SECOND 50
|
||||
#define AMR_FRAME_DURATION (GST_SECOND/AMR_FRAMES_PER_SECOND)
|
||||
#define AMR_MIME_HEADER_SIZE 9
|
||||
|
||||
gboolean gst_amrparse_start (GstBaseParse * parse);
|
||||
gboolean gst_amrparse_stop (GstBaseParse * parse);
|
||||
|
||||
static gboolean gst_amrparse_sink_setcaps (GstBaseParse * parse,
|
||||
GstCaps * caps);
|
||||
|
||||
gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
|
||||
|
||||
GstFlowReturn gst_amrparse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
|
||||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_amrparse_debug, "amrparse", 0, \
|
||||
"AMR-NB audio stream parser");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstAmrParse, gst_amrparse, GstBaseParse,
|
||||
GST_TYPE_BASE_PARSE, _do_init);
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_base_init:
|
||||
* @klass: #GstElementClass.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
gst_amrparse_base_init (gpointer klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
|
||||
gst_element_class_set_details_simple (element_class,
|
||||
"AMR audio stream parser", "Codec/Parser/Audio",
|
||||
"Adaptive Multi-Rate audio parser",
|
||||
"Ronald Bultje <rbultje@ronald.bitfreak.net>");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_class_init:
|
||||
* @klass: GstAmrParseClass.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
gst_amrparse_class_init (GstAmrParseClass * klass)
|
||||
{
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_amrparse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_amrparse_stop);
|
||||
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_amrparse_sink_setcaps);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_amrparse_parse_frame);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_amrparse_check_valid_frame);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_init:
|
||||
* @amrparse: #GstAmrParse
|
||||
* @klass: #GstAmrParseClass.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
gst_amrparse_init (GstAmrParse * amrparse, GstAmrParseClass * klass)
|
||||
{
|
||||
/* init rest */
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (amrparse), 62);
|
||||
GST_DEBUG ("initialized");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_set_src_caps:
|
||||
* @amrparse: #GstAmrParse.
|
||||
*
|
||||
* Set source pad caps according to current knowledge about the
|
||||
* audio stream.
|
||||
*
|
||||
* Returns: TRUE if caps were successfully set.
|
||||
*/
|
||||
static gboolean
|
||||
gst_amrparse_set_src_caps (GstAmrParse * amrparse)
|
||||
{
|
||||
GstCaps *src_caps = NULL;
|
||||
gboolean res = FALSE;
|
||||
|
||||
if (amrparse->wide) {
|
||||
GST_DEBUG_OBJECT (amrparse, "setting srcpad caps to AMR-WB");
|
||||
src_caps = gst_caps_new_simple ("audio/AMR-WB",
|
||||
"channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 16000, NULL);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (amrparse, "setting srcpad caps to AMR-NB");
|
||||
/* Max. size of NB frame is 31 bytes, so we can set the min. frame
|
||||
size to 32 (+1 for next frame header) */
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (amrparse), 32);
|
||||
src_caps = gst_caps_new_simple ("audio/AMR",
|
||||
"channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 8000, NULL);
|
||||
}
|
||||
gst_pad_use_fixed_caps (GST_BASE_PARSE (amrparse)->srcpad);
|
||||
res = gst_pad_set_caps (GST_BASE_PARSE (amrparse)->srcpad, src_caps);
|
||||
gst_caps_unref (src_caps);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_sink_setcaps:
|
||||
* @sinkpad: GstPad
|
||||
* @caps: GstCaps
|
||||
*
|
||||
* Returns: TRUE on success.
|
||||
*/
|
||||
static gboolean
|
||||
gst_amrparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
|
||||
{
|
||||
GstAmrParse *amrparse;
|
||||
GstStructure *structure;
|
||||
const gchar *name;
|
||||
|
||||
amrparse = GST_AMRPARSE (parse);
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
name = gst_structure_get_name (structure);
|
||||
|
||||
GST_DEBUG_OBJECT (amrparse, "setcaps: %s", name);
|
||||
|
||||
if (!strncmp (name, "audio/x-amr-wb-sh", 17)) {
|
||||
amrparse->block_size = block_size_wb;
|
||||
amrparse->wide = 1;
|
||||
} else if (!strncmp (name, "audio/x-amr-nb-sh", 17)) {
|
||||
amrparse->block_size = block_size_nb;
|
||||
amrparse->wide = 0;
|
||||
} else {
|
||||
GST_WARNING ("Unknown caps");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
amrparse->need_header = FALSE;
|
||||
gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
|
||||
gst_amrparse_set_src_caps (amrparse);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_amrparse_parse_header:
|
||||
* @amrparse: #GstAmrParse
|
||||
* @data: Header data to be parsed.
|
||||
* @skipsize: Output argument where the frame size will be stored.
|
||||
*
|
||||
* Check if the given data contains an AMR mime header.
|
||||
*
|
||||
* Returns: TRUE on success.
|
||||
*/
|
||||
static gboolean
|
||||
gst_amrparse_parse_header (GstAmrParse * amrparse,
|
||||
const guint8 * data, gint * skipsize)
|
||||
{
|
||||
GST_DEBUG_OBJECT (amrparse, "Parsing header data");
|
||||
|
||||
if (!memcmp (data, "#!AMR-WB\n", 9)) {
|
||||
GST_DEBUG_OBJECT (amrparse, "AMR-WB detected");
|
||||
amrparse->block_size = block_size_wb;
|
||||
amrparse->wide = TRUE;
|
||||
*skipsize = amrparse->header = 9;
|
||||
} else if (!memcmp (data, "#!AMR\n", 6)) {
|
||||
GST_DEBUG_OBJECT (amrparse, "AMR-NB detected");
|
||||
amrparse->block_size = block_size_nb;
|
||||
amrparse->wide = FALSE;
|
||||
*skipsize = amrparse->header = 6;
|
||||
} else
|
||||
return FALSE;
|
||||
|
||||
gst_amrparse_set_src_caps (amrparse);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_check_valid_frame:
|
||||
* @parse: #GstBaseParse.
|
||||
* @buffer: #GstBuffer.
|
||||
* @framesize: Output variable where the found frame size is put.
|
||||
* @skipsize: Output variable which tells how much data needs to be skipped
|
||||
* until a frame header is found.
|
||||
*
|
||||
* Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: TRUE if the given data contains valid frame.
|
||||
*/
|
||||
gboolean
|
||||
gst_amrparse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
const guint8 *data;
|
||||
gint fsize, mode, dsize;
|
||||
GstAmrParse *amrparse;
|
||||
|
||||
amrparse = GST_AMRPARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
data = GST_BUFFER_DATA (buffer);
|
||||
dsize = GST_BUFFER_SIZE (buffer);
|
||||
|
||||
GST_LOG ("buffer: %d bytes", dsize);
|
||||
|
||||
if (amrparse->need_header) {
|
||||
if (dsize >= AMR_MIME_HEADER_SIZE &&
|
||||
gst_amrparse_parse_header (amrparse, data, skipsize)) {
|
||||
amrparse->need_header = FALSE;
|
||||
gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
|
||||
} else {
|
||||
GST_WARNING ("media doesn't look like a AMR format");
|
||||
}
|
||||
/* We return FALSE, so this frame won't get pushed forward. Instead,
|
||||
the "skip" value is set, so next time we will receive a valid frame. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Does this look like a possible frame header candidate? */
|
||||
if ((data[0] & 0x83) == 0) {
|
||||
/* Yep. Retrieve the frame size */
|
||||
mode = (data[0] >> 3) & 0x0F;
|
||||
fsize = amrparse->block_size[mode] + 1; /* +1 for the header byte */
|
||||
|
||||
/* We recognize this data as a valid frame when:
|
||||
* - We are in sync. There is no need for extra checks then
|
||||
* - We are in EOS. There might not be enough data to check next frame
|
||||
* - Sync is lost, but the following data after this frame seem
|
||||
* to contain a valid header as well (and there is enough data to
|
||||
* perform this check)
|
||||
*/
|
||||
if (fsize &&
|
||||
(GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame)
|
||||
|| (dsize > fsize && (data[fsize] & 0x83) == 0))) {
|
||||
*framesize = fsize;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
GST_LOG ("sync lost");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_parse_frame:
|
||||
* @parse: #GstBaseParse.
|
||||
* @buffer: #GstBuffer.
|
||||
*
|
||||
* Implementation of "parse" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: #GstFlowReturn defining the parsing status.
|
||||
*/
|
||||
GstFlowReturn
|
||||
gst_amrparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
{
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_start:
|
||||
* @parse: #GstBaseParse.
|
||||
*
|
||||
* Implementation of "start" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: TRUE on success.
|
||||
*/
|
||||
gboolean
|
||||
gst_amrparse_start (GstBaseParse * parse)
|
||||
{
|
||||
GstAmrParse *amrparse;
|
||||
|
||||
amrparse = GST_AMRPARSE (parse);
|
||||
GST_DEBUG ("start");
|
||||
amrparse->need_header = TRUE;
|
||||
amrparse->header = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amrparse_stop:
|
||||
* @parse: #GstBaseParse.
|
||||
*
|
||||
* Implementation of "stop" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: TRUE on success.
|
||||
*/
|
||||
gboolean
|
||||
gst_amrparse_stop (GstBaseParse * parse)
|
||||
{
|
||||
GstAmrParse *amrparse;
|
||||
|
||||
amrparse = GST_AMRPARSE (parse);
|
||||
GST_DEBUG ("stop");
|
||||
amrparse->need_header = TRUE;
|
||||
amrparse->header = 0;
|
||||
return TRUE;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/* GStreamer Adaptive Multi-Rate parser
|
||||
* Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __GST_AMRPARSE_H__
|
||||
#define __GST_AMRPARSE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/baseparse/gstbaseparse.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_AMRPARSE \
|
||||
(gst_amrparse_get_type())
|
||||
#define GST_AMRPARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AMRPARSE, GstAmrParse))
|
||||
#define GST_AMRPARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AMRPARSE, GstAmrParseClass))
|
||||
#define GST_IS_AMRPARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AMRPARSE))
|
||||
#define GST_IS_AMRPARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AMRPARSE))
|
||||
|
||||
|
||||
typedef struct _GstAmrParse GstAmrParse;
|
||||
typedef struct _GstAmrParseClass GstAmrParseClass;
|
||||
|
||||
/**
|
||||
* GstAmrParse:
|
||||
* @element: the parent element.
|
||||
* @block_size: Pointer to frame size lookup table.
|
||||
* @need_header: Tells whether the MIME header should be read in the beginning.
|
||||
* @wide: Wideband mode.
|
||||
* @eos: Indicates the EOS situation. Set when EOS event is received.
|
||||
* @sync: Tells whether the parser is in sync.
|
||||
* @framecount: Total amount of frames handled.
|
||||
* @bytecount: Total amount of bytes handled.
|
||||
* @ts: Timestamp of the current media.
|
||||
*
|
||||
* The opaque GstAacParse data structure.
|
||||
*/
|
||||
struct _GstAmrParse {
|
||||
GstBaseParse element;
|
||||
const gint *block_size;
|
||||
gboolean need_header;
|
||||
gint header;
|
||||
gboolean wide;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstAmrParseClass:
|
||||
* @parent_class: Element parent class.
|
||||
*
|
||||
* The opaque GstAmrParseClass data structure.
|
||||
*/
|
||||
struct _GstAmrParseClass {
|
||||
GstBaseParseClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_amrparse_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_AMRPARSE_H__ */
|
|
@ -1,451 +0,0 @@
|
|||
/* GStreamer DCA parser
|
||||
* Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* 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-dcaparse
|
||||
* @short_description: DCA (DTS Coherent Acoustics) parser
|
||||
* @see_also: #GstAmrParse, #GstAACParse, #GstAc3Parse
|
||||
*
|
||||
* This is a DCA (DTS Coherent Acoustics) parser.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch filesrc location=abc.dts ! dcaparse ! dtsdec ! audioresample ! audioconvert ! autoaudiosink
|
||||
* ]|
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* - should accept framed and unframed input (needs decodebin fixes first)
|
||||
* - seeking in raw .dts files doesn't seem to work, but duration estimate ok
|
||||
*
|
||||
* - if frames have 'odd' durations, the frame durations (plus timestamps)
|
||||
* aren't adjusted up occasionally to make up for rounding error gaps.
|
||||
* (e.g. if 512 samples per frame @ 48kHz = 10.666666667 ms/frame)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gstdcaparse.h"
|
||||
#include <gst/base/gstbytereader.h>
|
||||
#include <gst/base/gstbitreader.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (dca_parse_debug);
|
||||
#define GST_CAT_DEFAULT dca_parse_debug
|
||||
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-dts,"
|
||||
" framed = (boolean) true,"
|
||||
" channels = (int) [ 1, 8 ],"
|
||||
" rate = (int) [ 8000, 192000 ],"
|
||||
" depth = (int) { 14, 16 },"
|
||||
" endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }"));
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-dts, framed = (boolean) false"));
|
||||
|
||||
static void gst_dca_parse_finalize (GObject * object);
|
||||
|
||||
static gboolean gst_dca_parse_start (GstBaseParse * parse);
|
||||
static gboolean gst_dca_parse_stop (GstBaseParse * parse);
|
||||
static gboolean gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
||||
static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
|
||||
GST_BOILERPLATE (GstDcaParse, gst_dca_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
static void
|
||||
gst_dca_parse_base_init (gpointer klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
|
||||
gst_element_class_set_details_simple (element_class,
|
||||
"DTS Coherent Acoustics audio stream parser", "Codec/Parser/Audio",
|
||||
"DCA parser", "Tim-Philipp Müller <tim centricular net>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dca_parse_class_init (GstDcaParseClass * klass)
|
||||
{
|
||||
GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (dca_parse_debug, "dcaparse", 0,
|
||||
"DCA audio stream parser");
|
||||
|
||||
object_class->finalize = gst_dca_parse_finalize;
|
||||
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_dca_parse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_dca_parse_stop);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_dca_parse_check_valid_frame);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_dca_parse_parse_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dca_parse_reset (GstDcaParse * dcaparse)
|
||||
{
|
||||
dcaparse->channels = -1;
|
||||
dcaparse->rate = -1;
|
||||
dcaparse->depth = -1;
|
||||
dcaparse->endianness = -1;
|
||||
dcaparse->block_size = -1;
|
||||
dcaparse->frame_size = -1;
|
||||
dcaparse->last_sync = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dca_parse_init (GstDcaParse * dcaparse, GstDcaParseClass * klass)
|
||||
{
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (dcaparse),
|
||||
DCA_MIN_FRAMESIZE);
|
||||
gst_dca_parse_reset (dcaparse);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dca_parse_finalize (GObject * object)
|
||||
{
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dca_parse_start (GstBaseParse * parse)
|
||||
{
|
||||
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||
|
||||
GST_DEBUG_OBJECT (parse, "starting");
|
||||
|
||||
gst_dca_parse_reset (dcaparse);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dca_parse_stop (GstBaseParse * parse)
|
||||
{
|
||||
GST_DEBUG_OBJECT (parse, "stopping");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dca_parse_parse_header (GstDcaParse * dcaparse,
|
||||
const GstByteReader * reader, guint * frame_size,
|
||||
guint * sample_rate, guint * channels, guint * depth,
|
||||
gint * endianness, guint * num_blocks, guint * samples_per_block,
|
||||
gboolean * terminator)
|
||||
{
|
||||
static const int sample_rates[16] = { 0, 8000, 16000, 32000, 0, 0, 11025,
|
||||
22050, 44100, 0, 0, 12000, 24000, 48000, 96000, 192000
|
||||
};
|
||||
static const guint8 channels_table[16] = { 1, 2, 2, 2, 2, 3, 3, 4, 4, 5,
|
||||
6, 6, 6, 7, 8, 8
|
||||
};
|
||||
GstByteReader r = *reader;
|
||||
guint16 hdr[8];
|
||||
guint32 marker;
|
||||
guint chans, lfe, i;
|
||||
|
||||
if (gst_byte_reader_get_remaining (&r) < (4 + sizeof (hdr)))
|
||||
return FALSE;
|
||||
|
||||
marker = gst_byte_reader_peek_uint32_be_unchecked (&r);
|
||||
|
||||
/* raw big endian or 14-bit big endian */
|
||||
if (marker == 0x7FFE8001 || marker == 0x1FFFE800) {
|
||||
for (i = 0; i < G_N_ELEMENTS (hdr); ++i)
|
||||
hdr[i] = gst_byte_reader_get_uint16_be_unchecked (&r);
|
||||
} else
|
||||
/* raw little endian or 14-bit little endian */
|
||||
if (marker == 0xFE7F0180 || marker == 0xFF1F00E8) {
|
||||
for (i = 0; i < G_N_ELEMENTS (hdr); ++i)
|
||||
hdr[i] = gst_byte_reader_get_uint16_le_unchecked (&r);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (dcaparse, "dts sync marker 0x%08x at offset %u", marker,
|
||||
gst_byte_reader_get_pos (reader));
|
||||
|
||||
/* 14-bit mode */
|
||||
if (marker == 0x1FFFE800 || marker == 0xFF1F00E8) {
|
||||
if ((hdr[2] & 0xFFF0) != 0x07F0)
|
||||
return FALSE;
|
||||
/* discard top 2 bits (2 void), shift in 2 */
|
||||
hdr[0] = (hdr[0] << 2) | ((hdr[1] >> 12) & 0x0003);
|
||||
/* discard top 4 bits (2 void, 2 shifted into hdr[0]), shift in 4 etc. */
|
||||
hdr[1] = (hdr[1] << 4) | ((hdr[2] >> 10) & 0x000F);
|
||||
hdr[2] = (hdr[2] << 6) | ((hdr[3] >> 8) & 0x003F);
|
||||
hdr[3] = (hdr[3] << 8) | ((hdr[4] >> 6) & 0x00FF);
|
||||
hdr[4] = (hdr[4] << 10) | ((hdr[5] >> 4) & 0x03FF);
|
||||
hdr[5] = (hdr[5] << 12) | ((hdr[6] >> 2) & 0x0FFF);
|
||||
hdr[6] = (hdr[6] << 14) | ((hdr[7] >> 0) & 0x3FFF);
|
||||
g_assert (hdr[0] == 0x7FFE && hdr[1] == 0x8001);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (dcaparse, "frame header: %04x%04x%04x%04x",
|
||||
hdr[2], hdr[3], hdr[4], hdr[5]);
|
||||
|
||||
*terminator = (hdr[2] & 0x80) ? FALSE : TRUE;
|
||||
*samples_per_block = ((hdr[2] >> 10) & 0x1f) + 1;
|
||||
*num_blocks = ((hdr[2] >> 2) & 0x7F) + 1;
|
||||
*frame_size = (((hdr[2] & 0x03) << 12) | (hdr[3] >> 4)) + 1;
|
||||
chans = ((hdr[3] & 0x0F) << 2) | (hdr[4] >> 14);
|
||||
*sample_rate = sample_rates[(hdr[4] >> 10) & 0x0F];
|
||||
lfe = (hdr[5] >> 9) & 0x03;
|
||||
|
||||
GST_TRACE_OBJECT (dcaparse, "frame size %u, num_blocks %u, rate %u, "
|
||||
"samples per block %u", *frame_size, *num_blocks, *sample_rate,
|
||||
*samples_per_block);
|
||||
|
||||
if (*num_blocks < 6 || *frame_size < 96 || *sample_rate == 0)
|
||||
return FALSE;
|
||||
|
||||
if (marker == 0x1FFFE800 || marker == 0xFF1F00E8)
|
||||
*frame_size = (*frame_size * 16) / 14; /* FIXME: round up? */
|
||||
|
||||
if (chans < G_N_ELEMENTS (channels_table))
|
||||
*channels = channels_table[chans] + ((lfe) ? 1 : 0);
|
||||
else
|
||||
*channels = 0;
|
||||
|
||||
if (depth)
|
||||
*depth = (marker == 0x1FFFE800 || marker == 0xFF1F00E8) ? 14 : 16;
|
||||
if (endianness)
|
||||
*endianness = (marker == 0xFE7F0180 || marker == 0xFF1F00E8) ?
|
||||
G_LITTLE_ENDIAN : G_BIG_ENDIAN;
|
||||
|
||||
GST_TRACE_OBJECT (dcaparse, "frame size %u, channels %u, rate %u, "
|
||||
"num_blocks %u, samples_per_block %u", *frame_size, *channels,
|
||||
*sample_rate, *num_blocks, *samples_per_block);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
|
||||
const GstBuffer * buf, guint32 * sync)
|
||||
{
|
||||
guint32 best_sync = 0;
|
||||
guint best_offset = G_MAXUINT;
|
||||
gint off;
|
||||
|
||||
/* FIXME: verify syncs via _parse_header() here already */
|
||||
|
||||
/* Raw little endian */
|
||||
off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xfe7f0180,
|
||||
0, GST_BUFFER_SIZE (buf));
|
||||
if (off >= 0 && off < best_offset) {
|
||||
best_offset = off;
|
||||
best_sync = 0xfe7f0180;
|
||||
}
|
||||
|
||||
/* Raw big endian */
|
||||
off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x7ffe8001,
|
||||
0, GST_BUFFER_SIZE (buf));
|
||||
if (off >= 0 && off < best_offset) {
|
||||
best_offset = off;
|
||||
best_sync = 0x7ffe8001;
|
||||
}
|
||||
|
||||
/* FIXME: check next 2 bytes as well for 14-bit formats (but then don't
|
||||
* forget to adjust the *skipsize= in _check_valid_frame() */
|
||||
|
||||
/* 14-bit little endian */
|
||||
off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xff1f00e8,
|
||||
0, GST_BUFFER_SIZE (buf));
|
||||
if (off >= 0 && off < best_offset) {
|
||||
best_offset = off;
|
||||
best_sync = 0xff1f00e8;
|
||||
}
|
||||
|
||||
/* 14-bit big endian */
|
||||
off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x1fffe800,
|
||||
0, GST_BUFFER_SIZE (buf));
|
||||
if (off >= 0 && off < best_offset) {
|
||||
best_offset = off;
|
||||
best_sync = 0x1fffe800;
|
||||
}
|
||||
|
||||
if (best_offset == G_MAXUINT)
|
||||
return -1;
|
||||
|
||||
*sync = best_sync;
|
||||
return best_offset;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
{
|
||||
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||
gboolean parser_draining;
|
||||
gboolean parser_in_sync;
|
||||
gboolean terminator;
|
||||
guint32 sync = 0;
|
||||
guint size, rate, chans, num_blocks, samples_per_block;
|
||||
gint off = -1;
|
||||
|
||||
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16))
|
||||
return FALSE;
|
||||
|
||||
parser_in_sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
||||
|
||||
if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) {
|
||||
off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff,
|
||||
dcaparse->last_sync, 0, GST_BUFFER_SIZE (buf));
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (off < 0)) {
|
||||
off = gst_dca_parse_find_sync (dcaparse, &r, buf, &sync);
|
||||
}
|
||||
|
||||
/* didn't find anything that looks like a sync word, skip */
|
||||
if (off < 0) {
|
||||
*skipsize = GST_BUFFER_SIZE (buf) - 3;
|
||||
GST_DEBUG_OBJECT (dcaparse, "no sync, skipping %d bytes", *skipsize);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (parse, "possible sync %08x at buffer offset %d", sync, off);
|
||||
|
||||
/* possible frame header, but not at offset 0? skip bytes before sync */
|
||||
if (off > 0) {
|
||||
*skipsize = off;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* make sure the values in the frame header look sane */
|
||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, NULL,
|
||||
NULL, &num_blocks, &samples_per_block, &terminator)) {
|
||||
*skipsize = 4;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (parse, "got frame, sync %08x, size %u, rate %d, channels %d",
|
||||
sync, size, rate, chans);
|
||||
|
||||
*framesize = size;
|
||||
|
||||
dcaparse->last_sync = sync;
|
||||
|
||||
parser_draining = GST_BASE_PARSE_FRAME_DRAIN (frame);
|
||||
|
||||
if (!parser_in_sync && !parser_draining) {
|
||||
/* check for second frame to be sure */
|
||||
GST_DEBUG_OBJECT (dcaparse, "resyncing; checking next frame syncword");
|
||||
if (GST_BUFFER_SIZE (buf) >= (size + 16)) {
|
||||
guint s2, r2, c2, n2, s3;
|
||||
gboolean t;
|
||||
|
||||
GST_MEMDUMP ("buf", GST_BUFFER_DATA (buf), size + 16);
|
||||
gst_byte_reader_init_from_buffer (&r, buf);
|
||||
gst_byte_reader_skip_unchecked (&r, size);
|
||||
|
||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &s2, &r2, &c2, NULL, NULL,
|
||||
&n2, &s3, &t)) {
|
||||
GST_DEBUG_OBJECT (dcaparse, "didn't find second syncword");
|
||||
*skipsize = 4;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ok, got sync now, let's assume constant frame size */
|
||||
gst_base_parse_set_min_frame_size (parse, size);
|
||||
} else {
|
||||
/* FIXME: baseparse always seems to hand us buffers of min_frame_size
|
||||
* bytes, which is unhelpful here */
|
||||
GST_LOG_OBJECT (dcaparse, "next sync out of reach (%u < %u)",
|
||||
GST_BUFFER_SIZE (buf), size + 16);
|
||||
/* *skipsize = 0; */
|
||||
/* return FALSE; */
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
{
|
||||
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||
guint size, rate, chans, depth, block_size, num_blocks, samples_per_block;
|
||||
gint endianness;
|
||||
gboolean terminator;
|
||||
|
||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, &depth,
|
||||
&endianness, &num_blocks, &samples_per_block, &terminator))
|
||||
goto broken_header;
|
||||
|
||||
block_size = num_blocks * samples_per_block;
|
||||
|
||||
if (G_UNLIKELY (dcaparse->rate != rate || dcaparse->channels != chans
|
||||
|| dcaparse->depth != depth || dcaparse->endianness != endianness
|
||||
|| (!terminator && dcaparse->block_size != block_size)
|
||||
|| (size != dcaparse->frame_size))) {
|
||||
GstCaps *caps;
|
||||
|
||||
caps = gst_caps_new_simple ("audio/x-dts",
|
||||
"framed", G_TYPE_BOOLEAN, TRUE,
|
||||
"rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, chans,
|
||||
"endianness", G_TYPE_INT, endianness, "depth", G_TYPE_INT, depth,
|
||||
"block-size", G_TYPE_INT, block_size, "frame-size", G_TYPE_INT, size,
|
||||
NULL);
|
||||
gst_buffer_set_caps (buf, caps);
|
||||
gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
dcaparse->rate = rate;
|
||||
dcaparse->channels = chans;
|
||||
dcaparse->depth = depth;
|
||||
dcaparse->endianness = endianness;
|
||||
dcaparse->block_size = block_size;
|
||||
dcaparse->frame_size = size;
|
||||
|
||||
gst_base_parse_set_frame_props (parse, rate, block_size, 0, 0);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
broken_header:
|
||||
{
|
||||
/* this really shouldn't ever happen */
|
||||
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/* GStreamer DCA parser
|
||||
* Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __GST_DCA_PARSE_H__
|
||||
#define __GST_DCA_PARSE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/baseparse/gstbaseparse.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_DCA_PARSE \
|
||||
(gst_dca_parse_get_type())
|
||||
#define GST_DCA_PARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DCA_PARSE, GstDcaParse))
|
||||
#define GST_DCA_PARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DCA_PARSE, GstDcaParseClass))
|
||||
#define GST_IS_DCA_PARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DCA_PARSE))
|
||||
#define GST_IS_DCA_PARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DCA_PARSE))
|
||||
|
||||
#define DCA_MIN_FRAMESIZE 96
|
||||
#define DCA_MAX_FRAMESIZE 18725 /* 16384*16/14 */
|
||||
|
||||
typedef struct _GstDcaParse GstDcaParse;
|
||||
typedef struct _GstDcaParseClass GstDcaParseClass;
|
||||
|
||||
/**
|
||||
* GstDcaParse:
|
||||
*
|
||||
* The opaque GstDcaParse object
|
||||
*/
|
||||
struct _GstDcaParse {
|
||||
GstBaseParse baseparse;
|
||||
|
||||
/*< private >*/
|
||||
gint rate;
|
||||
gint channels;
|
||||
gint depth;
|
||||
gint endianness;
|
||||
gint block_size;
|
||||
gint frame_size;
|
||||
|
||||
guint32 last_sync;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstDcaParseClass:
|
||||
* @parent_class: Element parent class.
|
||||
*
|
||||
* The opaque GstDcaParseClass data structure.
|
||||
*/
|
||||
struct _GstDcaParseClass {
|
||||
GstBaseParseClass baseparse_class;
|
||||
};
|
||||
|
||||
GType gst_dca_parse_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_DCA_PARSE_H__ */
|
File diff suppressed because it is too large
Load diff
|
@ -1,92 +0,0 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
|
||||
* Copyright (C) 2009 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
#ifndef __GST_FLAC_PARSE_H__
|
||||
#define __GST_FLAC_PARSE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/baseparse/gstbaseparse.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_FLAC_PARSE (gst_flac_parse_get_type())
|
||||
#define GST_FLAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FLAC_PARSE,GstFlacParse))
|
||||
#define GST_FLAC_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FLAC_PARSE,GstFlacParseClass))
|
||||
#define GST_FLAC_PARSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_FLAC_PARSE,GstFlacParseClass))
|
||||
#define GST_IS_FLAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLAC_PARSE))
|
||||
#define GST_IS_FLAC_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLAC_PARSE))
|
||||
#define GST_FLAC_PARSE_CAST(obj) ((GstFlacParse *)(obj))
|
||||
|
||||
typedef struct _GstFlacParse GstFlacParse;
|
||||
typedef struct _GstFlacParseClass GstFlacParseClass;
|
||||
|
||||
typedef enum {
|
||||
GST_FLAC_PARSE_STATE_INIT,
|
||||
GST_FLAC_PARSE_STATE_HEADERS,
|
||||
GST_FLAC_PARSE_STATE_GENERATE_HEADERS,
|
||||
GST_FLAC_PARSE_STATE_DATA
|
||||
} GstFlacParseState;
|
||||
|
||||
typedef struct {
|
||||
guint8 type;
|
||||
} GstFlacParseSubFrame;
|
||||
|
||||
struct _GstFlacParse {
|
||||
GstBaseParse parent;
|
||||
|
||||
/* Properties */
|
||||
gboolean check_frame_checksums;
|
||||
|
||||
GstFlacParseState state;
|
||||
|
||||
gint64 upstream_length;
|
||||
|
||||
/* STREAMINFO content */
|
||||
guint16 min_blocksize, max_blocksize;
|
||||
guint32 min_framesize, max_framesize;
|
||||
guint32 samplerate;
|
||||
guint8 channels;
|
||||
guint8 bps;
|
||||
guint64 total_samples;
|
||||
|
||||
/* Current frame */
|
||||
guint64 offset;
|
||||
guint8 blocking_strategy;
|
||||
guint16 block_size;
|
||||
guint64 sample_number;
|
||||
|
||||
GstTagList *tags;
|
||||
|
||||
GList *headers;
|
||||
GstBuffer *seektable;
|
||||
};
|
||||
|
||||
struct _GstFlacParseClass {
|
||||
GstBaseParseClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_flac_parse_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FLAC_PARSE_H__ */
|
File diff suppressed because it is too large
Load diff
|
@ -1,111 +0,0 @@
|
|||
/* GStreamer MPEG audio parser
|
||||
* Copyright (C) 2006-2007 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
* Copyright (C) 2010 Mark Nauwelaerts <mnauw users sf net>
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef __GST_MPEG_AUDIO_PARSE_H__
|
||||
#define __GST_MPEG_AUDIO_PARSE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/baseparse/gstbaseparse.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_MPEG_AUDIO_PARSE \
|
||||
(gst_mpeg_audio_parse_get_type())
|
||||
#define GST_MPEG_AUDIO_PARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_MPEG_AUDIO_PARSE, GstMpegAudioParse))
|
||||
#define GST_MPEG_AUDIO_PARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_MPEG_AUDIO_PARSE, GstMpegAudioParseClass))
|
||||
#define GST_IS_MPEG_AUDIO_PARSE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_MPEG_AUDIO_PARSE))
|
||||
#define GST_IS_MPEG_AUDIO_PARSE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_MPEG_AUDIO_PARSE))
|
||||
|
||||
typedef struct _GstMpegAudioParse GstMpegAudioParse;
|
||||
typedef struct _GstMpegAudioParseClass GstMpegAudioParseClass;
|
||||
|
||||
/**
|
||||
* GstMpegAudioParse:
|
||||
*
|
||||
* The opaque GstMpegAudioParse object
|
||||
*/
|
||||
struct _GstMpegAudioParse {
|
||||
GstBaseParse baseparse;
|
||||
|
||||
/*< private >*/
|
||||
gint rate;
|
||||
gint channels;
|
||||
gint layer;
|
||||
gint version;
|
||||
|
||||
GstClockTime max_bitreservoir;
|
||||
/* samples per frame */
|
||||
gint spf;
|
||||
|
||||
gboolean sent_codec_tag;
|
||||
guint last_posted_bitrate;
|
||||
gint last_posted_crc, last_crc;
|
||||
guint last_posted_channel_mode, last_mode;
|
||||
|
||||
/* Bitrate from non-vbr headers */
|
||||
guint32 hdr_bitrate;
|
||||
|
||||
/* Xing info */
|
||||
guint32 xing_flags;
|
||||
guint32 xing_frames;
|
||||
GstClockTime xing_total_time;
|
||||
guint32 xing_bytes;
|
||||
/* percent -> filepos mapping */
|
||||
guchar xing_seek_table[100];
|
||||
/* filepos -> percent mapping */
|
||||
guint16 xing_seek_table_inverse[256];
|
||||
guint32 xing_vbr_scale;
|
||||
guint xing_bitrate;
|
||||
|
||||
/* VBRI info */
|
||||
guint32 vbri_frames;
|
||||
GstClockTime vbri_total_time;
|
||||
guint32 vbri_bytes;
|
||||
guint vbri_bitrate;
|
||||
guint vbri_seek_points;
|
||||
guint32 *vbri_seek_table;
|
||||
gboolean vbri_valid;
|
||||
|
||||
/* LAME info */
|
||||
guint32 encoder_delay;
|
||||
guint32 encoder_padding;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstMpegAudioParseClass:
|
||||
* @parent_class: Element parent class.
|
||||
*
|
||||
* The opaque GstMpegAudioParseClass data structure.
|
||||
*/
|
||||
struct _GstMpegAudioParseClass {
|
||||
GstBaseParseClass baseparse_class;
|
||||
};
|
||||
|
||||
GType gst_mpeg_audio_parse_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_MPEG_AUDIO_PARSE_H__ */
|
|
@ -1,57 +0,0 @@
|
|||
/* GStreamer audio parsers
|
||||
* Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstaacparse.h"
|
||||
#include "gstamrparse.h"
|
||||
#include "gstac3parse.h"
|
||||
#include "gstdcaparse.h"
|
||||
#include "gstflacparse.h"
|
||||
#include "gstmpegaudioparse.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
ret = gst_element_register (plugin, "aacparse",
|
||||
GST_RANK_PRIMARY + 1, GST_TYPE_AACPARSE);
|
||||
ret &= gst_element_register (plugin, "amrparse",
|
||||
GST_RANK_PRIMARY + 1, GST_TYPE_AMRPARSE);
|
||||
ret &= gst_element_register (plugin, "ac3parse",
|
||||
GST_RANK_PRIMARY + 1, GST_TYPE_AC3_PARSE);
|
||||
ret &= gst_element_register (plugin, "dcaparse",
|
||||
GST_RANK_PRIMARY + 1, GST_TYPE_DCA_PARSE);
|
||||
ret &= gst_element_register (plugin, "flacparse",
|
||||
GST_RANK_PRIMARY + 1, GST_TYPE_FLAC_PARSE);
|
||||
ret &= gst_element_register (plugin, "mpegaudioparse",
|
||||
GST_RANK_PRIMARY + 2, GST_TYPE_MPEG_AUDIO_PARSE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"audioparsersbad",
|
||||
"audioparsers",
|
||||
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
|
|
@ -154,15 +154,11 @@ check_PROGRAMS = \
|
|||
$(check_ofa) \
|
||||
$(check_timidity) \
|
||||
$(check_kate) \
|
||||
elements/aacparse \
|
||||
elements/ac3parse \
|
||||
elements/amrparse \
|
||||
elements/autoconvert \
|
||||
elements/autovideoconvert \
|
||||
elements/asfmux \
|
||||
elements/camerabin \
|
||||
elements/dataurisrc \
|
||||
elements/flacparse \
|
||||
elements/legacyresample \
|
||||
$(check_jifmux) \
|
||||
elements/jpegparse \
|
||||
|
@ -171,7 +167,6 @@ check_PROGRAMS = \
|
|||
elements/mxfdemux \
|
||||
elements/mxfmux \
|
||||
elements/id3mux \
|
||||
elements/mpegaudioparse \
|
||||
pipelines/mxf \
|
||||
$(check_mimic) \
|
||||
elements/rtpmux \
|
||||
|
@ -237,23 +232,6 @@ elements_rtpmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-0.10 $(GST_BASE_LIBS)
|
|||
elements_assrender_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||
elements_assrender_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-0.10 -lgstapp-0.10 $(GST_BASE_LIBS) $(LDADD)
|
||||
|
||||
# parser unit test convenience lib
|
||||
noinst_LTLIBRARIES = libparser.la
|
||||
libparser_la_SOURCES = elements/parser.c elements/parser.h
|
||||
libparser_la_CFLAGS = \
|
||||
-I$(top_srcdir)/tests/check \
|
||||
$(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS)
|
||||
|
||||
elements_aacparse_LDADD = libparser.la $(LDADD)
|
||||
|
||||
elements_ac3parse_LDADD = libparser.la $(LDADD)
|
||||
|
||||
elements_amrparse_LDADD = libparser.la $(LDADD)
|
||||
|
||||
elements_flacparse_LDADD = libparser.la $(LDADD)
|
||||
|
||||
elements_mpegaudioparse_LDADD = libparser.la $(LDADD)
|
||||
|
||||
EXTRA_DIST = gst-plugins-bad.supp
|
||||
|
||||
orc_cog_CFLAGS = $(ORC_CFLAGS)
|
||||
|
|
6
tests/check/elements/.gitignore
vendored
6
tests/check/elements/.gitignore
vendored
|
@ -1,7 +1,4 @@
|
|||
.dirstamp
|
||||
aacparse
|
||||
ac3parse
|
||||
amrparse
|
||||
asfmux
|
||||
assrender
|
||||
autoconvert
|
||||
|
@ -12,7 +9,6 @@ deinterleave
|
|||
dataurisrc
|
||||
faac
|
||||
faad
|
||||
flacparse
|
||||
gdpdepay
|
||||
gdppay
|
||||
id3mux
|
||||
|
@ -22,8 +18,8 @@ jifmux
|
|||
jpegparse
|
||||
kate
|
||||
legacyresample
|
||||
logoinsert
|
||||
mpeg2enc
|
||||
mpegaudioparse
|
||||
mplex
|
||||
mxfdemux
|
||||
mxfmux
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
/*
|
||||
* GStreamer
|
||||
*
|
||||
* unit test for aacparse
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include "parser.h"
|
||||
|
||||
#define SRC_CAPS_CDATA "audio/mpeg, framed=(boolean)false, codec_data=(buffer)1190"
|
||||
#define SRC_CAPS_TMPL "audio/mpeg, framed=(boolean)false, mpegversion=(int){2,4}"
|
||||
|
||||
#define SINK_CAPS \
|
||||
"audio/mpeg, framed=(boolean)true"
|
||||
#define SINK_CAPS_MPEG2 \
|
||||
"audio/mpeg, framed=(boolean)true, mpegversion=2, rate=48000, channels=2"
|
||||
#define SINK_CAPS_MPEG4 \
|
||||
"audio/mpeg, framed=(boolean)true, mpegversion=4, rate=96000, channels=2"
|
||||
#define SINK_CAPS_TMPL "audio/mpeg, framed=(boolean)true, mpegversion=(int){2,4}"
|
||||
|
||||
GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SINK_CAPS_TMPL)
|
||||
);
|
||||
|
||||
GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS_TMPL)
|
||||
);
|
||||
|
||||
/* some data */
|
||||
static guint8 adif_header[] = {
|
||||
'A', 'D', 'I', 'F'
|
||||
};
|
||||
|
||||
static guint8 adts_frame_mpeg2[] = {
|
||||
0xff, 0xf9, 0x4c, 0x80, 0x01, 0xff, 0xfc, 0x21, 0x10, 0xd3, 0x20, 0x0c,
|
||||
0x32, 0x00, 0xc7
|
||||
};
|
||||
|
||||
static guint8 adts_frame_mpeg4[] = {
|
||||
0xff, 0xf1, 0x4c, 0x80, 0x01, 0xff, 0xfc, 0x21, 0x10, 0xd3, 0x20, 0x0c,
|
||||
0x32, 0x00, 0xc7
|
||||
};
|
||||
|
||||
static guint8 garbage_frame[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
/*
|
||||
* Test if the parser pushes data with ADIF header properly and detects the
|
||||
* stream to MPEG4 properly.
|
||||
*/
|
||||
GST_START_TEST (test_parse_adif_normal)
|
||||
{
|
||||
GstParserTest ptest;
|
||||
|
||||
/* ADIF header */
|
||||
gst_parser_test_init (&ptest, adif_header, sizeof (adif_header), 1);
|
||||
/* well, no garbage, followed by random data */
|
||||
ptest.series[2].size = 100;
|
||||
ptest.series[2].num = 3;
|
||||
/* and we do not really expect output frames */
|
||||
ptest.framed = FALSE;
|
||||
/* Check that the negotiated caps are as expected */
|
||||
/* For ADIF parser assumes that data is always version 4 */
|
||||
ptest.sink_caps =
|
||||
gst_caps_from_string (SINK_CAPS_MPEG4 ", stream-format=(string)adif");
|
||||
|
||||
gst_parser_test_run (&ptest, NULL);
|
||||
|
||||
gst_caps_unref (ptest.sink_caps);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_adts_normal)
|
||||
{
|
||||
gst_parser_test_normal (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_adts_drain_single)
|
||||
{
|
||||
gst_parser_test_drain_single (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_adts_drain_garbage)
|
||||
{
|
||||
gst_parser_test_drain_garbage (adts_frame_mpeg4, sizeof (adts_frame_mpeg4),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_adts_split)
|
||||
{
|
||||
gst_parser_test_split (adts_frame_mpeg4, sizeof (adts_frame_mpeg4));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_adts_skip_garbage)
|
||||
{
|
||||
gst_parser_test_skip_garbage (adts_frame_mpeg4, sizeof (adts_frame_mpeg4),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
/*
|
||||
* Test if the src caps are set according to stream format (MPEG version).
|
||||
*/
|
||||
GST_START_TEST (test_parse_adts_detect_mpeg_version)
|
||||
{
|
||||
gst_parser_test_output_caps (adts_frame_mpeg2, sizeof (adts_frame_mpeg2),
|
||||
NULL, SINK_CAPS_MPEG2 ", stream-format=(string)adts");
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
#define structure_get_int(s,f) \
|
||||
(g_value_get_int(gst_structure_get_value(s,f)))
|
||||
#define fail_unless_structure_field_int_equals(s,field,num) \
|
||||
fail_unless_equals_int (structure_get_int(s,field), num)
|
||||
/*
|
||||
* Test if the parser handles raw stream and codec_data info properly.
|
||||
*/
|
||||
GST_START_TEST (test_parse_handle_codec_data)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GstStructure *s;
|
||||
const gchar *stream_format;
|
||||
|
||||
/* Push random data. It should get through since the parser should be
|
||||
* initialized because it got codec_data in the caps */
|
||||
caps = gst_parser_test_get_output_caps (NULL, 100, SRC_CAPS_CDATA);
|
||||
fail_unless (caps != NULL);
|
||||
|
||||
/* Check that the negotiated caps are as expected */
|
||||
/* When codec_data is present, parser assumes that data is version 4 */
|
||||
GST_LOG ("aac output caps: %" GST_PTR_FORMAT, caps);
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
fail_unless (gst_structure_has_name (s, "audio/mpeg"));
|
||||
fail_unless_structure_field_int_equals (s, "mpegversion", 4);
|
||||
fail_unless_structure_field_int_equals (s, "channels", 2);
|
||||
fail_unless_structure_field_int_equals (s, "rate", 48000);
|
||||
fail_unless (gst_structure_has_field (s, "codec_data"));
|
||||
fail_unless (gst_structure_has_field (s, "stream-format"));
|
||||
stream_format = gst_structure_get_string (s, "stream-format");
|
||||
fail_unless (strcmp (stream_format, "raw") == 0);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static Suite *
|
||||
aacparse_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("aacparse");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
/* ADIF tests */
|
||||
tcase_add_test (tc_chain, test_parse_adif_normal);
|
||||
|
||||
/* ADTS tests */
|
||||
tcase_add_test (tc_chain, test_parse_adts_normal);
|
||||
tcase_add_test (tc_chain, test_parse_adts_drain_single);
|
||||
tcase_add_test (tc_chain, test_parse_adts_drain_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_adts_split);
|
||||
tcase_add_test (tc_chain, test_parse_adts_skip_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_adts_detect_mpeg_version);
|
||||
|
||||
/* Other tests */
|
||||
tcase_add_test (tc_chain, test_parse_handle_codec_data);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Both push- and pull-modes need to be tested
|
||||
* * Pull-mode & EOS
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
|
||||
Suite *s = aacparse_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
/* init test context */
|
||||
ctx_factory = "aacparse";
|
||||
ctx_sink_template = &sinktemplate;
|
||||
ctx_src_template = &srctemplate;
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
|
||||
return nf;
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
/*
|
||||
* GStreamer
|
||||
*
|
||||
* unit test for ac3parse
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include "parser.h"
|
||||
|
||||
#define SRC_CAPS_TMPL "audio/x-ac3, framed=(boolean)false"
|
||||
#define SINK_CAPS_TMPL "audio/x-ac3, framed=(boolean)true"
|
||||
|
||||
GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SINK_CAPS_TMPL)
|
||||
);
|
||||
|
||||
GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS_TMPL)
|
||||
);
|
||||
|
||||
/* some data */
|
||||
|
||||
static guint8 ac3_frame[512] = {
|
||||
0x0b, 0x77, 0xb6, 0xa8, 0x10, 0x40, 0x2f, 0x84,
|
||||
0x29, 0xcb, 0xfe, 0x75, 0x7c, 0xf9, 0xf3, 0xe7,
|
||||
0xcf, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3, 0xe7, 0xcf,
|
||||
0x9f, 0x3e, 0x7c, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f,
|
||||
0x3e, 0x7c, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3e,
|
||||
0x7c, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3e, 0x7c,
|
||||
0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3e, 0x7c, 0xf9,
|
||||
0xf3, 0xe7, 0xcf, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3,
|
||||
0xe7, 0xcf, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3, 0xe7,
|
||||
0xcf, 0x9f, 0x3e, 0x32, 0xd3, 0xff, 0xc0, 0x06,
|
||||
0xe9, 0x40, 0x00, 0x6e, 0x94, 0x00, 0x06, 0xe9,
|
||||
0x40, 0x00, 0x6e, 0x94, 0x00, 0x06, 0xe9, 0x40,
|
||||
0x00, 0x6e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static guint8 garbage_frame[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_normal)
|
||||
{
|
||||
gst_parser_test_normal (ac3_frame, sizeof (ac3_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_drain_single)
|
||||
{
|
||||
gst_parser_test_drain_single (ac3_frame, sizeof (ac3_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_drain_garbage)
|
||||
{
|
||||
gst_parser_test_drain_garbage (ac3_frame, sizeof (ac3_frame),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_split)
|
||||
{
|
||||
gst_parser_test_split (ac3_frame, sizeof (ac3_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_skip_garbage)
|
||||
{
|
||||
gst_parser_test_skip_garbage (ac3_frame, sizeof (ac3_frame),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_detect_stream)
|
||||
{
|
||||
gst_parser_test_output_caps (ac3_frame, sizeof (ac3_frame),
|
||||
NULL, SINK_CAPS_TMPL ",channels=1,rate=48000");
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static Suite *
|
||||
ac3parse_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("ac3parse");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_parse_normal);
|
||||
tcase_add_test (tc_chain, test_parse_drain_single);
|
||||
tcase_add_test (tc_chain, test_parse_drain_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_split);
|
||||
tcase_add_test (tc_chain, test_parse_skip_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_detect_stream);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Both push- and pull-modes need to be tested
|
||||
* * Pull-mode & EOS
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
|
||||
Suite *s = ac3parse_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
/* init test context */
|
||||
ctx_factory = "ac3parse";
|
||||
ctx_sink_template = &sinktemplate;
|
||||
ctx_src_template = &srctemplate;
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
|
||||
return nf;
|
||||
}
|
|
@ -1,327 +0,0 @@
|
|||
/*
|
||||
* GStreamer
|
||||
*
|
||||
* unit test for amrparse
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include "parser.h"
|
||||
|
||||
#define SRC_CAPS_NB "audio/x-amr-nb-sh"
|
||||
#define SRC_CAPS_WB "audio/x-amr-wb-sh"
|
||||
#define SRC_CAPS_ANY "ANY"
|
||||
|
||||
#define SINK_CAPS_NB "audio/AMR, rate=8000 , channels=1"
|
||||
#define SINK_CAPS_WB "audio/AMR-WB, rate=16000 , channels=1"
|
||||
#define SINK_CAPS_ANY "ANY"
|
||||
|
||||
#define AMR_FRAME_DURATION (GST_SECOND/50)
|
||||
|
||||
static GstStaticPadTemplate sinktemplate_nb = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SINK_CAPS_NB)
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate sinktemplate_wb = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SINK_CAPS_WB)
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate srctemplate_nb = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS_NB)
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate srctemplate_wb = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS_WB)
|
||||
);
|
||||
|
||||
|
||||
/* some data */
|
||||
|
||||
static guint8 frame_data_nb[] = {
|
||||
0x0c, 0x56, 0x3c, 0x52, 0xe0, 0x61, 0xbc, 0x45,
|
||||
0x0f, 0x98, 0x2e, 0x01, 0x42, 0x02
|
||||
};
|
||||
|
||||
static guint8 frame_data_wb[] = {
|
||||
0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
|
||||
};
|
||||
|
||||
static guint8 frame_hdr_nb[] = {
|
||||
'#', '!', 'A', 'M', 'R', '\n'
|
||||
};
|
||||
|
||||
static guint8 frame_hdr_wb[] = {
|
||||
'#', '!', 'A', 'M', 'R', '-', 'W', 'B', '\n'
|
||||
};
|
||||
|
||||
static guint8 garbage_frame[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_nb_normal)
|
||||
{
|
||||
gst_parser_test_normal (frame_data_nb, sizeof (frame_data_nb));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_nb_drain_single)
|
||||
{
|
||||
gst_parser_test_drain_single (frame_data_nb, sizeof (frame_data_nb));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_nb_drain_garbage)
|
||||
{
|
||||
gst_parser_test_drain_garbage (frame_data_nb, sizeof (frame_data_nb),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_nb_split)
|
||||
{
|
||||
gst_parser_test_split (frame_data_nb, sizeof (frame_data_nb));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_nb_skip_garbage)
|
||||
{
|
||||
gst_parser_test_skip_garbage (frame_data_nb, sizeof (frame_data_nb),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_nb_detect_stream)
|
||||
{
|
||||
GstParserTest ptest;
|
||||
GstCaps *old_ctx_caps;
|
||||
|
||||
/* no input caps, override ctx */
|
||||
old_ctx_caps = ctx_input_caps;
|
||||
ctx_input_caps = NULL;
|
||||
|
||||
/* AMR-NB header */
|
||||
gst_parser_test_init (&ptest, frame_hdr_nb, sizeof (frame_hdr_nb), 1);
|
||||
/* well, no garbage, followed by real data */
|
||||
ptest.series[2].data = frame_data_nb;
|
||||
ptest.series[2].size = sizeof (frame_data_nb);
|
||||
ptest.series[2].num = 10;
|
||||
/* header gets dropped, so ... */
|
||||
/* buffer count will not match */
|
||||
ptest.framed = FALSE;
|
||||
/* total size a bit less */
|
||||
ptest.dropped = sizeof (frame_hdr_nb);
|
||||
|
||||
/* Check that the negotiated caps are as expected */
|
||||
ptest.sink_caps = gst_caps_from_string (SINK_CAPS_NB);
|
||||
|
||||
gst_parser_test_run (&ptest, NULL);
|
||||
|
||||
gst_caps_unref (ptest.sink_caps);
|
||||
|
||||
ctx_input_caps = old_ctx_caps;
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_wb_normal)
|
||||
{
|
||||
gst_parser_test_normal (frame_data_wb, sizeof (frame_data_wb));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_wb_drain_single)
|
||||
{
|
||||
gst_parser_test_drain_single (frame_data_wb, sizeof (frame_data_wb));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_wb_drain_garbage)
|
||||
{
|
||||
gst_parser_test_drain_garbage (frame_data_wb, sizeof (frame_data_wb),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_wb_split)
|
||||
{
|
||||
gst_parser_test_split (frame_data_wb, sizeof (frame_data_wb));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_wb_skip_garbage)
|
||||
{
|
||||
gst_parser_test_skip_garbage (frame_data_wb, sizeof (frame_data_wb),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_wb_detect_stream)
|
||||
{
|
||||
GstParserTest ptest;
|
||||
GstCaps *old_ctx_caps;
|
||||
|
||||
/* no input caps, override ctx */
|
||||
old_ctx_caps = ctx_input_caps;
|
||||
ctx_input_caps = NULL;
|
||||
|
||||
/* AMR-WB header */
|
||||
gst_parser_test_init (&ptest, frame_hdr_wb, sizeof (frame_hdr_wb), 1);
|
||||
/* well, no garbage, followed by real data */
|
||||
ptest.series[2].data = frame_data_wb;
|
||||
ptest.series[2].size = sizeof (frame_data_wb);
|
||||
ptest.series[2].num = 10;
|
||||
/* header gets dropped, so ... */
|
||||
/* buffer count will not match */
|
||||
ptest.framed = FALSE;
|
||||
/* total size a bit less */
|
||||
ptest.dropped = sizeof (frame_hdr_wb);
|
||||
|
||||
/* Check that the negotiated caps are as expected */
|
||||
ptest.sink_caps = gst_caps_from_string (SINK_CAPS_WB);
|
||||
|
||||
gst_parser_test_run (&ptest, NULL);
|
||||
|
||||
gst_caps_unref (ptest.sink_caps);
|
||||
|
||||
ctx_input_caps = old_ctx_caps;
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Create test suite.
|
||||
*/
|
||||
static Suite *
|
||||
amrnb_parse_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("amrwb_parse");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
/* AMR-NB tests */
|
||||
tcase_add_test (tc_chain, test_parse_nb_normal);
|
||||
tcase_add_test (tc_chain, test_parse_nb_drain_single);
|
||||
tcase_add_test (tc_chain, test_parse_nb_drain_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_nb_split);
|
||||
tcase_add_test (tc_chain, test_parse_nb_detect_stream);
|
||||
tcase_add_test (tc_chain, test_parse_nb_skip_garbage);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static Suite *
|
||||
amrwb_parse_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("amrnb_parse");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
/* AMR-WB tests */
|
||||
tcase_add_test (tc_chain, test_parse_wb_normal);
|
||||
tcase_add_test (tc_chain, test_parse_wb_drain_single);
|
||||
tcase_add_test (tc_chain, test_parse_wb_drain_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_wb_split);
|
||||
tcase_add_test (tc_chain, test_parse_wb_detect_stream);
|
||||
tcase_add_test (tc_chain, test_parse_wb_skip_garbage);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Both push- and pull-modes need to be tested
|
||||
* * Pull-mode & EOS
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
GstCaps *caps;
|
||||
|
||||
Suite *s = amrnb_parse_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
/* init test context */
|
||||
ctx_factory = "amrparse";
|
||||
ctx_sink_template = &sinktemplate_nb;
|
||||
ctx_src_template = &srctemplate_nb;
|
||||
caps = gst_caps_from_string (SRC_CAPS_NB);
|
||||
g_assert (caps);
|
||||
ctx_input_caps = caps;
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
s = amrwb_parse_suite ();
|
||||
sr = srunner_create (s);
|
||||
|
||||
ctx_sink_template = &sinktemplate_wb;
|
||||
ctx_src_template = &srctemplate_wb;
|
||||
caps = gst_caps_from_string (SRC_CAPS_WB);
|
||||
g_assert (caps);
|
||||
ctx_input_caps = caps;
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf += srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
return nf;
|
||||
}
|
|
@ -1,299 +0,0 @@
|
|||
/*
|
||||
* GStreamer
|
||||
*
|
||||
* unit test for flacparse
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include "parser.h"
|
||||
|
||||
#define SRC_CAPS_TMPL "audio/x-flac, framed=(boolean)false"
|
||||
#define SINK_CAPS_TMPL "audio/x-flac, framed=(boolean)true"
|
||||
|
||||
GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SINK_CAPS_TMPL)
|
||||
);
|
||||
|
||||
GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS_TMPL)
|
||||
);
|
||||
|
||||
/* some data */
|
||||
static guint8 streaminfo_header[] = {
|
||||
0x7f, 0x46, 0x4c, 0x41, 0x43, 0x01, 0x00, 0x00,
|
||||
0x02, 0x66, 0x4c, 0x61, 0x43, 0x00, 0x00, 0x00,
|
||||
0x22, 0x12, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0a, 0xc4, 0x40, 0xf0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static guint8 comment_header[] = {
|
||||
0x84, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static guint8 flac_frame[] = {
|
||||
0xff, 0xf8, 0xa9, 0x08, 0x00, 0x50, 0x18, 0x06,
|
||||
0x6a, 0x0c, 0xce, 0x13, 0x24, 0x19, 0x68, 0x00,
|
||||
0x46, 0x23, 0x08, 0xca, 0xcb, 0x58, 0x9c, 0x26,
|
||||
0x92, 0x30, 0xa6, 0x29, 0x8a, 0xca, 0xd1, 0x18,
|
||||
0xae, 0x26, 0x5c, 0x90, 0x60, 0xbf, 0x11, 0xad,
|
||||
0x43, 0x02, 0x06, 0x26, 0xbd, 0x35, 0xdd, 0xa3,
|
||||
0x11, 0xa6, 0x4d, 0x18, 0x8c, 0x9a, 0xe4, 0x62,
|
||||
0xd9, 0x23, 0x11, 0x8b, 0xcb, 0x56, 0x55, 0x45,
|
||||
0xc2, 0x18, 0x56, 0xa2, 0xe2, 0xe1, 0x18, 0x99,
|
||||
0x54, 0x98, 0x46, 0x4d, 0x08, 0x70, 0x9a, 0x64,
|
||||
0xc4, 0x18, 0x4f, 0x27, 0x64, 0x31, 0x66, 0x27,
|
||||
0x79, 0x19, 0x3c, 0x8c, 0x8c, 0xa3, 0x44, 0x18,
|
||||
0x23, 0xd2, 0x6b, 0x8b, 0x64, 0x8c, 0x21, 0x84,
|
||||
0xd6, 0x23, 0x13, 0x13, 0x2d, 0x44, 0xca, 0x5a,
|
||||
0x23, 0x09, 0x93, 0x25, 0x18, 0x10, 0x61, 0x38,
|
||||
0xb4, 0x60, 0x8f, 0x2c, 0x8d, 0x26, 0xb4, 0xc9,
|
||||
0xd9, 0x19, 0x19, 0x34, 0xd7, 0x31, 0x06, 0x10,
|
||||
0xc4, 0x30, 0x83, 0x17, 0xe2, 0x0c, 0x2c, 0xc4,
|
||||
0xc8, 0xc9, 0x3c, 0x5e, 0x93, 0x11, 0x8a, 0x62,
|
||||
0x64, 0x8c, 0x26, 0x23, 0x22, 0x30, 0x9a, 0x58,
|
||||
0x86, 0x04, 0x18, 0x4c, 0xab, 0x2b, 0x26, 0x5c,
|
||||
0x46, 0x88, 0xcb, 0xb1, 0x0d, 0x26, 0xbb, 0x5e,
|
||||
0x8c, 0xa7, 0x64, 0x31, 0x3d, 0x31, 0x06, 0x26,
|
||||
0x43, 0x17, 0xa3, 0x08, 0x61, 0x06, 0x17, 0xc4,
|
||||
0x62, 0xec, 0x4d, 0x4b, 0x2e, 0x2d, 0x4a, 0x94,
|
||||
0xa4, 0xc2, 0x31, 0x4c, 0x4c, 0x20, 0xc0, 0x83,
|
||||
0x14, 0x8c, 0x27, 0x8b, 0x31, 0x23, 0x2f, 0x23,
|
||||
0x11, 0x91, 0x94, 0x65, 0x1a, 0x20, 0xc2, 0x18,
|
||||
0x86, 0x51, 0x88, 0x62, 0x7c, 0x43, 0x2e, 0xa3,
|
||||
0x04, 0x18, 0x8c, 0x20, 0xc2, 0xf5, 0xaa, 0x94,
|
||||
0xc2, 0x31, 0x32, 0xd2, 0xb2, 0xa2, 0x30, 0xba,
|
||||
0x10, 0xc2, 0xb5, 0x89, 0xa5, 0x18, 0x10, 0x62,
|
||||
0x9a, 0x10, 0x61, 0x19, 0x72, 0x71, 0x1a, 0xb9,
|
||||
0x0c, 0x23, 0x46, 0x10, 0x62, 0x78, 0x81, 0x82,
|
||||
0x3d, 0x75, 0xea, 0x6b, 0x51, 0x8b, 0x61, 0x06,
|
||||
0x08, 0x62, 0x32, 0x5e, 0x84, 0x18, 0x27, 0x25,
|
||||
0xc2, 0x6a, 0x4b, 0x51, 0x31, 0x34, 0x5e, 0x29,
|
||||
0xa1, 0x3c, 0x4d, 0x26, 0x23, 0x10, 0xc2, 0x6b,
|
||||
0xb1, 0x0d, 0x11, 0xae, 0x46, 0x88, 0x31, 0x35,
|
||||
0xb1, 0x06, 0x08, 0x79, 0x7e, 0x4f, 0x53, 0x23,
|
||||
0x29, 0xa4, 0x30, 0x20, 0x30, 0x23, 0x5a, 0xb2,
|
||||
0xc8, 0x60, 0x9c, 0x93, 0x13, 0x17, 0x92, 0x98,
|
||||
0x46, 0x13, 0x54, 0x53, 0x08, 0xcb, 0x13, 0xa1,
|
||||
0x1a, 0x89, 0xe5, 0x46, 0x08, 0x18, 0x10, 0x30,
|
||||
0x9d, 0x68, 0xc2, 0x1c, 0x46, 0x46, 0xae, 0x62,
|
||||
0x1a, 0x46, 0x4e, 0x4d, 0x34, 0x8c, 0xbd, 0x26,
|
||||
0xc0, 0x40, 0x62, 0xc9, 0xa9, 0x31, 0x74, 0xa8,
|
||||
0x99, 0x52, 0xb0, 0x8c, 0xa9, 0x29, 0x84, 0x61,
|
||||
0x19, 0x54, 0x43, 0x02, 0x06, 0x04, 0x32, 0xe5,
|
||||
0x18, 0x21, 0x91, 0x8b, 0xf2, 0xcc, 0x10, 0x30,
|
||||
0x8e, 0x23, 0xc4, 0x76, 0x43, 0x08, 0x30, 0x83,
|
||||
0x08, 0x62, 0x6c, 0x4e, 0xe2, 0x35, 0x96, 0xd0,
|
||||
0x8e, 0x89, 0x97, 0x42, 0x18, 0x91, 0x84, 0x61,
|
||||
0x3c, 0x26, 0xa5, 0x2c, 0x4e, 0x17, 0x94, 0xb8,
|
||||
0xb5, 0xa4, 0xcb, 0x88, 0xc9, 0x84, 0x18, 0xb9,
|
||||
0x84, 0x19, 0x23, 0x2d, 0xa4, 0x64, 0x62, 0x18,
|
||||
0x86, 0x53, 0x93, 0xcb, 0x30, 0x8f, 0x2f, 0x93,
|
||||
0x55, 0xc4, 0xd7, 0x08, 0x62, 0xb8, 0x46, 0x84,
|
||||
0x68, 0xa3, 0x02, 0xaf, 0x33
|
||||
};
|
||||
|
||||
static guint8 garbage_frame[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_flac_normal)
|
||||
{
|
||||
gst_parser_test_normal (flac_frame, sizeof (flac_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_flac_drain_single)
|
||||
{
|
||||
gst_parser_test_drain_single (flac_frame, sizeof (flac_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_flac_drain_garbage)
|
||||
{
|
||||
/* We always output the after frame garbage too because we
|
||||
* have no way of detecting it
|
||||
*/
|
||||
#if 0
|
||||
gst_parser_test_drain_garbage (flac_frame, sizeof (flac_frame),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
#endif
|
||||
guint8 frame[sizeof (flac_frame) + sizeof (garbage_frame)];
|
||||
|
||||
memcpy (frame, flac_frame, sizeof (flac_frame));
|
||||
memcpy (frame + sizeof (flac_frame), garbage_frame, sizeof (garbage_frame));
|
||||
|
||||
gst_parser_test_drain_single (frame, sizeof (frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_flac_split)
|
||||
{
|
||||
gst_parser_test_split (flac_frame, sizeof (flac_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_flac_skip_garbage)
|
||||
{
|
||||
/* We always include the garbage into the frame because
|
||||
* we have no easy way for finding the real end of the
|
||||
* frame. The decoder will later skip the garbage
|
||||
*/
|
||||
#if 0
|
||||
gst_parser_test_skip_garbage (flac_frame, sizeof (flac_frame),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
#endif
|
||||
guint8 frame[sizeof (flac_frame) + sizeof (garbage_frame)];
|
||||
|
||||
memcpy (frame, flac_frame, sizeof (flac_frame));
|
||||
memcpy (frame + sizeof (flac_frame), garbage_frame, sizeof (garbage_frame));
|
||||
|
||||
gst_parser_test_normal (frame, sizeof (frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
#define structure_get_int(s,f) \
|
||||
(g_value_get_int(gst_structure_get_value(s,f)))
|
||||
#define fail_unless_structure_field_int_equals(s,field,num) \
|
||||
fail_unless_equals_int (structure_get_int(s,field), num)
|
||||
/*
|
||||
* Test if the parser handles raw stream and codec_data info properly.
|
||||
*/
|
||||
GST_START_TEST (test_parse_flac_detect_stream)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GstStructure *s;
|
||||
const GValue *streamheader;
|
||||
GArray *bufarr;
|
||||
gint i;
|
||||
|
||||
/* Push random data. It should get through since the parser should be
|
||||
* initialized because it got codec_data in the caps */
|
||||
caps = gst_parser_test_get_output_caps (flac_frame, sizeof (flac_frame),
|
||||
SRC_CAPS_TMPL);
|
||||
fail_unless (caps != NULL);
|
||||
|
||||
/* Check that the negotiated caps are as expected */
|
||||
/* When codec_data is present, parser assumes that data is version 4 */
|
||||
GST_LOG ("flac output caps: %" GST_PTR_FORMAT, caps);
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
fail_unless (gst_structure_has_name (s, "audio/x-flac"));
|
||||
fail_unless_structure_field_int_equals (s, "channels", 1);
|
||||
fail_unless_structure_field_int_equals (s, "rate", 44100);
|
||||
fail_unless (gst_structure_has_field (s, "streamheader"));
|
||||
streamheader = gst_structure_get_value (s, "streamheader");
|
||||
fail_unless (G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY);
|
||||
bufarr = g_value_peek_pointer (streamheader);
|
||||
fail_unless (bufarr->len == 2);
|
||||
for (i = 0; i < bufarr->len; i++) {
|
||||
GstBuffer *buf;
|
||||
GValue *bufval = &g_array_index (bufarr, GValue, i);
|
||||
|
||||
fail_unless (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER);
|
||||
buf = g_value_peek_pointer (bufval);
|
||||
if (i == 0) {
|
||||
fail_unless (GST_BUFFER_SIZE (buf) == sizeof (streaminfo_header));
|
||||
fail_unless (memcmp (buf, streaminfo_header, sizeof (streaminfo_header)));
|
||||
} else if (i == 1) {
|
||||
fail_unless (GST_BUFFER_SIZE (buf) == sizeof (comment_header));
|
||||
fail_unless (memcmp (buf, comment_header, sizeof (comment_header)));
|
||||
}
|
||||
}
|
||||
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static Suite *
|
||||
flacparse_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("flacparse");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_parse_flac_normal);
|
||||
tcase_add_test (tc_chain, test_parse_flac_drain_single);
|
||||
tcase_add_test (tc_chain, test_parse_flac_drain_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_flac_split);
|
||||
tcase_add_test (tc_chain, test_parse_flac_skip_garbage);
|
||||
|
||||
/* Other tests */
|
||||
tcase_add_test (tc_chain, test_parse_flac_detect_stream);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Both push- and pull-modes need to be tested
|
||||
* * Pull-mode & EOS
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
|
||||
Suite *s = flacparse_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
/* init test context */
|
||||
ctx_factory = "flacparse";
|
||||
ctx_sink_template = &sinktemplate;
|
||||
ctx_src_template = &srctemplate;
|
||||
ctx_discard = 3;
|
||||
ctx_headers[0].data = streaminfo_header;
|
||||
ctx_headers[0].size = sizeof (streaminfo_header);
|
||||
ctx_headers[1].data = comment_header;
|
||||
ctx_headers[1].size = sizeof (comment_header);
|
||||
/* custom offsets, and ts always repeatedly 0 */
|
||||
ctx_no_metadata = TRUE;
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
|
||||
return nf;
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* GStreamer
|
||||
*
|
||||
* unit test for aacparse
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include "parser.h"
|
||||
|
||||
#define SRC_CAPS_TMPL "audio/mpeg, parsed=(boolean)false, mpegversion=(int)1"
|
||||
#define SINK_CAPS_TMPL "audio/mpeg, parsed=(boolean)true, mpegversion=(int)1"
|
||||
|
||||
GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SINK_CAPS_TMPL)
|
||||
);
|
||||
|
||||
GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS_TMPL)
|
||||
);
|
||||
|
||||
const gchar *factory = "aacparse";
|
||||
|
||||
/* some data */
|
||||
static guint8 mp3_frame[384] = {
|
||||
0xff, 0xfb, 0x94, 0xc4, 0xff, 0x83, 0xc0, 0x00,
|
||||
0x01, 0xa4, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
|
||||
0x34, 0x80, 0x00, 0x00, 0x04, 0x00,
|
||||
};
|
||||
|
||||
static guint8 garbage_frame[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_normal)
|
||||
{
|
||||
gst_parser_test_normal (mp3_frame, sizeof (mp3_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_drain_single)
|
||||
{
|
||||
gst_parser_test_drain_single (mp3_frame, sizeof (mp3_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_drain_garbage)
|
||||
{
|
||||
gst_parser_test_drain_garbage (mp3_frame, sizeof (mp3_frame),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_split)
|
||||
{
|
||||
gst_parser_test_split (mp3_frame, sizeof (mp3_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_parse_skip_garbage)
|
||||
{
|
||||
gst_parser_test_skip_garbage (mp3_frame, sizeof (mp3_frame),
|
||||
garbage_frame, sizeof (garbage_frame));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
#define structure_get_int(s,f) \
|
||||
(g_value_get_int(gst_structure_get_value(s,f)))
|
||||
#define fail_unless_structure_field_int_equals(s,field,num) \
|
||||
fail_unless_equals_int (structure_get_int(s,field), num)
|
||||
|
||||
GST_START_TEST (test_parse_detect_stream)
|
||||
{
|
||||
GstStructure *s;
|
||||
GstCaps *caps;
|
||||
|
||||
caps = gst_parser_test_get_output_caps (mp3_frame, sizeof (mp3_frame), NULL);
|
||||
|
||||
fail_unless (caps != NULL);
|
||||
|
||||
GST_LOG ("mpegaudio output caps: %" GST_PTR_FORMAT, caps);
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
fail_unless (gst_structure_has_name (s, "audio/mpeg"));
|
||||
fail_unless_structure_field_int_equals (s, "mpegversion", 1);
|
||||
fail_unless_structure_field_int_equals (s, "layer", 3);
|
||||
fail_unless_structure_field_int_equals (s, "channels", 1);
|
||||
fail_unless_structure_field_int_equals (s, "rate", 48000);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static Suite *
|
||||
mpegaudioparse_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("mpegaudioparse");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_parse_normal);
|
||||
tcase_add_test (tc_chain, test_parse_drain_single);
|
||||
tcase_add_test (tc_chain, test_parse_drain_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_split);
|
||||
tcase_add_test (tc_chain, test_parse_skip_garbage);
|
||||
tcase_add_test (tc_chain, test_parse_detect_stream);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Both push- and pull-modes need to be tested
|
||||
* * Pull-mode & EOS
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
|
||||
Suite *s = mpegaudioparse_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
/* init test context */
|
||||
ctx_factory = "mpegaudioparse";
|
||||
ctx_sink_template = &sinktemplate;
|
||||
ctx_src_template = &srctemplate;
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
|
||||
return nf;
|
||||
}
|
Loading…
Reference in a new issue